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.
Comments
Join the discussionI 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.
