When building a backend service, you’ll often need to implement email sending functionality in your web app. You’ve come to the right place if you’re looking to send emails in your Golang app.
From simple user account notifications to complex marketing campaigns, ensuring your application can send and receive email notifications is crucial.
In this guide, I’ll walk you through how to send emails in Go. We’ll cover both SMTP and API-based sending methods.
Understanding Email Sending Options in Go
When you’re working with email in Go, there are two main ways to send messages:
SMTP: Direct Sending
SMTP (Simple Mail Transfer Protocol) is the traditional way of sending emails. With Go’s standard net/smtp
package, you can connect directly to an SMTP server and send emails without needing third-party SDKs.
Email APIs: Simplified Integration
Transactional email service providers like SendLayer, Postmark, and Amazon SES offer an abstraction over raw SMTP, making it easier to manage things like authentication, retries, and analytics.
If you’re looking for a suitable transactional email provider to use with Golang, SendLayer is a great choice.
One feature that makes SendLayer stand out is its domain reputation protection. It automatically creates a subdomain to handle email activities. This essentially means your actual domain is protected from any potential email deliverability issues.
SendLayer also offers a free trial that allows you to send up to 200 emails, and a flexible pricing plan starting at $5 monthly. This makes it an affordable choice whether you’re a hobby developer looking to test during development or you need to scale up and send thousands of emails from your Golang web application.
How to Send Email in Golang With SMTP and API
Prerequisites
Below are some requirements you’ll need to follow along with this guide:
- Golang is installed on your machine.
- Basic programming knowledge
- SMTP credentials. I’m using SendLayer for this tutorial, but you can use any provider you’d like.
If you’re using SendLayer, you’ll need to authorize your sending domain. This step is essential to improve your site’s email deliverability.
Setting Up a Golang Project
You’ll need to install Golang on your machine if you haven’t done it already. Go supports Windows, macOS, and Linux. The installation steps may vary a little depending on your operating system.
Their official documentation includes specific instructions for various Operating Systems on how to install Golang.
After installing Go, open a terminal window and create a new directory using the command:
mkdir email-test
Next, navigate into the directory and create a new file:
cd email-test && touch sendEmail.go
Then open the folder in your favorite code editor (I’m using VS Code).
Once you’ve opened it, you’re ready to start sending emails in Go.
Method 1: Send Emails With SMTP in Golang
There is a built-in Golang email package (net/smtp
) for sending emails that work for basic emails. However, the library isn’t ideal as it doesn’t allow features like attaching files to emails.
For this tutorial, we’ll use the Gomail SMTP package, a third-party library to handle email sending.
Sending Plain Text Emails
To get started, you’ll need to install the package on your machine. To do so, open a terminal window, then navigate to your Go project directory and run the command:
go get gopkg.in/mail.v2
Once the installation completes, open the sendEmail.go
file we created earlier and paste the snippet below:
package main
import (
"fmt"
"gopkg.in/gomail.v2"
)
func main() {
// Initializing the email method
msg := gomail.NewMessage()
// Setting email headers
msg.SetHeader("From", "[email protected]")
msg.SetHeader("To", "[email protected]")
msg.SetHeader("Subject", "Email Sent From Go With SendLayer SMTP!")
// Setting Email body
msg.SetBody("text/plain", "This is an example of a plain text message sent using Go")
// Setting up SMTP dialer
dialer := gomail.NewDialer("smtp.sendlayer.net", 587, "your-smtp-username", "your-smtp-password")
// Sending the email
if err := dialer.DialAndSend(msg); err != nil {
fmt.Println("Error:", err)
panic(err)
} else {
fmt.Println("Email sent successfully")
}
}
Here is what the code does:
First, we import the gomail package we just installed. The gomail.NewMessage()
line initializes the email module.
Then we configure the email headers using the msg.SetHeader()
method. This is where you’ll specify the sender, recipient, and email subject.
Next, we use the msg.SetBody()
method to write the actual message. It accepts 2 parameters: the message format and the message string.
After configuring the email headers and body, we use the gomail.NewDialer()
module to set the SMTP server settings. You’ll need to replace the details in the snippet above with your actual SMTP server details.
I’m using SendLayer SMTP credentials for this tutorial. You can retrieve your SendLayer SMTP details from your account dashboard by navigating to the Settings » SMTP Credentials screen.

