Use the official Go SDK to send email through the Lettermint Sending API. This guide covers installation, message options, responses, and errors. See Integrations for the SDK capability overview.
1. Installation
Install the SDK using Go modules:
go get github.com/lettermint/lettermint-go
Requires Go 1.21 or higher.
2. Send your first email
Initialize the client with your Project API token:
package main
import (
" context "
" fmt "
" log "
" os "
lettermint " github.com/lettermint/lettermint-go "
)
func main () {
client, err := lettermint. New (os. Getenv ( "LETTERMINT_PROJECT_TOKEN" ))
if err != nil {
log. Fatal (err)
}
}
Send your first email:
ctx := context. Background ()
resp, err := client. Email (ctx).
From ( "John Doe <john@yourdomain.com>" ).
To ( "recipient@example.com" ).
Subject ( "Hello from Lettermint" ).
Text ( "This is a test email sent using the Lettermint Go SDK." ).
Send ()
if err != nil {
log. Fatal (err)
}
fmt. Printf ( "Email sent with ID: %s\n " , resp.MessageID)
3. Email features
Basic email
Send a simple text or HTML email:
resp, err := client. Email (ctx).
From ( "John Doe <john@yourdomain.com>" ).
To ( "recipient@example.com" ).
Subject ( "Your account is ready!" ).
HTML ( "<h1>Welcome!</h1><p>Thanks for signing up.</p>" ).
Text ( "Welcome! Thanks for signing up." ).
Send ()
Multiple recipients
Send to multiple recipients using CC and BCC:
resp, err := client. Email (ctx).
From ( "John Doe <john@yourdomain.com>" ).
To ( "user1@example.com" , "user2@example.com" ).
CC ( "manager@yourdomain.com" ).
BCC ( "archive@yourdomain.com" ).
Subject ( "Monthly Newsletter" ).
HTML ( "<h1>This Month's Updates</h1>" ).
Send ()
Custom headers and reply-to
Add custom headers and set reply-to addresses:
resp, err := client. Email (ctx).
From ( "support@yourdomain.com" ).
To ( "customer@example.com" ).
ReplyTo ( "help@yourdomain.com" ).
Subject ( "Support Ticket #12345" ).
Headers ( map [ string ] string {
"X-Priority" : "1" ,
"X-Ticket-ID" : "12345" ,
}).
HTML ( "<p>Your support ticket has been updated.</p>" ).
Send ()
Metadata
Add metadata for tracking and webhook payloads:
resp, err := client. Email (ctx).
From ( "notifications@yourdomain.com" ).
To ( "user@example.com" ).
Subject ( "Order Confirmation" ).
Metadata ( map [ string ] string {
"order_id" : "12345" ,
"customer_id" : "cust_789" ,
"campaign" : "order_confirmation" ,
}).
HTML ( "<p>Your order has been confirmed.</p>" ).
Send ()
Metadata is included in webhook payloads but not added to the actual email headers. Use it for tracking and analytics purposes.
Tags
Categorize emails for filtering and analytics:
resp, err := client. Email (ctx).
From ( "alerts@yourdomain.com" ).
To ( "admin@example.com" ).
Subject ( "System Alert" ).
Tag ( "system-alerts" ).
HTML ( "<p>Critical system alert detected.</p>" ).
Send ()
This SDK example uses the existing singular tag. It has no deprecation date. Use the raw HTTP API to send structured tags until this SDK has a multi-tag method. See Tags documentation .
Route selection
Direct emails to specific routes within your project:
resp, err := client. Email (ctx).
From ( "notifications@yourdomain.com" ).
To ( "user@example.com" ).
Subject ( "Welcome!" ).
Route ( "transactional" ).
HTML ( "<p>Welcome to our platform.</p>" ).
Send ()
File attachments
Attach files to your emails:
import (
" encoding/base64 "
" os "
)
// Read and encode file
fileContent, err := os. ReadFile ( "/path/to/document.pdf" )
if err != nil {
log. Fatal (err)
}
encodedContent := base64.StdEncoding. EncodeToString (fileContent)
resp, err := client. Email (ctx).
From ( "invoices@yourdomain.com" ).
To ( "customer@example.com" ).
Subject ( "Your Invoice" ).
HTML ( "<p>Please find your invoice attached.</p>" ).
Attach ( "invoice.pdf" , encodedContent).
Send ()
Inline images
Embed images directly in your HTML using Content-ID:
logoContent, _ := os. ReadFile ( "/path/to/logo.png" )
encodedLogo := base64.StdEncoding. EncodeToString (logoContent)
resp, err := client. Email (ctx).
From ( "marketing@yourdomain.com" ).
To ( "customer@example.com" ).
Subject ( "Welcome to Our Platform" ).
HTML ( `<p>Welcome!</p><img src="cid:logo" alt="Company Logo">` ).
AttachWithContentID ( "logo.png" , encodedLogo, "logo" ).
Send ()
Idempotency
Prevent duplicate emails with idempotency keys:
resp, err := client. Email (ctx).
From ( "notifications@yourdomain.com" ).
To ( "user@example.com" ).
Subject ( "Order Confirmation" ).
HTML ( "<p>Your order has been confirmed.</p>" ).
IdempotencyKey ( "order-12345-confirmation" ).
Send ()
Use one unique key for each logical email. For example, combine the order ID and the email type. A retry with the same key does not send a duplicate email.
4. Client configuration
Customize the client with functional options:
import " time "
client, err := lettermint. New (
os. Getenv ( "LETTERMINT_PROJECT_TOKEN" ),
lettermint. WithTimeout ( 30 * time.Second),
lettermint. WithBaseURL ( "https://api.lettermint.co/v1" ),
)
5. Response
resp, err := client. Email (ctx).
From ( "John Doe <john@yourdomain.com>" ).
To ( "recipient@example.com" ).
Subject ( "Test" ).
Text ( "Hello!" ).
Send ()
if err != nil {
log. Fatal (err)
}
fmt. Println (resp.MessageID) // Unique email ID
fmt. Println (resp.Status) // Current status
6. Error handling
Handle errors with type checking:
import " errors "
resp, err := client. Email (ctx).
From ( "sender@yourdomain.com" ).
To ( "recipient@example.com" ).
Subject ( "Test" ).
Text ( "Hello!" ).
Send ()
if err != nil {
var apiErr * lettermint . APIError
if errors. As (err, & apiErr) {
fmt. Printf ( "API Error ( %d ): %s\n " , apiErr.StatusCode, apiErr.Message)
fmt. Printf ( "Validation errors: %v\n " , apiErr.Errors)
return
}
// Check specific error types
switch {
case errors. Is (err, lettermint.ErrUnauthorized):
fmt. Println ( "Invalid Project API token" )
case errors. Is (err, lettermint.ErrValidation):
fmt. Println ( "Invalid request parameters" )
case errors. Is (err, lettermint.ErrRateLimited):
fmt. Println ( "Rate limit exceeded" )
case errors. Is (err, lettermint.ErrTimeout):
fmt. Println ( "Request timed out" )
default :
fmt. Printf ( "Unexpected error: %v\n " , err)
}
}
7. Webhook verification
Verify incoming webhooks from Lettermint:
import " net/http "
func webhookHandler ( w http . ResponseWriter , r * http . Request ) {
event, err := lettermint. VerifyWebhookFromRequest (
r,
os. Getenv ( "LETTERMINT_WEBHOOK_SECRET" ),
lettermint.DefaultWebhookTolerance,
)
if err != nil {
http. Error (w, "Invalid signature" , http.StatusUnauthorized)
return
}
switch event.Event {
case "message.delivered" :
log. Printf ( "Email delivered to %s " , event.Data.Recipient)
case "message.hard_bounced" :
log. Printf ( "Hard bounce for %s " , event.Data.Recipient)
case "message.soft_bounced" :
log. Printf ( "Soft bounce for %s " , event.Data.Recipient)
}
w. WriteHeader (http.StatusOK)
}
Store your webhook secret in an environment variable. Never hardcode secrets in your application.
Next steps
Organize and filter emails with tags.
Track opens, clicks, and deliverability.
Receive delivery events through webhooks.
Send via SMTP instead of the API.
Find the complete source code, report issues, or contribute on GitHub.