Several things to note: The SendMail function will automatically use TLS encryption if the server supports it — any major SMTP server will do so. Also, SendMail doesn’t itself offer support for DKIM authentication or MIME attachments. Luckily, for the latter there’s an alternative method that works just fine. More about that later!
Server infrastructure for SendMail function
As you’ve probably noticed by now, we’ve already tried to connect to mail.maitrap.io several times, so that is obviously our Golang mail server. This is because we need to use a mail server, or at least something that resembles one, to handle sending email. You can compose the most effective email ever written, but without proper infrastructure, it won’t even reach the first handshake.
One approach would be to use a regular Linux machine to work as a server. It would use a command-line utility called sendmail
to handle email sending. This post gives a detailed clarification on what the process looks like.
Another approach to consider would be to use a dedicated server for SMTP transmission. Using Postfix and Ubuntu, you could easily set up the architecture and send the first emails in minutes.
Note, however, that if you’ve never used this server for sending emails, you will suffer because of its lack of reputation. As we’ve discussed in another article, receiving servers pay a lot of attention to the reputation of a server that’s trying to send them an email. If they don’t know it or, even worse, know it as sending rather spammy content, they’re likely to discard the message or, at best, place it in a spam folder. Use more “experienced” servers or utilize those provided by 3rd party providers.
If you’re on a budget and need to send only occasional messages, you can utilize Google’s SMTP server that comes with free Gmail or a paid Google Apps account. See this article for more detailed instructions on how to set it up. Google allows users to send up to 99 emails per day. The limit resets 24 hours after it’s reached.
If you need something bigger but don’t want to set up your own server, you’ll want to look into integrating the API of a transactional email provider. More about that below.
Finally, chances are you want to send emails that are a bit more sophisticated than a typical “hello world.” Go supports HTML templates with its html/template
package so you can build a beautiful, responsive template to send to your users. There’s a number of tutorials on building templates in Go; in our opinion, this one seems really interesting.
Other configurations
Sending an email to a single recipient is fairly simple, but what if we have several people in mind? Luckily, this is also really easy to set up. Let’s cut a piece of the code from the previous paragraph and focus solely on the message headers and body:
to := []string{"bill@gates.com"}
msg := []byte("To: bill@gates.com\r\n" +
"Subject: Why you’re not using Mailtrap yet?\r\n" +
"\r\n" +
"Here’s the space for our great sales pitch\r\n")
Notice how the recipient’s email address is placed in both the headers and the body. In order to send emails to more than one recipient, we’ll need to add them to both parts, separated by a comma.
to := []string{"bill@gates.com", “stevie@microsoft.com}
msg := []byte("To: bill@gates.com, stevie@microsoft.com \r\n" +
"Subject: Why you’re not using Mailtrap yet?\r\n" +
"\r\n" +
"Here’s the space for our great sales pitch\r\n")
Now, let’s assume this email is mainly addressed to Mr. Gates, but we want Mr. Ballmer to be cc’ed.
to := []string{"bill@gates.com"}
cc:= []string{“stevie@microsoft.com”}
msg := []byte("To: bill@gates.com\r\n" +
“cc: stevie@microsoft.com\r\n"
"Subject: Why you’re not using Mailtrap yet?\r\n" +
"\r\n" +
"Here’s the space for our great sales pitch\r\n")
Finally, let’s imagine that we don’t want Bill to know that Steve knows. This is done differently by adding Steve to the function parameters but excluding him from the message headers.
to := []string{"bill@gates.com", “stevie@microsoft.com}
msg := []byte("To: bill@gates.com\r\n" +
"Subject: Why you’re not using Mailtrap yet?\r\n" +
"\r\n" +
"Here’s the space for our great sales pitch\r\n")
Okay, we’ve taken care of the recipients. Now, what if we want to include an attachment with our message? Golang uses the mime/multipart
method by default for this purpose, but it’s far from straightforward. That’s why developers prefer 3rd-party libraries that simplify the process without adding too much boilerplate. Among them, Jordan Wright’s “email” library is the most popular. It can also be used to add cc or bcc along with other features. We strongly recommend it.
Using Golang’s API to connect 3rd party mailing services
If you’re going to be emailing hundreds or thousands of users, or are sending something a bit more sophisticated than password reset instructions, you will probably want to use something that is likewise more sophisticated. An obvious approach would be to connect your Go app to a 3rd party service that specializes in transactional mailings. This comes with several quite convincing benefits:
- You can send emails from a recognizable domain with an established reputation. This can have a serious impact on your deliverability.
- You can create beautiful email templates with drag & drop wizards, without the need to write any HTML.
- Finally, you can preview your emails before they’re sent to avoid unpleasant surprises.
There’s a number of resources ready to work with Go that you can utilize. Mailgun offers its own SDK for Go. SendGrid also comes with its own community-driven Go library. If Mailjet is your choice, you’ll also find numerous code samples for Golang in their REST API docs. If you prefer other platforms, you’ll likely find other user-made libraries to make integration smoother.
Each of these platforms (except for Mandrill) comes with a free pricing tier that lets you use some functionalities and send a limited number of messages.