How to Send Emails in Go using SMTP or Email API

On October 08, 2024
15min read
Piotr Malek Technical Content Writer @ Mailtrap
Ivan Djuric, an author at Mailtrap
Ivan Djuric Technical Content Writer @Mailtrap
This is a featured image for an article on how to send emails with Go

In this tutorial, I’ll show you how to send emails by leveraging various Golang packages with an SMTP service or automating the process with an email API. Of course, I’ll also Go over testing in the end so we can make sure all of this code works properly. So, stick around!

The code snippets I provide in this article are compatible with Go 1.13 and above.

Send emails using Gomail

Gomail is a community-driven package for Go that truly is, as its creators say, “simple and efficient.” 

It supports the following:

  • SSL / TLS
  • Attachments
  • Embedded images
  • Text/HTML templates
  • Automatic encoding of special characters

Additionally, it’s important to mention that Gomail must be paired with an external SMTP server.

So now I’ll provide you with the code you can use with any SMTP, whether it’s a dedicated provider or your Gmail account even. Later on though, I’ll leverage Gomail with Mailtrap SMTP so you can see it in action.

First, install the package itself with the following command:

go get gopkg.in/mail.v2

Then, once installed, you can use the following code snippet to start sending emails:

package main

import (
    "fmt"
    gomail "gopkg.in/mail.v2"
)

