In this guide, we will discuss how you can send emails using the SMTP package in Go. For testing, we will use a locally hosted SMTP server using MailSlurper.
Golang SMTP
The SMTP package is a sub-package of the Golang net package. It implements high-level functionalities for working with SMTP protocol.
Let’s learn how to send email using the SMTP package.
The SMTP package provides a SendMail() method that allows you to send email to the specified address.
The function syntax is as shown:
The function accepts the address of the SMTP server as a string, an authentication mechanism, email address to send from, the email address to send to, and the email message as the parameters.
The email message should start with the header, a blank line, and the email body. You should end each line of the message with CRLF characters, allowing compliance with RFC 822 email style.
The following code shows a simple example of using the SendMail function to send an email.
import (
"fmt"
"log"
"net/smtp"
)
const (
USERNAME = "linuxhint"
PASSWD = "password"
HOST = "localhost"
)
func main() {
from := "[email protected]"
to := []string{
"[email protected]",
}
msg := []byte("From: [email protected]\r\n" +
"To: [email protected]" +
"Subject: Golang testing mail\r\n" +
"Email Body: Welcome to Go!\r\n")
auth := smtp.PlainAuth("", USERNAME, PASSWD, HOST)
err := smtp.SendMail(HOST+":25", auth, from, to, msg)
if err != nil {
log.Fatal(err)
}
fmt.Println("Mail sent successfully!")
}
In the example above, we start by importing the required packages. We then specify the required variables. In our example, we set the username, password, and the host.
In the main function, we set the sender of the email and the receiver using the from and to variables, respectively.
Next comes the email body, we use RFC 822 style to construct the message. Note that each line is separated with CRLF characters.
Next, we build the authentication using the PlainAuth method. The function takes the identity, username, password and host and gears a plain auth mechanism with the server. The function then returns to an auth object.
Finally, we send the email using the SendMail function passing the address, auth object, sender, recipient and the message as the arguments.
MailSlurper Auth Method
If you run the code above on MailSlurper, the server will return an error as below and close the connection.
2022/02/02 02:52:39 smtp: server doesn't support AUTH
exit status 1
You can solve this by using a custom SendMail function. An example code is as shown below:
import (
"encoding/base64"
"fmt"
"log"
"net/smtp"
"strings"
)
const (
USERNAME = "linuxhint"
PASSWD = "password"
HOST = "localhost"
)
func main() {
from := "[email protected]"
to := []string{
"[email protected]",
}
msg := []byte("Email Body: Welcome to Go!\r\n")
err := SendMail(HOST+":2500", from, "Golang testing email", string(msg), to)
if err != nil {
log.Fatal(err)
}
fmt.Println("Mail Sent Successfully!")
}
func SendMail(addr, from, subject, body string, to []string) error {
r := strings.NewReplacer("\r\n", "", "\r", "", "\n", "", "%0a", "", "%0d", "")
c, err := smtp.Dial(addr)
if err != nil {
return err
}
defer c.Close()
if err = c.Mail(r.Replace(from)); err != nil {
return err
}
for i := range to {
to[i] = r.Replace(to[i])
if err = c.Rcpt(to[i]); err != nil {
return err
}
}
w, err := c.Data()
if err != nil {
return err
}
msg := "To: " + strings.Join(to, ",") + "\r\n" +
"From: " + from + "\r\n" +
"Subject: " + subject + "\r\n" +
"Content-Type: text/html; charset="UTF-8"\r\n" +
"Content-Transfer-Encoding: base64\r\n" +
"\r\n" + base64.StdEncoding.EncodeToString([]byte(body))
_, err = w.Write([]byte(msg))
if err != nil {
return err
}
err = w.Close()
if err != nil {
return err
}
return c.Quit()
}
Golang Send Mail – Carbon Copy
You can also send emails to multiple users using carbon copy and blind carbon copy. CC recipients will be visible to all.
We can do this using the code as below:
import (
"fmt"
"log"
"net/smtp"
"strings"
)
type Mail struct {
Sender string
To []string
CC []string
Bcc []string
Subject string
Body string
}
func main() {
sender := "[email protected]"
to := []string{
"[email protected]",
"[email protected]",
"[email protected]",
}
cc := []string{
"[email protected]",
"[email protected]",
}
username := "linuxhint"
passwd := "password"
host := "localhost"
subject := "Golang Mail Test"
body := "Message body"
req := Mail{
Sender: sender,
To: to,
CC: cc,
Subject: subject,
Body: body,
}
msg := ComposeMsg(req)
auth := smtp.PlainAuth("", username, passwd, host)
err := smtp.SendMail(host+":2500", auth, sender, to, []byte(msg))
if err != nil {
log.Fatal(err)
}
fmt.Println("Message Sent successfully!")
}
// construct message based on the cc
func ComposeMsg(mail Mail) string {
// empty string
msg := ""
// set sender
msg += fmt.Sprintf("From: %s\r\n", mail.Sender)
// if more than 1 recipient
if len(mail.To) > 0 {
msg += fmt.Sprintf("Cc: %s\r\n", strings.Join(mail.CC, ";"))
}
// add subject
msg += fmt.Sprintf("Subject: %s\r\n", mail.Subject)
// add mail body
msg += fmt.Sprintf("Body: %s\r\n", mail.Body)
return msg
}
The above code will send the emails to the specified recipients using the SMTP protocol.
Closing
In this guide, we explored the basics of using the SMTP package in Go to send emails to one or more users. Check the documentation to learn more.