How to send emails using Go(golang).

How to send emails using Go(golang).

Send emails using the go standard library (net/smtp).

Prerequisites

To follow along, you will need to have golang installed locally

Step 1: Create a project and configure it

Create a project directory, and in that type the following commands.

go mod init send_mail

We are going to use the GoDotEnv package to load the .env file

go get github.com/joho/godotenv

In the root directory create a go file called main.go

package main

import (
    "fmt"
    "log"
    "net/smtp"
    "os"

    "github.com/joho/godotenv"
)

func main() {
    err := godotenv.Load(".env")

    if err != nil {
        log.Fatalf("Error loading .env file")
    }

    _, ok := os.LookupEnv("MAIL_USER")

    if !ok {
        log.Fatalf("SMTP username not set")
    }

    _, ok = os.LookupEnv("MAIL_PASSWORD")

    if !ok {
        log.Fatalf("SMTP password not set")
    }

    _, ok = os.LookupEnv("MAIL_HOST")

    if !ok {
        log.Fatalf("SMTP host not set")
    }

    _, ok = os.LookupEnv("MAIL_PORT")

    if !ok {
        log.Fatalf("SMTP port not set")
    }

    response := sendMail("walkerbrownmason@outlook.com", "This is a test mail", "Hello walker what are you up to")
    fmt.Println(response)
    os.Exit(0)
}

This is just a boiler plate to start our project.

Step 2: Create the sendMail function

To send mail using the net/smtp standard library, you first need to authenticate with your smtp server using the smtp.PlainAuth function.

func sendMail(to, subject, body string) Response {

    username := os.Getenv("MAIL_USER")
    password := os.Getenv("MAIL_PASSWORD")
    host := os.Getenv("MAIL_HOST")
    port := os.Getenv("MAIL_PORT")
    auth := smtp.PlainAuth("", username, password, host)
}

After authenticating with your smtp server, you can now send an email with the smtp.SendMail function. Append the following code to oursendMail function.

err := smtp.SendMail(host+":"+port, auth, username, []string{to}, []byte("Subject: "+subject+"\n"+body))

    if err != nil {
        log.Fatalf(err.Error())
    }

    return Response{
        status:  200,
        message: "Mail sent",
    }

The sendMail function now becomes:

func sendMail(to, subject, body string) Response {

    username := os.Getenv("MAIL_USER")
    password := os.Getenv("MAIL_PASSWORD")
    host := os.Getenv("MAIL_HOST")
    port := os.Getenv("MAIL_PORT")
    auth := smtp.PlainAuth("", username, password, host)

    err := smtp.SendMail(host+":"+port, auth, username, []string{to}, []byte("Subject: "+subject+"\n"+body))

    if err != nil {
        log.Fatalf(err.Error())
    }

    return Response{
        status:  200,
        message: "Mail sent",
    }
}

Let's now define the Response struct.

type Response struct {
    status  int
    message string
}

Step 3: Run the script using the go run command

go run main.go

You should get a response like

{200 Mail sent}

NB: For some reasons the net/smtp library only works with gmail smtp on port 587. I would love to get feedback on how to configure it to work with other smtps.