func main() {
    // Create a new message
    message := gomail.NewMessage()

    // Set email headers
    message.SetHeader("From", "youremail@email.com")
    message.SetHeader("To", "recipient1@email.com")
    message.SetHeader("Subject", "Hello from the Mailtrap team")

    // Set email body
`    message.SetBody("text/plain", "This is the Test Body")

    // Set up the SMTP dialer
    dialer := gomail.NewDialer("live.smtp.mailtrap.io", 587, "api", "1a2b3c4d5e6f7g")

    // Send the email
    if err := dialer.DialAndSend(message); err != nil {
        fmt.Println("Error:", err)
        panic(err)
    } else {
        fmt.Println("Email sent successfully!")
    }
}

Notes:

  • With this snippet, you can plain-text emails. However, I’ll cover other sending cases like HTML emails, emails with attachments, as well as asynchronous and bulk sending later in the article.
  • Besides being featured on the official Go website, I should probably mention that Gomail also has a rich documentation on GitHub.

Send emails using mail package

The mail package is a package for sending emails from applications built in Google App Engine. Additionally, the package uses Google’s API to send emails, so there’s no need to leverage an external SMTP server.

And here’s a code snippet for you to see how it works, which you can also paste into your main configuration file to start sending emails:

package main

import (
	"google.golang.org/appengine"
	"google.golang.org/appengine/mail"
	"net/http"
)

func sendEmail(w http.ResponseWriter, r *http.Request) {
	// Get the App Engine context from the request
	ctx := appengine.NewContext(r)

	// Create a new email message
	msg := &mail.Message{
		Sender:  "example@example.com",
		To:      []string{"recipient@example.com"},
		Subject: "Hello from App Engine!",
		Body:    "This is a plain text email.",
		HTMLBody: "<html><body><p>This is an <b>HTML</b> email.</p></body></html>",
	}

	// Send the email
	if err := mail.Send(ctx, msg); err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	w.Write([]byte("Email sent successfully!"))
}

func main() {
	http.HandleFunc("/send", sendEmail)
	appengine.Main()  // Starts the App Engine app
}

As simple as it gets, doesn’t it? However, I must note down the two of the mail package’s biggest limitations. Namely, they include:

  • Lack of capabilities – The mail package isn’t as great as Gomail, considering it only has basic features such as sending plain-text/HTML emails and attachments.
  • Sending quotas – Google App Engine imposes specific sending quotas to ensure service quality and prevent spam. 

Send emails in Go using net/smtp package

The net/smtp package is a native way to send emails in Golang. However, it’s been frozen by the Go language team since it lacked basic features such as:

  • TLS support
  • MIME attachments
  • DKIM signing
  • Email templates
  • Authentication mechanisms
  • Email queueing

As you can see, the net/smtp package is quite bare bones. Nonetheless, you can use it to send super simple, plain-text notifications. 

So, let me show you how the net/smtp works (paired with Mailtrap SMTP, of course) for explanatory purposes. ⬇️

The main function of the package is SendMail, and the syntax is quite simple: 

​​func SendMail(addr string, a Auth, from string, to []string, msg []byte) error

And, as it’s native to Golang, you don’t have to install net/smtp. You can simply copy/paste the following code snippet into your main application file (e.g., main.go):

package main

import (
    "log"
    "net/smtp"
)

func main() {
    // Authentication for Mailtrap
    auth := smtp.PlainAuth("", "mailtrap.foo@gmail.com", "your_password", "live.smtp.mailtrap.io")

    // Set the recipient
    to := []string{"mailtrap.foo@gmail.com"}

    // Create the message
    msg := []byte("To: mailtrap.foo@gmail.com\r\n" +
        "Subject: Why aren't you using Mailtrap yet?\r\n" +
        "\r\n" +
        "Here's the space for our great sales pitch\r\n")

    // Send the email
    err := smtp.SendMail("live.smtp.mailtrap.io:587", auth, "api", to, msg)
    if err != nil {
        log.Fatal(err)
    }
}

To authenticate, you can either use:

  • Plain authentication

The basic method of authorizing an email client to act on your behalf (used in the code sample above). You provide your username and password, which are encoded with the basic base64 method. In Golang, this method is represented by the PlainAuth function and comes in the following shape:

func PlainAuth(identity, username, password, host string) Auth 
  • Cram-MD5 authentication

Cram-MD5 is a little more sophisticated. Using the provided credentials, it utilizes the challenge-response mechanism to authenticate with a server. It adds an extra layer of security, and although it comes with plenty of weaknesses, it’s still a more secure option than PlainAuth. The CRAMMD5Auth function comes with the following syntax:

func CRAMMD5Auth(username, secret string) Auth

The “secret” used is either the user’s password or a hash of it.

Send emails in Go using SMTP

Now, it’s time to pair Gomail with Mailtrap SMTP, which has high deliverability rates by design and is super straightforward to configure.

Start by creating a free account and verifying your email-sending domain. Don’t worry; this takes ~5 minutes, and you can follow our Knowledge Base article step-by-step. 👀

Next, to find the SMTP credentials, simply navigate to Sending Domains Integration and choose the Transactional Stream for now (I’ll go over the Bulk Stream a bit later).

Then, all you have to do is copy your credentials into the following code snippet, which should go into a file named main.go or similar, and start sending plain-text emails:

package main

import (
    "fmt"
    gomail "gopkg.in/mail.v2"
)

func main() {
    // Create a new message
    message := gomail.NewMessage()

    // Set email headers
    message.SetHeader("From", "youremail@email.com")
    message.SetHeader("To", "recipient1@email.com")
    message.SetHeader("Subject", "Hello from the Mailtrap team")

    // Set email body
`    message.SetBody("text/plain", "This is the Test Body")

    // Set up the SMTP dialer
    dialer := gomail.NewDialer("live.smtp.mailtrap.io", 587, "api", "1a2b3c4d5e6f7g")

    // Send the email
    if err := dialer.DialAndSend(message); err != nil {
        fmt.Println("Error:", err)
        panic(err)
    } else {
        fmt.Println("Email sent successfully!")
    }
}

Send HTML email

Want to send HTML emails and spice it up a bit? I got you! 🌶️

Simply change the MIME type from “text/plain” to “text/html”, just like so:

package main

import (
    "fmt"
    gomail "gopkg.in/mail.v2"
)

func main() {
    // Create a new message
    message := gomail.NewMessage()

    // Set email headers
    message.SetHeader("From", "youremail@email.com")
    message.SetHeader("To", "recipient1@email.com")
    message.SetHeader("Subject", "Hello from the Mailtrap team")

    // Set the plain-text version of the email
    message.SetBody("text/plain", "This is a Test Email\n\nHello!\nThis is a test email with plain-text formatting.\nThanks,\nMailtrap")

    // Set the HTML version of the email
    message.AddAlternative("text/html", `
        <html>
            <body>
                <h1>This is a Test Email</h1>
                <p><b>Hello!</b> This is a test email with HTML formatting.</p>
                <p>Thanks,<br>Mailtrap</p>
            </body>
        </html>
    `)

    // Set up the SMTP dialer
    dialer := gomail.NewDialer("live.smtp.mailtrap.io", 587, "api", "1a2b3c4d5e6f7g")

    // Send the email
    if err := dialer.DialAndSend(message); err != nil {
        fmt.Println("Error:", err)
        panic(err)
    } else {
        fmt.Println("HTML Email sent successfully with a plain-text alternative!")
    }
}

