Skip to main content

Command Palette

Search for a command to run...

How to send emails using Go(golang).

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

Published
2 min read
How to send emails using Go(golang).

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.

K
Kenneth4y ago

I think the reason you can't communiate off of port 587 is because of Go, not gmail. The go doc for the PlainAuth function says:

func PlainAuth(identity, username, password, host string) Auth
    ...
    PlainAuth will only send the credentials if the connection is using TLS or
    is connected to localhost. Otherwise authentication will fail with an error,
    without sending the credentials.

587 is the standard outgoing port for TLS communications via SMTP.

1