After that, be sure to replace the dummy details with your actual username and password.
Finally, we use the dialer.DialAndSend()
method to send the email message. The method accepts one parameter, which is the message object. In our example, the parameter is stored in the msg
variable.
Send HTML Emails in Go
Gomail also allows you to send HTML emails. To do so, you’ll need to specify the format as HTML in the msg.SetBody()
line of code.
msg.SetBody("text/html", `
<html>
<body>
<h2>This is a Test Email from Golang</h2>
<p><b>Hello!</b> This test HTML email was sent using SendLayer SMTP server</p>
</body>
</html>
`)
Email best practices often suggest having a plain text version of your email message. This will serve as a fallback for email clients that do not support HTML emails.
You can implement this by using the AddAlternative()
module. Here is an updated version of our initial code.
package main
import (
"fmt"
"gopkg.in/gomail.v2"
)
func main() {
// Initializing the email method
msg := gomail.NewMessage()
// Setting email headers
msg.SetHeader("From", "[email protected]")
msg.SetHeader("To", "[email protected]")
msg.SetHeader("Subject", "Email Sent From Go With SendLayer SMTP!")
// Setting Email body
msg.SetBody("text/plain", "This is an example of a plain text message sent using Go")
// HTML Email version
msg.AddAlternative("text/html", `
<html>
<body>
<h2>This is a Test Email from Golang</h2>
<p><b>Hello!</b> This test HTML email was sent using SendLayer SMTP server</p>
</body>
</html>
`)
// Setting up SMTP dialer
dialer := gomail.NewDialer("smtp.sendlayer.net", 587, "your-smtp-username", "your-smtp-password")
// Sending the email
if err := dialer.DialAndSend(msg); err != nil {
fmt.Println("Error:", err)
panic(err)
} else {
fmt.Println("Email sent successfully")
}
}
Send Emails To Multiple Recipients
To send emails to multiple recipients, simply append the recipient email address(es) to the recipient header:
// Setting email headers
msg.SetHeader("From", "[email protected]")
msg.SetHeader("To", "[email protected]", "[email protected]", "[email protected]")
msg.SetHeader("Subject", "Email Sent From Go With SendLayer SMTP!")
Including Attachments to Emails in Golang
You can also include attachment files in your email messages using the .Attach()
method. This method accepts one parameter, which is a string containing the path to the attachment file. Here’s an updated version of the code:
package main
import (
"fmt"
"gopkg.in/gomail.v2"
)
func main() {
// Initializing the email method
msg := gomail.NewMessage()
// Setting email headers
msg.SetHeader("From", "[email protected]")
msg.SetHeader("To", "[email protected]")
msg.SetHeader("Subject", "Email Sent From Go With SendLayer SMTP!")
// HTML Email
msg.SetBody("text/html", `
<html>
<body>
<h2>This is a Test Email from Golang</h2>
<p><b>Hello!</b> This test HTML email was sent using SendLayer SMTP server</p>
</body>
</html>
`)
// Golang send email with attachment function
msg.Attach("path/to/file.pdf")
// Setting up SMTP dialer
dialer := gomail.NewDialer("smtp.sendlayer.net", 587, "your-smtp-username", "your-smtp-password")
// Sending the email
if err := dialer.DialAndSend(msg); err != nil {
fmt.Println("Error:", err)
panic(err)
} else {
fmt.Println("Email sent successfully")
}
}
Send a Test Email in Go
After creating your email function, testing it to ensure it’s properly configured is important. To do so, simply run the .go
file you created in a terminal window:
go run sendEmail.go
You should see a success notification in the terminal. Go ahead and check the email inbox of the recipient you specified.

