The most surprising thing about sending email with Go is that you’re probably not actually sending the email; you’re just handing it off to a mail server that will do the heavy lifting.

Let’s see gomail in action. Imagine you have a simple Go program that needs to send a welcome email to a new user.

package main

import (
	"log"

	"gopkg.in/gomail.v2"
)

func main() {
	m := gomail.NewMessage()
	m.SetHeader("From", "noreply@example.com")
	m.SetHeader("To", "user@example.com")
	m.SetHeader("Subject", "Welcome to Our Service!")
	m.SetBody("text/html", "<h1>Welcome!</h1><p>Thanks for joining us.</p>")

	d := gomail.NewDialer("smtp.example.com", 587, "username@example.com", "your_password")

	// Send the email
	if err := d.DialAndSend(m); err != nil {
		log.Fatalf("Failed to send email: %v", err)
	}

	log.Println("Email sent successfully!")
}

Here, gomail.NewMessage() creates a new email object. We then set the From, To, and Subject headers, and finally, the email’s body using SetBody. The text/html part tells the recipient’s email client to render the body as HTML.

The core of the sending process is handled by gomail.NewDialer. This struct encapsulates your SMTP server’s connection details: the hostname (smtp.example.com), the port (587 is standard for TLS/STARTTLS), your SMTP username (username@example.com), and your password (your_password). The DialAndSend method then establishes a connection to the SMTP server, sends your email message, and closes the connection.

This setup solves the problem of needing to interact with the Simple Mail Transfer Protocol (SMTP) from your Go application. Instead of writing raw SMTP commands, gomail provides a high-level API. The Dialer abstracts away the complexities of network connections, authentication (like LOGIN or PLAIN), and the SMTP conversation itself.

The problem this solves is the need for reliable, programmatic email delivery. Applications often need to send notifications, confirmations, or marketing messages. Doing this directly involves understanding SMTP, handling MIME types for rich content, managing connections, and dealing with potential network errors. gomail abstracts all of this.

Internally, gomail.Dialer uses Go’s net/smtp package under the hood. When DialAndSend is called, it first establishes a TCP connection to the specified SMTP host and port. It then initiates the SMTP handshake, including identifying itself (EHLO), authenticating with the provided credentials, and finally sending the email data (MAIL FROM, RCPT TO, DATA). The gomail library handles the formatting of the email message according to MIME standards, ensuring that attachments, HTML content, and plain text versions are correctly structured.

The gomail.Dialer struct is where you configure your SMTP connection. The port number is crucial: 587 is for STARTTLS (Transport Layer Security), which encrypts the connection after it’s established. 465 is typically used for SMTPS (implicit TLS), where the connection is encrypted from the very beginning. If your provider uses 465, you’d use gomail.NewDialer("smtp.example.com", 465, ...), and gomail.DialAndSend will automatically handle the TLS handshake.

A common pitfall is forgetting to enable TLS/STARTTLS. If your SMTP server requires encryption and you don’t specify the correct port or if the client doesn’t negotiate TLS, the connection will likely fail or be insecure. gomail.NewDialer handles the STARTTLS negotiation automatically if you use port 587. For port 465, it expects an implicit TLS connection.

The gomail.NewMessage() function creates an email structure that adheres to RFC 5322. You can add multiple recipients to To, Cc, and Bcc headers. The SetBody method can be called multiple times with different MIME types (e.g., text/plain and text/html) to provide both a plain text and an HTML version of your email, which gomail will combine into a multipart message for better compatibility with various email clients.

When sending emails through services like Gmail, SendGrid, or Mailgun, you’ll use their specific SMTP server details and your API key or credentials as the username and password. For example, Gmail’s SMTP server is smtp.gmail.com on port 587 (with STARTTLS) or 465 (with SMTPS). You’ll need to enable "Less secure app access" or generate an "App password" if using Gmail with a standard password.

You’ve successfully set up basic email sending. The next step is often handling attachments.

Want structured learning?

Take the full Smtp course →