Install mailgun-go/v5
mainTo use the Mailgun Go library with Go Modules, ensure you include the /v5 suffix in your import paths and run the following command:
go get github.com/mailgun/mailgun-go/v5repository·main·Indexed 20 days ago
https://github.com/mailgun/mailgun-goA Go library for interacting with the Mailgun API. It supports sending emails (including HTML and templates), event tracking, email validation, and webhook handling. The library provides functionality to manage API keys, configure alerts, retrieve account or domain metrics, and handle bounce records. Version 5 requires the /v5 suffix in import paths.
To use the Mailgun Go library with Go Modules, ensure you include the /v5 suffix in your import paths and run the following command:
go get github.com/mailgun/mailgun-go/v5To migrate to v5, follow these steps:
v4.23.0) first.staticcheck with SA1019 to find // Deprecated: comments)./v5, for example: import "github.com/mailgun/mailgun-go/v5".To securely handle webhooks, set a signing key using mg.SetWebhookSigningKey(key). When a request arrives, decode the mtypes.WebhookPayload, verify the signature using mg.VerifyWebhookSignature(payload.Signature), and then parse the event data using events.ParseEvent(payload.EventData).
package main
import (
"encoding/json"
"fmt"
"net/http"
"os"
"github.com/mailgun/mailgun-go/v5"
"github.com/mailgun/mailgun-go/v5/events"
"github.com/mailgun/mailgun-go/v5/mtypes"
)
func main() {
mg := mailgun.NewMailgun("MAILGUN_API_KEY")
mg.SetWebhookSigningKey("WEBHOOK_SIGNING_KEY")
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
var payload mtypes.WebhookPayload
if err := json.NewDecoder(r.Body).Decode(&payload); err != nil {
fmt.Printf("decode JSON error: %s", err)
w.WriteHeader(http.StatusNotAcceptable)
return
}
verified, err := mg.VerifyWebhookSignature(payload.Signature)
if err != nil {
fmt.Printf("verify error: %s\n", err)
w.WriteHeader(http.StatusNotAcceptable)
return
}
if !verified {
w.WriteHeader(http.StatusNotAcceptable)
fmt.Printf("failed verification %+v\n", payload.Signature)
return
}
fmt.Printf("Verified Signature\n")
e, err := events.ParseEvent(payload.EventData)
if err != nil {
fmt.Printf("parse event error: %s\n", err)
return
}
switch event := e.(type) {
case *events.Accepted:
fmt.Printf("Accepted: auth: %t\n", event.Flags.IsAuthenticated)
case *events.Delivered:
fmt.Printf("Delivered transport: %s\n", event.Envelope.Transport)
}
})
fmt.Println("Serve on :9090...")
if err := http.ListenAndServe(":9090", nil); err != nil {
fmt.Printf("serve error: %s\n", err)
os.Exit(1)
}
}Templates allow you to manage layouts on the Mailgun server and populate variables at send-time. Use message.SetTemplate(templateName) and message.AddTemplateVariable(key, value) to inject data into the template. The variables are sent as a JSON stringified X-Mailgun-Variables header.
package main
import (
"context"
"fmt"
"log"
"time"
"github.com/mailgun/mailgun-go/v5"
)
var yourDomain = "your-domain-name"
var apiKey = "MAILGUN_API_KEY"
func main() {
mg := mailgun.NewMailgun(apiKey)
sender := "sender@example.com"
subject := "Fancy subject!"
body := ""
recipient := "recipient@example.com"
message := mailgun.NewMessage(yourDomain, sender, subject, body, recipient)
message.SetTemplate("passwordReset")
err := message.AddTemplateVariable("passwordResetLink", "some link to your site unique to your user")
if err != nil {
log.Fatal(err)
}
ctx, cancel := context.WithTimeout(context.Background(), time.Second*10)
defer cancel()
resp, err := mg.Send(ctx, message)
if err != nil {
log.Fatal(err)
}
fmt.Printf("ID: %s Resp: %s\n", resp.ID, resp.Message)
}The MemberListIterator is a stateful iterator used for navigating paginated mailing list member results. It wraps a mtypes.MemberListResponse and provides methods to move through the pages of the API response.
First(ctx, items): Sets the iterator to the first page and populates items.Next(ctx, items): Fetches the next page of results. Returns false when no more pages exist.Previous(ctx, items): Moves to the previous page.Last(ctx, items): Moves to the last page (requires First() or Next() to have been called first).Err(): Returns any error encountered during the iteration process.To retrieve and navigate through multiple pages of mailing lists, use ListMailingLists. This returns a *ListsIterator which allows for paginated traversal.
First(ctx, *[]mtypes.MailingList) bool: Retrieves the first page of items.Next(ctx, *[]mtypes.MailingList) bool: Retrieves the next page of items. Returns false when no more pages exist or an error occurs.Previous(ctx, *[]mtypes.MailingList) bool: Retrieves the previous page of items.Last(ctx, *[]mtypes.MailingList) bool: Retrieves the last page of items. (Must call First or Next before calling Last).Err() error: Returns any error encountered during iteration.iterator := mg.ListMailingLists(&mailgun.ListOptions{Limit: 10})
// Start with the first page
var items []mtypes.MailingList
if iterator.First(ctx, &items) {
fmt.Println("First page items:", items)
}
// Iterate through subsequent pages
for iterator.Next(ctx, &items) {
fmt.Println("Next page items:", items)
}
if err := iterator.Err(); err != nil {
log.Fatal(err)
}An EventIterator manages the state required to page through Mailgun events. It wraps an events.Response which contains paging metadata (Next, First, Last, Previous URLs).
First(ctx, ee): Fetches the very first page of events.Next(ctx, ee): Fetches the next page of events. Returns false when no more pages exist or an error occurs.Last(ctx, ee): Fetches the last page. Note: This is invalid unless First() or Next() has been called first.Previous(ctx, ee): Fetches the previous page. Returns false if no previous page exists.All methods populate the provided slice ee *[]events.Event with the results of the current page. Always check iterator.Err() after a method returns false to determine if the termination was due to an error or simply reaching the end of the data.
The CredentialsIterator is a stateful object used to navigate through paginated credential lists. It embeds mtypes.CredentialsListResponse, providing access to the TotalCount of credentials available.
ListCredentials(domain, opts) to get an iterator.First() to start or Next() to move forward. These methods perform the actual API request and populate the provided slice.iterator.Err() after a loop or a failed navigation attempt to see if the failure was due to a network or API error.offset and limit internally to manage pagination via the skip and limit parameters in the underlying API calls.If your Mailgun domain is hosted in the EU region, you must change the default API base using mg.SetAPIBase(mailgun.APIBaseEU).
mg := mailgun.NewMailgun("MAILGUN_API_KEY")
mg.SetAPIBase(mailgun.APIBaseEU)Methods starting with List (e.g., ListEvents, ListDomains) return an iterator. This allows you to page through large datasets efficiently without loading everything into memory at once.
To use an iterator:
List method with ListOptions (you can specify a Limit per page, up to a maximum of 100).for it.Next(ctx, &page) loop to fetch subsequent pages.context.Context with a timeout to prevent the operation from hanging indefinitely.mg := mailgun.NewMailgun("MAILGUN_API_KEY")
// Request 100 items per page
it := mg.ListEvents(&mailgun.ListEventOptions{Limit: 100})
// Use a context to prevent long-running operations
ctx, cancel := context.WithTimeout(context.Background(), time.Second*30)
defer cancel()
var page []mailgun.Event
for it.Next(ctx, &page) {
for _, e := range page {
// Process event 'e'
}
}The TagIterator provides several methods to navigate through pages of tags. It embeds mtypes.TagsResponse, giving you access to the current Items and Paging information.
Next(ctx context.Context, items *[]mtypes.Tag) bool: Fetches the next page of items. Returns true if new items were loaded, false otherwise.Previous(ctx context.Context, items *[]mtypes.Tag) bool: Fetches the previous page of items.First(ctx context.Context, items *[]mtypes.Tag) bool: Returns to the first page of results.Last(ctx context.Context, items *[]mtypes.Tag) bool: Jumps to the last page of results.Err() error: Returns any error encountered during pagination or fetching.To retrieve a list of subaccounts, use ListSubaccounts. This returns a SubaccountsIterator which allows for paginated traversal of your subaccounts.
Pass a *ListSubaccountsOptions to control the results:
Limit: Number of items per page (defaults to 10 if 0).Skip: Number of items to skip.SortArray: Field to sort by.Enabled: Filter by enabled status.First(ctx, *[]mtypes.Subaccount) bool: Retrieves the first page. Returns false on error.Next(ctx, *[]mtypes.Subaccount) bool: Retrieves the next page. Returns false when no more pages exist or an error occurs.Last(ctx, *[]mtypes.Subaccount) bool: Retrieves the last page. Note: Must be called after First() or Next().Previous(ctx, *[]mtypes.Subaccount) bool: Retrieves the previous page.Err() error: Returns any error encountered during iteration.Offset() int: Returns the current offset of the iterator.opts := &mailgun.ListSubaccountsOptions{
Limit: 20,
Enabled: true,
}
iterator := mg.ListSubaccounts(opts)
var subaccounts []mtypes.Subaccount
for iterator.Next(ctx, &subaccounts) {
// Process subaccounts page by page
fmt.Println(subaccounts)
}
if err := iterator.Err(); err != nil {
// Handle iteration error
}