Send emails with Go
Send email from Go with the official mailblastr-go module — typed request structs, context variants, and zero third-party dependencies.
The official Go module is the fastest way to send email from Go. It depends only on the standard library, sets the required User-Agent header for you, and retries 429/503 responses automatically.
One thing to get right: the module path ends in /v5. That suffix is mandatory (it is the Go major-version path for the v5 line) — go get without it resolves an old pre-v2 tag. The package name inside is mailblastr, not v5, so import it with an explicit alias.
Prerequisites
- A verified domain for your
fromaddress. (guide) - An API key (
mb_...), read fromMAILBLASTR_API_KEY. (Authentication) - Go 1.22 or newer — that is the floor declared in the module
go.mod.
Install
go get github.com/shekhu10/mailblastr-sdks/mailblastr-go/v5Send an email
Construct the client with mailblastr.NewClient and call client.Emails.Send. delivered@mailblastr.dev is the delivery simulator — safe to send to while you wire things up. Do not use example.com: it is a blocked recipient domain and the send comes back 422.
package main
import (
"errors"
"fmt"
"log"
"os"
mailblastr "github.com/shekhu10/mailblastr-sdks/mailblastr-go/v5"
)
func main() {
client := mailblastr.NewClient(os.Getenv("MAILBLASTR_API_KEY"))
sent, err := client.Emails.Send(&mailblastr.SendEmailRequest{
From: "Acme <hello@yourdomain.com>",
To: []string{"delivered@mailblastr.dev"},
Subject: "Hello from Go",
Html: "<p>Sent with the official Go module 🐹</p>",
})
if err != nil {
var apiErr *mailblastr.MailblastrError
if errors.As(err, &apiErr) {
log.Fatalf("MailBlastr %d %s: %s", apiErr.StatusCode, apiErr.Name, apiErr.Message)
}
log.Fatal(err)
}
fmt.Println("Sent email", sent.Id)
}Handling the response
A successful send returns *mailblastr.CreateEmailResponse, whose only field is Id. Keep it to retrieve the email later or to correlate webhook events.
{
"id": "49a3999c-0ce1-4ea6-ab68-afcd6dc2e794"
}Any non-2xx answer comes back as a *mailblastr.MailblastrError carrying the { statusCode, name, message } envelope. Branch on Name together with StatusCode, never on Message — message text is scrubbed server-side and is not a stable contract. Plan and quota rejections additionally populate Limit, and reputation gates populate Reputation; both are nil on an ordinary error.
var apiErr *mailblastr.MailblastrError
if errors.As(err, &apiErr) {
switch apiErr.Name {
case "validation_error":
// 422 — a bad field, or 403 when the User-Agent header is missing.
case "daily_quota_exceeded":
if l := apiErr.Limit; l != nil {
fmt.Printf("%s cap hit: %d/%d\n", l.Kind, l.Used, l.Limit)
}
}
}Context and tuning
Every method has a context-aware variant with a WithContext suffix, so a send can inherit the deadline of the request that triggered it.
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
sent, err := client.Emails.SendWithContext(ctx, params)The exported client fields may be overridden before first use. Timeout bounds each attempt (default mailblastr.DefaultTimeout, 30s) and MaxRetries is the retry budget for 429/503 only (default mailblastr.DefaultMaxRetries, 2) — no other status, network error, or timeout is retried, so a send is never silently duplicated.
client := mailblastr.NewClient(os.Getenv("MAILBLASTR_API_KEY"))
client.Timeout = 10 * time.Second
client.MaxRetries = 3User-Agent (mailblastr-go/5.1.0), which the API requires on every route — a request without one is rejected with 403 validation_error before it is even authenticated. Setting client.UserAgent = "" falls back to that default rather than producing a client that 403s on every call.mb_ API key from the environment (or your secrets manager) and keep it server-side. Never compile it into a binary you ship to users — the key can send email as your account.Next steps
- See the full Send Email API reference for every body field (
Cc,Bcc,ReplyTo,Attachments,ScheduledAt). - Explore the SDKs reference for the other resources the module exposes.
- Prefer no dependencies at all? Send with Go over raw HTTP uses only
net/http.