Congratulations! You’ve successfully built an email notification system in your Golang application.
Method 2: Send Email in Go via API
Sending emails in Golang through an SMTP server works well for smaller projects. However, it is less secure and slower when compared to using an API-based email provider. Using an API-based service is also much faster, especially when you need to send bulk emails.
I’ll show you how to send emails using the SendLayer email API as an example.
Getting Started With SendLayer API
To send an email using SendLayer API, you’ll need 3 parameters:
- URL: This is the API endpoint for sending emails. For SendLayer, this endpoint is available at
https://console.sendlayer.com/api/v1/email
- Headers: This is where you’ll define the format for the request and also authenticate your connection
- Payload: This is a JSON object containing the email data.
Pro Tip: Our developer site includes details on how to send emails using SendLayer email API. It includes sample code snippets for popular programming languages as well including Golang.
Send Email With SendLayer API
Before getting started, you’ll need to retrieve your SendLayer API key. To get your API key, log in to your SendLayer account. Once you’re logged in, click the Settings menu and select the API Keys tab.

Then click the copy icon next to Default API key to copy it.

After retrieving your API key, copy and paste the code below into your email API file.
package main
import (
"fmt"
"strings"
"net/http"
"io/ioutil"
)
func main() {
url := "https://console.sendlayer.com/api/v1/email"
apiKey := "your-sendlayer-api-key"
payload := strings.NewReader(`{
"From": {
"name": "Paulie Paloma",
"email": "[email protected]"
},
"To": [
{
"name": "Recipient",
"email": "[email protected]"
}
],
"Subject": "Golang email template testing",
"ContentType": "HTML",
"HTMLContent": "<html><body><p>This is a test email sent with the <a href=\"https://sendlayer.com\">SendLayer</a> API!</p></body></html>",
}`)
req, err := http.NewRequest("POST", url, payload)
if err != nil {
fmt.Printf("Error creating request: %v\n", err)
return
}
req.Header.Add("Authorization", "Bearer " + apiKey)
req.Header.Add("Content-Type", "application/json")
res, err := http.DefaultClient.Do(req)
if err != nil {
fmt.Printf("Error making request: %v\n", err)
return
}
defer res.Body.Close()
body, err := ioutil.ReadAll(res.Body)
if err != nil {
fmt.Printf("Error reading response: %v\n", err)
return
}
fmt.Println(res)
fmt.Println(string(body))
}
Code breakdown
In the code above, we first define the API URL and API key variables. Be sure to paste your SendLayer API key as the value for the apiKey
variable.
Next, we use the strings.NewReader()
module to specify the JSON payload for the API request. This payload variable contains details about the email, like the sender and recipient email addresses. You’ll need to update these values to match your specific email data.
The http.NewRequest()
method is where we define the request parameters. It accepts 3 arguments: request type, URL, and payload.
We use the req.Header.Add()
method to specify the request headers. The method that runs the API request is the http.DefaultClient.Do()
function, which accepts the request object as a parameter.
When you run the file, you’ll see the MessageID printed in the console if the email is successfully sent. You should also receive an email in the recipient’s email inbox.

