Mailgun email provider

Mailgun provider implementing email.ProviderPort against Mailgun's REST API.

Overview

Mailgun is a developer-focused email service provider. The adapter sends outbound mail through Mailgun's HTTP REST API, not the SMTP gateway. It covers single send, bulk send, attachments, and inline images keyed by Content-ID. Per-message tags and open or click tracking pass through as provider options. Both the U.S. and EU regions are reachable by choosing the matching API hostname.

The adapter implements email.ProviderPort, so the same EmailBuilder and templated-email API work regardless of which provider you register. The adapter rate-limits itself. A token bucket caps sends at 50 calls per second with a burst of 100, so the provider self-throttles against Mailgun without any limiter code on your side.

The adapter emits OpenTelemetry metrics for send count and duration, labelled by status and by single or bulk send. All methods are safe for concurrent use. The adapter sends only. Mailgun's inbound routing, parsing, and forwarding are not part of this integration.

Requirements

  • A Mailgun account with API access. Generate a private API key in the Mailgun dashboard (Settings, then API Security).
  • A verified sending domain (for example mg.example.com) with the matching DNS records (SPF, DKIM).
  • Network egress to api.mailgun.net (U.S. region) or api.eu.mailgun.net (EU region). Select the EU region with the APIBase field on MailgunProviderArgs.

Configuration

import (
    "context"
    "os"

    "piko.sh/piko/wdk/email/email_provider_mailgun"
)

provider, err := email_provider_mailgun.NewMailgunProvider(ctx, email_provider_mailgun.MailgunProviderArgs{
    Domain:    "mg.example.com",             // required, the verified sending domain
    APIKey:    os.Getenv("MAILGUN_API_KEY"), // required
    FromEmail: "[email protected]",     // required, default From address
    APIBase:   "https://api.eu.mailgun.net", // optional, omit for the U.S. region
})
if err != nil {
    return err
}

NewMailgunProvider returns an email.ProviderPort. The fourth field, APIBase, overrides the API base URL. Leave it empty for the U.S. endpoint, or set it to https://api.eu.mailgun.net for the EU region. The constructor returns an error when Domain, APIKey, or FromEmail is empty, so a misconfigured provider fails at startup, not at first send.

Per-message options

Set Mailgun-specific behaviour per message through the EmailBuilder.ProviderOption method. The adapter reads these keys:

  • tag. A string label for Mailgun analytics.
  • tracking. A bool that turns message tracking on or off.
  • tracking_clicks. A bool for click tracking.
  • tracking_opens. A bool for open tracking.
  • require_tls. A bool that requires TLS for delivery.
  • skip_verification. A bool that skips certificate verification.
err := builder.
    To("[email protected]").
    Subject("Welcome").
    BodyHTML("<p>Hello</p>").
    ProviderOption("tag", "onboarding").
    ProviderOption("tracking_opens", true).
    Do(ctx)

The adapter drops unrecognised keys. The adapter never returns delivery events or per-message tracking IDs back through piko. The only telemetry it surfaces is the OpenTelemetry send count and duration.

Bulk sending

SupportsBulkSending returns false. SendBulk fans out to one Send call per message, and each call passes through the same rate limiter. Failures aggregate into an email.MultiError, so a partial failure reports which messages did not send and leaves the rest delivered.

Bootstrap

ssr := piko.New(
    piko.WithEmailProvider("mailgun", provider),
    piko.WithDefaultEmailProvider("mailgun"),
)

See also

Other email providers:

  • SendGrid, combined transactional and marketing.
  • Postmark, transactional-only, sub-second delivery.
  • SES, cheapest at scale if already on AWS.
  • Mailchimp Transactional, the former Mandrill.
  • SMTP, generic backend for self-hosted or vendor-neutral relays.
  • Gmail, Gmail SMTP with app passwords (dev / low-volume).

Framework docs:

External: