Product
If you’re building with Go and need reliable email for sign-ups, receipts, password resets, or alerts, this guide shows the fastest path.
You’ll set up a sender, send your first message with Mailjet’s Go SDK, and learn patterns for templates, attachments, bulk sending, webhooks, and SMTP.
This is an example-first, production-ready approach to email integration.
Back in 2009, Google released a language called Go, often referred to as “Golang”. Go was introduced as a robust server-side programming language. Since then, it has never failed to fulfill its promises with low-level programming patterns and powerful data structures.
This guide is designed for:
Before getting started, you’ll need:
💡 Pro tip: Authenticate your domain via SPF/DKIM to improve inbox delivery rates. See the complete authentication guide for setup details and examples.
Let’s get you sending emails quickly using the official Mailjet Go SDK and the v3.1 Send API.
First, install the Mailjet Go SDK:
go get github.com/mailjet/mailjet-apiv3-go/v4
Then set your environment variables:
export MJ_APIKEY_PUBLIC=your_api_key
export MJ_APIKEY_PRIVATE=your_secret_key
export SENDER_EMAIL=your_verified_sender@yourdomain.com
Create a main.go file with the following code:
package main
import (
"fmt"
"log"
"os"
"github.com/mailjet/mailjet-apiv3-go/v4"
)
func main() {
mj := mailjet.NewMailjetClient(os.Getenv("MJ_APIKEY_PUBLIC"), os.Getenv("MJ_APIKEY_PRIVATE"))
msgs := []mailjet.InfoMessagesV31{
{
From: &mailjet.RecipientV31{Email: os.Getenv("SENDER_EMAIL"), Name: "Go App"},
To: &mailjet.RecipientsV31{
{Email: "recipient@example.com", Name: "Recipient"},
},
Subject: "Hello from Go + Mailjet",
TextPart: "This is a plain-text fallback.",
HTMLPart: "<h3>Hello from Go + Mailjet</h3><p>It works.</p>",
},
}
messages := mailjet.MessagesV31{Info: msgs}
res, err := mj.SendMailV31(&messages)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Status: %+v\n", res)
}
The Go SDK wraps Mailjet’s REST endpoints and provides a convenient SendMailV31 helper that accepts a Messages array. This approach gives you the full power of the Mailjet API with minimal code.
If you prefer SMTP or already use an SMTP MTA, you can use Mailjet’s SMTP relay with your API credentials.
package main
import (
"net/smtp"
"os"
)
func main() {
host := "in-v3.mailjet.com"
auth := smtp.PlainAuth("", os.Getenv("MJ_APIKEY_PUBLIC"), os.Getenv("MJ_APIKEY_PRIVATE"), host)
to := []string{"recipient@example.com"}
from := "sender@yourdomain.com"
msg := []byte(
"To: recipient@example.com\r\n" +
"From: Go App <sender@yourdomain.com>\r\n" +
"Subject: SMTP from Go via Mailjet\r\n" +
"MIME-Version: 1.0\r\n" +
"Content-Type: text/html; charset=UTF-8\r\n\r\n" +
"<p>Hello via SMTP</p>",
)
// Port 587 (TLS) or 465 (SSL) are common choices
err := smtp.SendMail(host+":587", auth, from, to, msg)
if err != nil {
log.Fatal(err)
}
}
For more details, see the SMTP configuration guide.
Design your email template once in the Mailjet dashboard, then pass a TemplateID and Variables from your Go code for dynamic content.
msgs := []mailjet.InfoMessagesV31{
{
From: &mailjet.RecipientV31{Email: os.Getenv("SENDER_EMAIL"), Name: "Go App"},
To: &mailjet.RecipientsV31{{Email: "recipient@example.com", Name: "Terry"}},
TemplateID: 123456, // replace with your template ID
TemplateLanguage: true, // enable Mailjet templating language
Variables: map[string]any{"first_name": "Terry", "plan": "Pro"},
Subject: "Welcome, {{var:first_name:\"there\"}}",
},
}
For more template examples, see this Stack Overflow discussion.
Send attachments and embed inline images in your emails. The total message size limit is 15 MB.
// Read and base64-encode your files first, then:
msgs := []mailjet.InfoMessagesV31{
{
From: &mailjet.RecipientV31{Email: os.Getenv("SENDER_EMAIL")},
To: &mailjet.RecipientsV31{{Email: "recipient@example.com"}},
Subject: "Invoice attached + inline logo",
HTMLPart: `<p>Thanks for your purchase!</p><img src="cid:logo1" alt="Company Logo">`,
Attachments: &[]mailjet.AttachmentV31{
{
ContentType: "application/pdf",
Filename: "invoice.pdf",
Base64Content: "<BASE64_STRING>", // your base64-encoded PDF
},
},
InlinedAttachments: &[]mailjet.InlinedAttachmentV31{
{
AttachmentV31: mailjet.AttachmentV31{
ContentType: "image/png",
Filename: "logo.png",
Base64Content: "<BASE64_PNG>", // your base64-encoded image
},
ContentID: "logo1", // referenced in HTML as cid:logo1
},
},
},
}
Send multiple personalized messages in a single API call. Each message is validated independently, so successful messages will be sent even if one fails.
msgs := []mailjet.InfoMessagesV31{
{
From: &mailjet.RecipientV31{Email: os.Getenv("SENDER_EMAIL")},
To: &mailjet.RecipientsV31{{Email: "user1@example.com"}},
Subject: "Welcome, User 1!",
HTMLPart: "<p>Hello User 1</p>",
},
{
From: &mailjet.RecipientV31{Email: os.Getenv("SENDER_EMAIL")},
To: &mailjet.RecipientsV31{{Email: "user2@example.com"}},
Subject: "Welcome, User 2!",
HTMLPart: "<p>Hello User 2</p>",
},
}
res, err := mj.SendMailV31(&mailjet.MessagesV31{Info: msgs})
if err != nil {
log.Fatal(err)
}
// Process results - each message gets its own status and ID
for i, result := range res.ResultsV31 {
fmt.Printf("Message %d: Status=%s, MessageID=%d\n", i, result.Status, result.To[0].MessageID)
}
The v3.1 Send API returns per-message status and IDs, making it easy to correlate results with your original messages. Use the MessageID to track delivery status later.
Configure webhooks to receive real-time notifications about email events like delivery, opens, clicks, bounces, and unsubscribes.
package main
import (
"encoding/json"
"net/http"
"log"
)
type MailjetEvent struct {
Event string `json:"event"`
Time int64 `json:"time"`
MessageID int64 `json:"MessageID"`
Email string `json:"email"`
URL string `json:"url,omitempty"` // for click events
Error string `json:"error,omitempty"` // for bounce/error events
}
func webhookHandler(w http.ResponseWriter, r *http.Request) {
defer r.Body.Close()
var events []MailjetEvent
if err := json.NewDecoder(r.Body).Decode(&events); err != nil {
http.Error(w, "bad request", http.StatusBadRequest)
return
}
// Process events (consider using a queue for production)
for _, event := range events {
switch event.Event {
case "sent":
log.Printf("Message %d sent to %s", event.MessageID, event.Email)
case "open":
log.Printf("Message %d opened by %s", event.MessageID, event.Email)
case "click":
log.Printf("Message %d clicked by %s (URL: %s)", event.MessageID, event.Email, event.URL)
case "bounce":
log.Printf("Message %d bounced for %s: %s", event.MessageID, event.Email, event.Error)
}
}
// Always return 200 to acknowledge receipt
w.WriteHeader(http.StatusOK)
}
func main() {
http.HandleFunc("/mj/events", webhookHandler)
log.Fatal(http.ListenAndServe(":8080", nil))
}
For complete event documentation, see the Event Tracking API guide.
Here are three deliverability essentials to keep in mind.
Set up SPF and DKIM authentication for your sending domain to improve inbox placement and reduce the risk of spoofing:
Follow the complete domain authentication guide for step-by-step setup instructions.
If your Mailjet account is on the US infrastructure, configure the SDK to use the US API endpoint:
// For US region accounts
mj := mailjet.NewMailjetClient(apiKey, secretKey)
mj.SetAPIBase("https://api.us.mailjet.com/v3.1/")
Firewall considerations: Test your network’s port access; many providers block port 25
Here are the most common issues and how to troubleshoot them.
Use the official SDK with SendMailV31 as shown in the Quickstart section. It’s a single function call once your API keys are configured.
Yes! Point Go’s net/smtp package at in-v3.mailjet.com using your API key and secret as credentials, with port 587 or 465.
Set TemplateID, enable TemplateLanguage: true, and pass your data in the Variables field. Use {{var:name:”default”}} syntax in your templates.
Use webhooks for real-time event data, or check the Mailjet dashboard and REST API statistics endpoints for aggregated metrics.
Now that you have email sending working in your Go application, consider these enhancements:
With this foundation, you’re ready to build robust, scalable email functionality into your Go applications. The combination of Mailjet’s reliable infrastructure and Go’s performance makes for a powerful email solution.