Note: Following the best practices, I’ve made sure to add the plain-text variant of the email (in case some of your recipients’ can’t render HTML properly) and I’ve also enclosed the HTML in backticks (`) for multiline string support. 

Send email to multiple recipients

Sending emails to multiple recipients is also easy, as all you have to do is add their email addresses in the “To” field under the SetHeader method.

For example:

package main

import (
    "fmt"
    gomail "gopkg.in/mail.v2"
)

func main() {
    // Create a new message
    message := gomail.NewMessage()

    // Set email headers with multiple recipients
    message.SetHeader("From", "youremail@email.com")
    message.SetHeader("To", "abc@gmail.com", "xyz@gmail.com", "123@gmail.com")  // Multiple recipients
    message.SetHeader("Subject", "Test Email to Multiple Recipients")

    // Set email body
    message.SetBody("text/html", `
        <html>
            <body>
                <h1>This is a Test Email</h1>
                <p><b>Hello!</b> This is a test email sent to multiple recipients.</p>
                <p>Thanks,<br>Mailtrap</p>
            </body>
        </html>
    `)

    // Set up the SMTP mail server dialer
    dialer := gomail.NewDialer("live.smtp.mailtrap.io", 587, "api", "1a2b3c4d5e6f7g")

    // Send the email
    if err := dialer.DialAndSend(message); err != nil {
        fmt.Println("Error:", err)
        panic(err)
    } else {
        fmt.Println("Email sent successfully to multiple recipients!")
    }
}

Reminder: An easily overlooked detail is the commas, so don’t forget to insert them to separate the addresses.

Send email with attachments

In Go, we can simply move the image/document to our project folder and specify its name under the Attach method.

Check it out, I’ve added a line of code with a comment on top:

package main

import (
    "fmt"
    gomail "gopkg.in/mail.v2"
)

func main() {
    // Create a new message
    message := gomail.NewMessage()

    // Set email headers
    message.SetHeader("From", "youremail@email.com")
    message.SetHeader("To", "abc@gmail.com")
    message.SetHeader("Subject", "Test Email with Attachment")

    // Set email body
    message.SetBody("text/html", `
        <html>
            <body>
                <h1>This is a Test Email</h1>
                <p><b>Hello!</b> Please find the attachment below.</p>
                <p>Thanks,<br>Mailtrap</p>
            </body>
        </html>
    `)

    // Add attachments
    message.Attach("/invoice#1.pdf")

    // Set up the SMTP dialer
    dialer := gomail.NewDialer("live.smtp.mailtrap.io", 587, "api", "1a2b3c4d5e6f7g")

    // Send the email
    if err := dialer.DialAndSend(message); err != nil {
        fmt.Println("Error:", err)
        panic(err)
    } else {
        fmt.Println("Email sent successfully with attachments!")
    }
}

Send email with embedded image

For displaying images inline rather than as attachments, we can lean on the Embed() method. With it, we can easily attach an image directly within the email body.

Here’s an example:

package main

import (
    "fmt"
    gomail "gopkg.in/mail.v2"
)

func main() {
    // Create a new message
    message := gomail.NewMessage()

    // Set email headers
    message.SetHeader("From", "youremail@email.com")
    message.SetHeader("To", "abc@gmail.com")
    message.SetHeader("Subject", "Test Email with Embedded Image")

    // Embed image and set email body to reference the embedded image
    message.Embed("/path/to/image.jpg", "image123")

    message.SetBody("text/html", `
        <html>
            <body>
                <h1>Test Email with Embedded Image</h1>
                <p><b>Hello!</b> This email contains an embedded image:</p>
                <img src="cid:image123" alt="Embedded Image">
                <p>Thanks,<br>Mailtrap</p>
            </body>
        </html>
    `)

    // Set up the SMTP dialer
    dialer := gomail.NewDialer("live.smtp.mailtrap.io", 587, "api", "1a2b3c4d5e6f7g")

    // Send the email
    if err := dialer.DialAndSend(message); err != nil {
        fmt.Println("Error:", err)
        panic(err)
    } else {
        fmt.Println("Email sent successfully with an embedded image!")
    }
}

Asynchronous email sending

To send emails asynchronously with Gomail, we have to use goroutines, a lightweight thread managed by Go. With goroutines, we can simply call go sendAsyncEmail(recipient, dialer) and send emails concurrently. 

Check it out:

package main

import (
    "fmt"
    "gopkg.in/mail.v2"
    "time"
)

func sendAsyncEmail(recipient string, dialer *mail.Dialer) {
    // Create a new message
    message := mail.NewMessage()

    // Set email headers
    message.SetHeader("From", "your.email@example.com")
    message.SetHeader("To", recipient)
    message.SetHeader("Subject", "Async Email Example")
    message.SetBody("text/plain", "This is an asynchronously sent email!")

    // Send email
    if err := dialer.DialAndSend(message); err != nil {
        fmt.Println("Error sending email:", err)
    } else {
        fmt.Println("Email sent to:", recipient)
    }
}

func main() {
    // Configure the SMTP dialer
    dialer := mail.NewDialer("smtp.mailtrap.io", 587, "username", "password")

    // List of recipients
    recipients := []string{"recipient1@example.com", "recipient2@example.com", "recipient3@example.com"}

    // Loop over the recipient list and send emails asynchronously
    for _, recipient := range recipients {
        go sendAsyncEmail(recipient, dialer) // Send email in a separate goroutine
    }

    // Wait for all emails to be sent
    time.Sleep(5 * time.Second) // This gives enough time for goroutines to finish before exiting
}

Send bulk email

With goroutines, we can kill two birds with one stone—both asynchronous and bulk email sending with just one call! 

Feel free to use this code:

package main

import (
    "fmt"
    "gopkg.in/mail.v2"
    "sync"
    "time"
)

func sendAsyncEmail(recipient string, dialer *mail.Dialer, wg *sync.WaitGroup, throttle <-chan time.Time) {
    defer wg.Done() // Notify that this goroutine is done

    // Wait for the throttle to allow sending
    <-throttle

    // Create a new message
    message := mail.NewMessage()

    // Set email headers
    message.SetHeader("From", "your.email@example.com")
    message.SetHeader("To", recipient)
    message.SetHeader("Subject", "Async Email Example")
    message.SetBody("text/plain", "This is an asynchronously sent email!")

    // Send email (you could implement retry logic here, but be careful not to affect deliverability with too many retried attempts)
    if err := dialer.DialAndSend(message); err != nil {
        fmt.Println("Error sending email:", err)
    } else {
        fmt.Println("Email sent to:", recipient)
    }
}

func main() {
    // Configure the SMTP dialer
    dialer := mail.NewDialer("bulk.smtp.mailtrap.io", 587, "username", "password")

    // List of recipients (e.g., bulk list)
    recipients := []string{"recipient1@example.com", "recipient2@example.com", "recipient3@example.com"}

    // Create a WaitGroup to wait for all emails to be sent
    var wg sync.WaitGroup

    // Throttle to control the rate of email sending (1 email per second)
    throttle := time.Tick(1 * time.Second)

    // Loop over the recipient list and send emails asynchronously
    for _, recipient := range recipients {
        wg.Add(1)
        go sendAsyncEmail(recipient, dialer, &wg, throttle) // Send email in a separate goroutine
    }

    // Wait for all goroutines to finish
    wg.Wait()
    fmt.Println("All emails have been sent.")
}

As you can notice, I’ve used bulk.smtp.mailtrap.io, host name of Mailtrap Bulk Stream, which I mentioned previously in the article. Mailtrap Bulk Stream is designed to handle large amounts of emails without a stutter, all the while keeping your deliverability high.

Send emails in Go using email API

Prefer having an automated sending process? If so, I suggest using Mailtrap’s very own Email API. The API is regularly maintained and updated by a team of developers, which means you can sit back and enjoy stress-free coding.

And here’s how you can integrate the API with your project and start sending emails:

  • Create a free Mailtrap account.
  • Verify your domain and update DNS records.
  • Navigate to the Sending Domains Integration and choose the Transactional Stream for now.
  • Click on API and select Go underneath Code Samples.

Then, to send a plain-text email, copy the snippet below into your main.go file:

package main

import (

"bytes"

"fmt"

"io"

"log"

"net/http"

"time"

)

func main() {

// Mailtrap account config

token := "<secret_token>"

httpHost := "https://send.api.mailtrap.io/api/send"

// Message body

message := []byte(`{"from":{"email":"john.doe@your.domain"},

"to":[{"email":"kate.doe@example.com"}],

"subject":"Why aren’t you using Mailtrap yet?",

"text":"Here’s the space for your great sales pitch"}`)

// Set up request

request, err := http.NewRequest(http.MethodPost, httpHost, bytes.NewBuffer(message))

if err != nil {

log.Fatal(err)

}

// Set required headers

request.Header.Set("Content-Type", "application/json")

request.Header.Set("Authorization", "Bearer "+token)

// Send request

client := http.Client{Timeout: 5 * time.Second}

res, err := client.Do(request)

if err != nil {

log.Fatal(err)

}

defer res.Body.Close()

body, err := io.ReadAll(res.Body)

if err != nil {

log.Fatal(err)

}

fmt.Println(string(body))

}

All there’s left to do is start the server and make requests, which you can do by running main.go.

Important: make sure to replace the placeholders like token and from:email with your actual Mailtrap credentials.

Send HTML email

To send an HTML email, simply modify the code snippet from the previous chapter with the following:

Here’s how the message body would look like in that case:

message := []byte(`{
    "from":{"email":"john.doe@your.domain"},
    "to":[{"email":"kate.doe@example.com"}],
    "subject":"Why aren’t you using Mailtrap yet?",
    "text":"Here’s the space for your great sales pitch",
    "html":"<strong>Here’s the space for your great sales pitch</strong>"
}`)

As it’s a standard industry practice, I’ve also made sure to include text along with HTML, so it can be rendered by recipients who can’t open HTML.

Send email to multiple recipients

Sending emails to multiple recipients with Go and Mailtrap API is super easy, as all you have to do is add email addresses to the to field.

Check it out in the dissected message body:

message := []byte(`{
    "from":{"email":"john.doe@your.domain"},
    "to":[
        {"email":"kate.doe@example.com"},
        {"email":"alex.doe@example.com"},
        {"email":"lisa.doe@example.com"}
    ],
    "subject":"Why aren’t you using Mailtrap yet?",
    "text":"Here’s the space for your great sales pitch",
    "html":"<strong>Here’s the space for your great sales pitch</strong>"
}`)

Send email with attachments

To add attachments, add the attachments field under html and specify the following, as in the code snippet below:

import (
	"bytes"
	"encoding/base64"
	"fmt"
	"io"
	"log"
	"net/http"
	"os"
	"time"
)

// within main function
	// Open the file
	file, err := os.Open("attachment.txt")
	if err != nil {
		log.Fatalf("Failed to open file: %v", err)
	}
	defer file.Close()

	// Read all contents of the file
	fileData, err := io.ReadAll(file)
	if err != nil {
		log.Fatalf("Failed to read file: %v", err)
	}

	// Encode the file data to base64
	encodedFileData := base64.StdEncoding.EncodeToString(fileData)

message := []byte(`{
    "from": { "email": "john.doe@your.domain" },
    "to": [
        { "email": "kate.doe@example.com" }
    ],
    "subject": "Here’s your attached file!",
    "text": "Check out the attached file.",
    "html": "<p>Check out the attached <strong>file</strong>.</p>",
    "attachments": [
        {
          "filename": "example.pdf",
          "content": "` + encodedFileData + `",
          "type": "application/pdf",
          "disposition": "attachment"
        }
    ]
}`)

Friendly reminder: Don’t forget to properly base64-encode your file before adding it to the content field. For this, you could perhaps use Go’s encoding/base64 package.

Asynchronous email sending

To send emails asynchronously, we’ll use goroutines’ go sendEmailAsync(token, message) and time.Sleep(5 * time.Second) functions.

Here’s a code example you can use:

package main

import (
    "bytes"
    "fmt"
    "io"
    "log"
    "net/http"
    "time"
)

// Function to send email asynchronously
func sendEmailAsync(token string, message []byte) {
    httpHost := "https://send.api.mailtrap.io/api/send"

    // Set up request
    request, err := http.NewRequest(http.MethodPost, httpHost, bytes.NewBuffer(message))
    if err != nil {
        log.Fatal(err)
    }

    // Set required headers
    request.Header.Set("Content-Type", "application/json")
    request.Header.Set("Authorization", "Bearer "+token)

    // Send request asynchronously
    client := http.Client{Timeout: 5 * time.Second}
    res, err := client.Do(request)
    if err != nil {
        log.Fatal(err)
    }
    defer res.Body.Close()

    body, err := io.ReadAll(res.Body)
    if err != nil {
        log.Fatal(err)
    }

    fmt.Println(string(body))
}

func main() {
    // Mailtrap account config
    token := "<secret_token>"

    // Message body
    message := []byte(`{
        "from":{"email":"john.doe@your.domain"},
        "to":[{"email":"kate.doe@example.com"}],
        "subject":"Why aren’t you using Mailtrap yet?",
        "text":"Here’s the space for your great sales pitch"
    }`)

    // Run email sending in a goroutine (asynchronously)
    go sendEmailAsync(token, message)

    // Wait for the goroutine to complete (simulate with sleep)
    time.Sleep(5 * time.Second) // Adjust time if necessary

    fmt.Println("Email sent asynchronously!")
}

Code breakdown:

  • The go keyword starts a new goroutine thread and allows the sendEmailAsync function to run asynchronously.
  • time.Sleep(5 * time.Second) stimulates waiting for the email to be sent before the program exits. You can adjust it depending on how long you expect the request to take.

Send bulk email

To send bulk email with Go, we’ll modify the code snippet from the previous chapter and use goroutines again.

Have a look:

package main

import (
	"fmt"
	"sync"
	"time"

	"gopkg.in/mail.v2"
)

func sendAsyncEmail(recipient string, dialer *mail.Dialer, wg *sync.WaitGroup, throttle <-chan time.Time) {
	defer wg.Done() // Notify that this goroutine is done

	// Wait for the throttle to allow sending
	<-throttle

	// Create a new message
	message := mail.NewMessage()

	// Set email headers
	message.SetHeader("From", "your.email@your.domain")
	message.SetHeader("To", recipient)
	message.SetHeader("Subject", "Async Email Example")
	message.SetBody("text/plain", "This is an asynchronously sent email!")

	// Send email
	if err := dialer.DialAndSend(message); err != nil {
		fmt.Println("Error sending email:", err)
	} else {
		fmt.Println("Email sent to:", recipient)
	}
}

func main() {
	// Configure the SMTP dialer
	dialer := mail.NewDialer("bulk.smtp.mailtrap.io", 587, "username", "password")

	// List of recipients (e.g., bulk list)
	recipients := []string{"abc@gmail.com", "xyz@gmail.com"}

	// Create a WaitGroup to wait for all emails to be sent
	var wg sync.WaitGroup

	// Throttle to control the rate of email sending (1 email per second)
	throttle := time.Tick(1 * time.Second)

	// Loop over the recipient list and send emails asynchronously
	for _, recipient := range recipients {
		wg.Add(1)
		go sendAsyncEmail(recipient, dialer, &wg, throttle) // Send email in a separate goroutine
	}

	// Wait for all goroutines to finish
	wg.Wait()
	fmt.Println("All emails have been sent.")
}

What changed:

  • recipients – The function that allows you to add more recipients to your bulk email list easier.
  • sync.WaitGroup – With this method, the program will wait for all email-sending goroutines to complete before it exits.
  • Personalized messages – Each address in the “to” field will receive a personalized message.
  • bulk.smtp.mailtrap.io – As in the SMTP chapter, I’ve used the Mailtrap Bulk Stream again here for its ability to handle large volumes of emails.

Moreover, it’s worth mentioning that Mailtrap’s email API is bulk-aware, allowing you to send marketing emails on top of transactional with high deliverability and, more importantly, without any additional costs.

Test email and email testing on staging

Okay, you’ve written down all this code, and you might be asking yourself, “Now what?” The answer is certainly not “moving straight to production.” If you want to ship your app properly, you must ensure critical functionality such as email-sending works as intended.

Among other things, this includes making sure that:

  • Your code is impeccable and your emails based on HTML/CSS designs are being rendered correctly across different browsers and clients.
  • Your emails will pass the spam filters and reach the destination, that is, the recipients’ main inbox folder.
  • Your domain isn’t getting blacklisted.

The perfect solution for all of the above is Mailtrap Email Testing, another inseparable part of Mailtrap Email Delivery Platform.

With Mailtrap Email Testing you can inspect the HTML/CSS of your emails and easily spot and fix any faulty lines of code. By doing this, you ensure your messages look the way you intend them to, whether they’re opened in Outlook, Thunderbird, or even on an iPhone.

Moreover, you can check both HTML and text versions of your emails, inspect the source code, and more.

Also, if you have Email Templates, you can design, edit, and host them on Mailtrap Email Delivery Platform. Then, easily test them with our API before moving to production once you’re ready to start sending.

After you make sure everything looks good, you can move on to checking your spam score. If you keep it below 5, you can prevent a significant amount of potential email deliverability issues your project/app could face when you move it to production.

All said and done, let me show you how easy to set up Mailtrap Email Testing is!

SMTP

Start by creating a free Mailtrap account and then navigate to Email Testing Inboxes Integration. Once there, simply copy the provided fake SMTP credentials into your Go configuration.

Depending on which package you settled for, your code should look something like this:

  • Gomail 
dialer := gomail.NewDialer("sandbox.smtp.mailtrap.io", 587, "ae54a7713017172", "1a2b3c4d5e6f7g")
  • net/smtp

Underneath func main () simply copy the following:

username := "your-username-here"
password := "your-password-here"
smtpHost := "sandbox.smtp.mailtrap.io"

API

To integrate Mailtrap API for testing, automation, and testing automated sequences, you can use the following code snippet:

package main

import (
	"fmt"
	"strings"
	"net/http"
	"io/ioutil"
)

func main() {

	url := "https://sandbox.api.mailtrap.io/api/send/2804194"
	method := "POST"

	payload := strings.NewReader(`{\"from\":{\"email\":\"hello@example.com\",\"name\":\"Mailtrap Test\"},\"to\":[{\"email\":\"demo@mailtrap.io\"}],\"subject\":\"You are awesome!\",\"text\":\"Congrats for sending test email with Mailtrap!\",\"category\":\"Integration Test\"}`)

	client := &http.Client {
	}
	req, err := http.NewRequest(method, url, payload)

	if err != nil {
		fmt.Println(err)
		return
	}
	req.Header.Add("Authorization", "Bearer 0e0****************************as9")
	req.Header.Add("Content-Type", "application/json")

	res, err := client.Do(req)
	if err != nil {
		fmt.Println(err)
		return
	}
	defer res.Body.Close()

	body, err := ioutil.ReadAll(res.Body)
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println(string(body))
}

For more information, feel free to consult the official Mailtrap API docs.

Ready, Set, Go

That’s that folks! 

I’ve covered the most popular and efficient approaches to sending emails in Go—from leveraging various packages and SMTP to using an email API. 

So now that you have everything you need for a rock-solid email-sending cycle in Go, it’s time to start hitting the inbox bullseye: main folder! 🎯

Article by Piotr Malek Technical Content Writer @ Mailtrap
Ivan Djuric, an author at Mailtrap
Article by Ivan Djuric Technical Content Writer @Mailtrap

I’m a Technical Content Writer with 5 years of background covering email-related topics in tight collaboration with software engineers and email marketers. I just love to research and share actionable insights with you about email sending, testing, deliverability improvements, and more. Happy to be your guide in the world of emails!