Sending Emails with SMTP in Go

Send emails through AhaSend’s SMTP servers using Go with the standard library net/smtp package or the more feature-rich gomail.v2 library. This guide covers everything from basic setup to advanced features like attachments and custom headers.
Go Standard Library vs Third-Party: While Go’s net/smtp package provides essential SMTP functionality, it’s low-level and verbose. For complex emails with attachments or custom headers, consider using gomail.v2 for a more convenient API.

Prerequisites

Before you begin, ensure you have:
Need SMTP Credentials? If you haven’t created SMTP credentials yet, check out our SMTP Credentials guide for step-by-step instructions.

Connection Settings

Use these settings for all Go SMTP configurations with AhaSend:

Primary Server

Host: send.ahasend.com
Ports: 587 (recommended), 25, 2525
Security: STARTTLS
Authentication: Required

US Server

Host: send-us.ahasend.com
Ports: 587 (recommended), 25, 2525
Security: STARTTLS
Authentication: Required

Using net/smtp (Standard Library)

Go’s standard library provides basic SMTP functionality through the net/smtp package. It’s lightweight but requires manual message construction.
package main

import (
    "fmt"
    "net/smtp"
)

func main() {
    // SMTP server configuration
    host := "send.ahasend.com"
    port := "587"
    username := "YOUR_SMTP_USERNAME"
    password := "YOUR_SMTP_PASSWORD"

    // Set up authentication
    auth := smtp.PlainAuth("", username, password, host)

    // Email details
    from := "[email protected]"
    to := []string{"[email protected]"}

    // Construct message
    subject := "Welcome to our platform!"
    body := "Thanks for signing up. We're excited to have you!"

    msg := []byte(fmt.Sprintf("To: %s\r\n"+
        "Subject: %s\r\n"+
        "\r\n"+
        "%s\r\n", to[0], subject, body))

    // Send email
    err := smtp.SendMail(host+":"+port, auth, from, to, msg)
    if err != nil {
        fmt.Printf("Failed to send email: %v\n", err)
        return
    }

    fmt.Println("Email sent successfully!")
}
Use gomail.v2 for production applications as it provides better error handling, attachment support, and cleaner API. Start with sandbox mode during development and use environment variables for credentials.
The gomail.v2 package provides a more convenient and feature-rich API for sending emails with attachments, custom headers, and better message construction.

Installation

Install gomail.v2 using Go modules:
go get gopkg.in/gomail.v2
package main

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

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

    // Set headers
    m.SetHeader("From", "[email protected]")
    m.SetHeader("To", "[email protected]")
    m.SetHeader("Subject", "Welcome to our platform!")

    // Set body
    m.SetBody("text/plain", "Thanks for signing up. We're excited to have you!")

    // Create SMTP dialer
    d := gomail.NewDialer("send.ahasend.com", 587, "YOUR_SMTP_USERNAME", "YOUR_SMTP_PASSWORD")

    // Send email
    if err := d.DialAndSend(m); err != nil {
        fmt.Printf("Failed to send email: %v\n", err)
        return
    }

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

Advanced Examples

package main

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

type Recipient struct {
    Email string
    Name  string
}

func main() {
    recipients := []Recipient{
        {Email: "[email protected]", Name: "User One"},
        {Email: "[email protected]", Name: "User Two"},
        {Email: "[email protected]", Name: "User Three"},
    }

    // Create dialer
    d := gomail.NewDialer("send.ahasend.com", 587, "YOUR_SMTP_USERNAME", "YOUR_SMTP_PASSWORD")

    // Open connection
    s, err := d.Dial()
    if err != nil {
        fmt.Printf("Failed to connect: %v\n", err)
        return
    }
    defer s.Close()

    // Send emails
    for _, recipient := range recipients {
        m := gomail.NewMessage()

        m.SetHeader("From", "[email protected]")
        m.SetHeader("To", recipient.Email)
        m.SetHeader("Subject", "Personalized Newsletter")
        m.SetHeader("ahasend-tags", "newsletter,bulk,golang")

        // Personalized content
        body := fmt.Sprintf(`
            <html>
            <body>
                <h1>Hello %s!</h1>
                <p>This is your personalized newsletter.</p>
            </body>
            </html>
        `, recipient.Name)
        m.SetBody("text/html", body)

        if err := gomail.Send(s, m); err != nil {
            fmt.Printf("Failed to send to %s: %v\n", recipient.Email, err)
            continue
        }

        fmt.Printf("Email sent to %s\n", recipient.Email)

        // Add delay to avoid rate limiting
        time.Sleep(100 * time.Millisecond)
    }

    fmt.Println("Bulk email sending completed!")
}

Testing with Sandbox Mode

Use sandbox mode to test your Go email integration safely:
package main

import (
    "fmt"
    "net/smtp"
)

func main() {
    host := "send.ahasend.com"
    port := "587"
    auth := smtp.PlainAuth("", "YOUR_SMTP_USERNAME", "YOUR_SMTP_PASSWORD", host)

    from := "[email protected]"
    to := []string{"[email protected]"}

    // Sandbox message with simulated outcome
    msg := []byte("To: [email protected]\r\n" +
        "Subject: Sandbox Test\r\n" +
        "AhaSend-Sandbox: true\r\n" +
        "AhaSend-Sandbox-Result: deliver\r\n" +
        "\r\n" +
        "This email is sent in sandbox mode for testing.\r\n")

    err := smtp.SendMail(host+":"+port, auth, from, to, msg)
    if err != nil {
        fmt.Printf("Failed to send sandbox email: %v\n", err)
        return
    }

    fmt.Println("Sandbox email sent!")
}
Sandbox Benefits: Emails sent in sandbox mode are free, trigger webhooks normally, and never actually deliver to recipients - perfect for development and testing.

Best Practices

Resources