Send Emails to Multiple Recipients
SendLayer API also supports sending emails to multiple users, including “CC” and “BCC” email addresses. To do so, update the payload variable to include the email addresses you’d like to add.
payload := strings.NewReader(`{
"From": {
"name": "Paulie Paloma",
"email": "[email protected]"
},
"To": [
{
"name": "Recipient 1",
"email": "[email protected]"
},
{
"name": "Recipient 2",
"email": "[email protected]"
}
],
"CC": [
{
"name": "Pattie Paloma CC",
"email": "[email protected]"
}
],
"BCC": [
{
"name": "Pattie Paloma BCC",
"email": "[email protected]"
}
],
],
"Subject": "This is the email subject",
"ContentType": "HTML",
"HTMLContent": "<html><body><p>This is a test email sent with the <a href=\"https://sendlayer.com\">SendLayer</a> API!</p></body></html>",
}`)
Send Email With Attachments
You can also send emails with file attachments. However, before sending the email, you’ll need to convert the attachment file to a base64 string. Here’s how to do it:
First, let’s create a function that’ll read the attachment file and return its base64 string. Start by including the following import statement in your email file:
import (
"fmt"
"strings"
"net/http"
"io/ioutil"
"encoding/base64"
"log"
"os"
"io"
)
After that, add the snippet below to create the function:
func readAttachment(filePath string) string {
// Open attachment file
file, err := os.Open(filePath)
if err != nil {
log.Fatalf("Failed to open file: %v", err)
}
defer file.Close()
// Read Attachment content
fileData, err := io.ReadAll(file)
if err != nil {
log.Fatalf("Failed to read file: %v", err)
}
// Encode attachment file to base64
encodedFileData := base64.StdEncoding.EncodeToString(fileData)
return encodedFileData
}
The readAttachment()
function accepts one parameter, which is a string containing the file path. We use the os.Open()
method to open the file, and then use the io.ReadAll()
method to access the file details.
Finally, we use the base64.StdEncoding.EncodeToString()
line to convert the file to base64 string and return the encoded file.
Now, we’ll use the function within the main()
function.
func main() {
url := "https://console.sendlayer.com/api/v1/email"
apiKey := "your-sendlayer-api-key"
// Read and encode the attachment
encodedAttachment := readAttachment("path/to/file.pdf")
payload := strings.NewReader(`{
"From": {
"name": "Paulie Paloma",
"email": "[email protected]"
},
"To": [
{
"name": "Recipient",
"email": "[email protected]"
}
],
"Subject": "This is the email subject",
"ContentType": "HTML",
"HTMLContent": "<html><body><p>This is a test email sent with the <a href=\"https://sendlayer.com\">SendLayer</a> API!</p></body></html>",
"Attachments": [
{
"Content": "` + encodedAttachment + `",
"Type": "application/pdf",
"Filename": "file.pdf",
"Disposition": "attachment",
"ContentId": "0"
}
]
}`)
req, err := http.NewRequest("POST", url, payload)
if err != nil {
fmt.Printf("Error creating request: %v\n", err)
return
}
req.Header.Add("Authorization", "Bearer " + apiKey)
req.Header.Add("Content-Type", "application/json")
res, err := http.DefaultClient.Do(req)
if err != nil {
fmt.Printf("Error making request: %v\n", err)
return
}
defer res.Body.Close()
body, err := ioutil.ReadAll(res.Body)
if err != nil {
fmt.Printf("Error reading response: %v\n", err)
return
}
fmt.Println(res)
fmt.Println(string(body))
}
First, we call the readAttachment()
function and specify the path to the attachment. The value is then stored in the encodedAttachment
variable.
Next, within the payload
object, we add an "Attachments"
list and fill out the parameters. The "Content"
field is where we specify the base64-encoded string of the attachment file. You’ll also need to specify the "Type"
and "Filename"
fields.
You can add multiple attachment objects if you’d like to the “Attachments"
list within the payload variable.
After updating the snippet, be sure to test your email module to ensure it is working. Here’s what the email looks like with a file attached.

FAQs – Send Email in Golang
These are answers to some of the top questions we see about sending emails with Golang.
How do I handle email bounces and delivery failures when sending emails in Go?
With SMTP, you need to process bounce messages manually. However, email APIs often provide tools and webhooks for managing bounces and delivery failures. Check our tutorial to learn more about managing webhooks in SendLayer.
Can I send emails asynchronously in Go to improve application performance?
Yes! You can use goroutines and channels to send emails asynchronously in the background.
What are the advantages of using an API-based service over SMTP in Go?
Using a transactional email service improves deliverability. Some providers also offer built-in analytics and handle bounces. They scale better than direct SMTP for high-volume sending. You can check our guide for details about the different sending methods (SMTP vs APIs).
Can I send email in Golang without SMTP?
Yes! You can connect your Golang app to an API-based email service like SendLayer. Then send your emails through the API.
That’s it! Now you know how to send emails in Golang with SMTP or API.
Next, would you like to learn about the various types of email bounce? Check out our tutorial on hard bounce vs soft bounce emails for more information.