gomail

package module
v1.7.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 3, 2026 License: MIT Imports: 47 Imported by: 2

README

📨  go-mail

Lightweight email package with multi-provider support (ses, mailgun, mandrill, postmark, resend, sendgrid, smtp)


Release Go Version License


CI / CD    Build Last Commit      Quality    Coverage
Security    Scorecard Security      Community    Contributors Bitcoin


Project Navigation
🚀 Installation 🧪 Examples & Tests 📚 Documentation
🤝 Contributing 🛠️ Code Standards ⚡ Benchmarks
🤖 AI Usage ⚖️ License 👥 Maintainers

Installation

go-mail requires a supported release of Go.

go get github.com/mrz1836/go-mail

Documentation

View the generated documentation

Quick Start
package main

import (
    "context"
    "log"

    gomail "github.com/mrz1836/go-mail"
)

func main() {
    // Configure the sender and at least one provider
    mail := &gomail.MailService{
        FromName:       "No Reply",
        FromUsername:   "no-reply",
        FromDomain:     "example.com",
        SendGridAPIKey: "SG.xxxx",
    }
    if err := mail.StartUp(); err != nil {
        log.Fatal(err)
    }

    // Create and send an email
    email := mail.NewEmail()
    email.Subject = "Welcome!"
    email.HTMLContent = "<p>Thanks for signing up.</p>"
    email.PlainTextContent = "Thanks for signing up."
    email.Recipients = []string{"Jane Doe <jane@example.com>"}

    result, err := mail.Send(context.Background(), email, gomail.SendGrid)
    if err != nil {
        log.Fatal(err)
    }
    log.Printf("sent via %s: %s", result.Provider, result.MessageID)
}

More complete examples (every provider, attachments, templates, failover and provider options) are in examples/examples.go.

Features
  • Supports multiple service providers (below), plus your own through the Provider interface
  • Failover across providers, with the provider's message id returned from Send
  • Provider-specific features through typed options (ie: Postmark message streams, SendGrid templates, Mailgun test mode)
  • AWS SES via static keys or the default credential chain (IAM role)
  • SMTP with STARTTLS or implicit TLS, optional authentication, and timeouts
  • Plain-text and HTML content
  • Recipients with display names (Jane Doe <jane@example.com>); duplicates across To, CC and BCC are removed
  • Multiple file attachments, plus inline (cid:) images
  • Custom headers, including one-click List-Unsubscribe (required by Gmail and Yahoo for bulk senders)
  • Tags, metadata, scheduled sending and idempotency keys (provider dependant)
  • Open & click tracking (provider dependant)
  • Inject css into html content
  • Basic template support
  • Max restrictions on To, CC and BCC
  • Secrets are redacted when the configuration is logged or marshaled to JSON
  • BCC recipients are never written into the message headers, and header values cannot inject new headers
Supported Service Providers
  • AWS SES (tags & metadata become message tags; tracking via a configuration set)
  • Mailgun (up to 10 tags; metadata becomes user variables; US or EU region)
  • Mandrill (recipients are not preserved: each To recipient only sees their own address)
  • Postmark (one tag per email: multiple tags are joined with a comma)
  • Resend (open & click tracking configured per domain)
  • SendGrid (native open & click tracking)
  • SMTP
Feature AWS SES Mailgun Mandrill Postmark Resend SendGrid SMTP
Tags ✓ ✓ ✓ ✓ ✓ ✓
Metadata ✓ ✓ ✓ ✓ ✓ ✓
Open / click tracking ✓ ✓ ✓ ✓
Scheduled send (SendAt) ✓ ✓ ✓ ✓
Idempotency key ✓
Auto text ✓ ✓
View content link ✓

When an email uses a feature its provider does not support, go-mail logs a warning (or returns ErrUnsupportedFeature when StrictFeatures is set). An unsupported SendAt is always an error, so a scheduled email is never sent early.

Mailgun detects an attachment's content type from its file name and uses the file name as the content id of an inline image, so inline attachments are sent named by their ContentID: use a content id with an extension (ie: logo.png, referenced as cid:logo.png).

Sending, Failover & Results
// Send returns the provider that accepted the email and its message id
result, err := mail.Send(ctx, email, gomail.Postmark, gomail.SendGrid) // tries Postmark, then SendGrid
if err != nil {
    return err
}
log.Printf("sent via %s: %s", result.Provider, result.MessageID)

// SendEmail is still available when only the error matters
err = mail.SendEmail(ctx, email, gomail.SMTP)

Every send is bounded by SendTimeout (default one minute) and honors the context. Attachments added with a reader are buffered on the first send, so the same email can be retried or failed over.

Provider-Specific Features

Each provider has a typed option that edits its native request right before it is sent, so anything the provider SDK supports is available. Options for other providers are ignored.

email.With(
    gomail.PostmarkOption(func(e *postmark.Email) { e.MessageStream = "broadcast" }),
    gomail.SendGridOption(func(m *mail.SGMailV3) { m.SetTemplateID("d-123") }),
    gomail.ResendOption(func(r *resend.SendEmailRequest) { r.TopicId = "topic_123" }),
    gomail.MailgunOption(func(m *mailgun.PlainMessage) { m.SetRequireTLS(true) }),
    gomail.MandrillOption(func(m *gochimp.Message) { m.Subaccount = "tenant-1" }),
    gomail.SESOption(func(in *ses.SendRawEmailInput) { in.FromArn = aws.String(arn) }),
)
Custom Providers & Clients

Register any Provider (a new service, a built-in provider with your own client, or a fake in tests). A registered provider is kept by StartUp.

// A custom provider
const SparkPost gomail.ServiceProvider = 100
err := mail.RegisterProvider(SparkPost, mySparkPostProvider)

// A built-in provider with a custom client (ie: SendGrid EU data residency)
client := sendgrid.NewSendClient(apiKey)
client.Request, _ = sendgrid.SetDataResidency(client.Request, "eu")
err = mail.RegisterProvider(gomail.SendGrid, gomail.NewSendGridProvider(client))

// A fake provider in your tests
err = mail.RegisterProvider(gomail.SMTP, fakeProvider)
Templates
htmlTemplate, _ := email.ParseHTMLTemplate("welcome.html") // {{.Styles}} is replaced with email.CSS, which is inlined
textTemplate, _ := email.ParseTextTemplate("welcome.txt")  // text/template: no HTML escaping
err := email.ApplyTemplates(htmlTemplate, textTemplate, data)
Configuration

A provider is loaded by StartUp for every service whose credentials are set.

Field Description
FromName, FromUsername, FromDomain Default sender (FromUsername and FromDomain are required)
AwsSesAccessID, AwsSesSecretKey AWS SES static credentials
AwsSesUseIAMRole Load AWS SES from the default credential chain instead of static keys
AwsSesRegion, AwsSesEndpoint, AwsSesConfigurationSet AWS SES region (default us-east-1), custom endpoint, and configuration set
MailgunAPIKey, MailgunDomain Mailgun credentials and sending domain (defaults to the domain of the from address)
MailgunAPIBase Mailgun API base URL (default US region; mailgun.APIBaseEU for the EU region)
MandrillAPIKey, PostmarkServerToken Mandrill and Postmark credentials
ResendAPIKey, SendGridAPIKey Resend and SendGrid credentials
SMTPHost, SMTPPort, SMTPUsername, SMTPPassword SMTP server (port defaults to 587; leave the username empty for a relay without auth)
SMTPImplicitTLS Connect with TLS from the start (always on for port 465)
AutoText, Important, TrackClicks, TrackOpens Defaults copied to every email created by NewEmail
EmailCSS Default CSS copied to every email (used by ParseHTMLTemplate)
MaxToRecipients, MaxCcRecipients, MaxBccRecipients Recipient limits (default 50 each)
MaxAttachmentSize Total attachment bytes per email (default 40 MiB, negative for no limit)
SendTimeout Maximum time for one provider send (default one minute, negative for no timeout)
StrictFeatures Return ErrUnsupportedFeature instead of logging a warning for unsupported features
Logger *slog.Logger for warnings (default slog.Default())
SMTP
  • Every send opens a new connection that honors the context deadline and cancellation
  • STARTTLS is used whenever the server offers it; set SMTPImplicitTLS (or port 465) for SMTPS
  • Server certificates are verified; credentials are never sent over an unencrypted connection (except to localhost)
  • PLAIN authentication is used, with LOGIN as a fallback for servers that only offer LOGIN (ie: Microsoft 365)
  • Use NewSMTPProvider with RegisterProvider for a custom tls.Config or EHLO name
Development Setup (Getting Started)

Install MAGE-X build tool for development:

# Install MAGE-X for development and building
go install github.com/mrz1836/mage-x/cmd/magex@latest
magex update:install
Library Deployment

This project uses goreleaser for streamlined binary and library deployment to GitHub. To get started, install it via:

brew install goreleaser

The release process is defined in the .goreleaser.yml configuration file.

Then create and push a new Git tag using:

magex version:bump bump=patch push=true branch=master

This process ensures consistent, repeatable releases with properly versioned artifacts and citation metadata.

Build Commands

View all build commands

magex help
GitHub Workflows

All workflows are driven by modular configuration in .github/env/ — no YAML editing required.

View all workflows and the control center →

Updating Dependencies

To update all dependencies (Go modules, linters, and related tools), run:

magex deps:update

This command ensures all dependencies are brought up to date in a single step, including Go modules and any managed tools. It is the recommended way to keep your development environment and CI in sync with the latest versions.


Examples & Tests

All unit tests and fuzz tests run via GitHub Actions and use Go version 1.26.x. View the configuration file.

Run all tests (fast):

magex test

Run all tests with race detector (slower):

magex test:race

Run the fuzz tests:

magex test:fuzz

Benchmarks

Run the Go benchmarks:

magex bench

Code Standards

Read more about this Go project's code standards.


🤖 AI Usage & Assistant Guidelines

Read the AI Usage & Assistant Guidelines for details on how AI is used in this project and how to interact with AI assistants.


Maintainers

MrZ
MrZ

Contributing

View the contributing guidelines and please follow the code of conduct.

How can I help?

All kinds of contributions are welcome 🙌! The most basic way to show your support is to star 🌟 the project, or to raise issues 💬. You can also support this project by becoming a sponsor on GitHub 👏 or by making a bitcoin donation to ensure this journey continues indefinitely! 🚀

Stars


License

License

Documentation

Overview

Package gomail is a lightweight email package with multi-provider support

Index

Examples

Constants

This section is empty.

Variables

View Source
var (
	// Config validation errors
	ErrMissingFromUsername = errors.New("missing required field: from_username")
	ErrMissingFromDomain   = errors.New("missing required field: from_domain")
	ErrNoServiceProvider   = errors.New("attempted to startup the email service provider(s) however there's no available service provider")
	ErrNilProvider         = errors.New("provider cannot be nil")

	// Email validation errors
	ErrMissingSubject          = errors.New("email is missing a subject")
	ErrMissingContent          = errors.New("email is missing content (plain & html)")
	ErrMissingRecipient        = errors.New("email is missing a recipient")
	ErrInvalidFromAddress      = errors.New("invalid FromAddress")
	ErrInvalidRecipient        = errors.New("invalid recipient address")
	ErrInvalidReplyToAddress   = errors.New("invalid ReplyToAddress")
	ErrInvalidHeader           = errors.New("invalid email header")
	ErrInvalidMetadata         = errors.New("invalid email metadata")
	ErrInvalidAttachment       = errors.New("invalid email attachment")
	ErrAttachmentsTooLarge     = errors.New("email attachments exceed the maximum allowed size")
	ErrInvalidListUnsubscribe  = errors.New("invalid List-Unsubscribe target")
	ErrProviderNotFound        = errors.New("service provider was not in the list of available service providers, email not sent")
	ErrMaxToRecipientsReached  = errors.New("max TO recipient limit reached")
	ErrMaxCcRecipientsReached  = errors.New("max CC recipient limit reached")
	ErrMaxBccRecipientsReached = errors.New("max BCC recipient limit reached")
	ErrUnsupportedFeature      = errors.New("email uses a feature the service provider does not support")

	// Provider errors
	ErrInvalidAWSResponse = errors.New("aws ses did not return expected valid response")
	ErrMailgunError       = errors.New("error from mailgun")
	ErrMessageNotSent     = errors.New("message status and not sent")
	ErrPostmarkError      = errors.New("error from postmark")
	ErrSendGridError      = errors.New("error from sendgrid")
	ErrResendError        = errors.New("error from resend")
	ErrSMTPError          = errors.New("error from smtp server")
)

Package-level sentinel errors to satisfy err113 linter rule

Functions

This section is empty.

Types

type Attachment

type Attachment struct {
	FileName   string    `json:"file_name" mapstructure:"file_name"`
	FileReader io.Reader `json:"-" mapstructure:"-"`
	FileType   string    `json:"file_type" mapstructure:"file_type"`
	Content    []byte    `json:"content,omitempty" mapstructure:"content"`
	ContentID  string    `json:"content_id,omitempty" mapstructure:"content_id"`
}

Attachment is the email file attachment.

Set either Content or FileReader. A FileReader can only be read once, so MailService.Send reads it into Content before sending; the email can then be retried or sent through another provider. Set ContentID to embed the attachment inline, referenced from the HTML as <img src="cid:ContentID">.

type Email

type Email struct {
	Attachments     []Attachment     `json:"attachments" mapstructure:"attachments"`
	CSS             []byte           `json:"css" mapstructure:"css"`
	ProviderOptions []ProviderOption `json:"-" mapstructure:"-"` // per-provider request customizations (see With)
	Recipients      []string         `json:"recipients" mapstructure:"recipients"`
	RecipientsBcc   []string         `json:"recipients_bcc" mapstructure:"recipients_bcc"`
	RecipientsCc    []string         `json:"recipients_cc" mapstructure:"recipients_cc"`
	// Deprecated: Styles is not used; set CSS and use the {{.Styles}} placeholder with ParseHTMLTemplate.
	Styles           []byte            `json:"styles" mapstructure:"styles"`
	Tags             []string          `json:"tags" mapstructure:"tags"`
	Headers          map[string]string `json:"headers" mapstructure:"headers"`   // custom headers (ie: List-Unsubscribe); see SetHeader
	Metadata         map[string]string `json:"metadata" mapstructure:"metadata"` // key/value data returned in provider webhooks
	SendAt           time.Time         `json:"send_at,omitzero" mapstructure:"send_at"`
	FromAddress      string            `json:"from_address" mapstructure:"from_address"`
	FromName         string            `json:"from_name" mapstructure:"from_name"`
	HTMLContent      string            `json:"html_content" mapstructure:"html_content"`
	IdempotencyKey   string            `json:"idempotency_key" mapstructure:"idempotency_key"` // prevents duplicate sends on retry (provider dependent)
	PlainTextContent string            `json:"plain_text_content" mapstructure:"plain_text_content"`
	ReplyToAddress   string            `json:"reply_to_address" mapstructure:"reply_to_address"`
	Subject          string            `json:"subject" mapstructure:"subject"`
	AutoText         bool              `json:"auto_text" mapstructure:"auto_text"`
	Important        bool              `json:"important" mapstructure:"important"`
	TrackClicks      bool              `json:"track_clicks" mapstructure:"track_clicks"`
	TrackOpens       bool              `json:"track_opens" mapstructure:"track_opens"`
	ViewContentLink  bool              `json:"view_content_link" mapstructure:"view_content_link"`
}

Email represents the fields of the email to send

DO NOT CHANGE ORDER - Optimized for memory (maligned)

func (*Email) AddAttachment

func (e *Email) AddAttachment(name, fileType string, reader io.Reader)

AddAttachment adds a new attachment read from the reader

Example

ExampleEmail_AddAttachment example using the AddAttachment()

service := new(MailService)
service.FromUsername = testUsernameEmail
service.FromName = testFromNameEmail
service.FromDomain = testDomainEmail

email := service.NewEmail()
email.AddAttachment("testName", "testType", strings.NewReader("contents"))

fmt.Printf("attachment: %s", email.Attachments[0].FileName)
Output:
attachment: testName

func (*Email) AddAttachmentBytes added in v1.6.0

func (e *Email) AddAttachmentBytes(name, fileType string, content []byte)

AddAttachmentBytes adds a new attachment with the given content

func (*Email) AddInlineAttachment added in v1.6.0

func (e *Email) AddInlineAttachment(name, fileType, contentID string, content []byte)

AddInlineAttachment adds an attachment embedded in the HTML body, referenced as <img src="cid:contentID">

func (*Email) ApplyTemplates added in v0.0.4

func (e *Email) ApplyTemplates(htmlTemplate *template.Template, textTemplate TemplateExecutor, emailData any) (err error)

ApplyTemplates will take the template files and process them with the email data (can be e or overridden).

Use ParseTextTemplate for the text template: a plain-text template parsed with html/template (ie: ParseTemplate) has its output HTML-escaped, so for backwards compatibility that output is unescaped here. An HTML template from ParseHTMLTemplate has its CSS inlined after it is executed.

func (*Email) ParseHTMLTemplate added in v0.0.5

func (e *Email) ParseHTMLTemplate(htmlLocation string) (htmlTemplate *template.Template, err error)

ParseHTMLTemplate parses an HTML template with style injection: the {{.Styles}} placeholder is replaced with the email CSS, and ApplyTemplates inlines the CSS into the rendered HTML (inlining after execution keeps template actions inside tables and attributes intact). This method returns the template which should be stored in memory for quick access

func (*Email) ParseTemplate added in v0.0.4

func (e *Email) ParseTemplate(filename string) (parsed *template.Template, err error)

ParseTemplate parses an HTML template file (html/template, so data is HTML-escaped). Use ParseTextTemplate for plain-text templates. This method returns the template which should be stored in memory for quick access

func (*Email) ParseTextTemplate added in v1.6.0

func (e *Email) ParseTextTemplate(filename string) (*texttemplate.Template, error)

ParseTextTemplate parses a plain-text template file (text/template, so data is not HTML-escaped) This method returns the template which should be stored in memory for quick access

func (*Email) SetHeader added in v1.6.0

func (e *Email) SetHeader(name, value string)

SetHeader sets a custom header, replacing any header with the same name (compared case-insensitively). Headers go-mail sets from the email fields (ie: From, To, Subject) are rejected when the email is sent.

func (*Email) SetListUnsubscribe added in v1.6.0

func (e *Email) SetListUnsubscribe(oneClick bool, targets ...string) error

SetListUnsubscribe sets the List-Unsubscribe header (RFC 2369) to the given https:, http: or mailto: targets. With oneClick, it also sets List-Unsubscribe-Post (RFC 8058), which requires an https: target. Gmail and Yahoo require one-click unsubscribe for bulk senders.

func (*Email) With added in v1.6.0

func (e *Email) With(opts ...ProviderOption) *Email

With adds provider options that customize the native request of a provider (ie: a PostmarkOption to set the MessageStream) and returns the email

type Feature added in v1.6.0

type Feature string

Feature is an optional email feature that not every provider supports

const (
	FeatureAutoText        Feature = "auto_text"         // Email.AutoText
	FeatureIdempotencyKey  Feature = "idempotency_key"   // Email.IdempotencyKey
	FeatureMetadata        Feature = "metadata"          // Email.Metadata
	FeatureSendAt          Feature = "send_at"           // Email.SendAt (never silently ignored)
	FeatureTags            Feature = "tags"              // Email.Tags
	FeatureTrackClicks     Feature = "track_clicks"      // Email.TrackClicks
	FeatureTrackOpens      Feature = "track_opens"       // Email.TrackOpens
	FeatureViewContentLink Feature = "view_content_link" // Email.ViewContentLink
)

Optional email features, checked against the provider before every send

type FeatureSupporter added in v1.6.0

type FeatureSupporter interface {
	SupportsFeature(feature Feature) bool
}

FeatureSupporter is optionally implemented by a Provider to report which optional features it supports. MailService logs a warning (or, with StrictFeatures, returns ErrUnsupportedFeature) when an email requests a feature the provider does not support. Providers that do not implement FeatureSupporter are assumed to support every feature.

type MailService

type MailService struct {
	AvailableProviders []ServiceProvider `json:"available_providers" mapstructure:"available_providers"` // list of providers that loaded successfully
	EmailCSS           []byte            `json:"email_css" mapstructure:"email_css"`                     // default css pre-parsed into bytes
	Logger             *slog.Logger      `json:"-" mapstructure:"-"`                                     // logger for warnings (default: slog.Default())

	AwsSesAccessID         string        `json:"aws_ses_access_id" mapstructure:"aws_ses_access_id"`                 // aws iam access id for ses service
	AwsSesConfigurationSet string        `json:"aws_ses_configuration_set" mapstructure:"aws_ses_configuration_set"` // optional ses configuration set (ie: for open/click tracking events)
	AwsSesEndpoint         string        `json:"aws_ses_endpoint" mapstructure:"aws_ses_endpoint"`                   // ie: https://email.us-east-1.amazonaws.com
	AwsSesSecretKey        string        `json:"aws_ses_secret_key" mapstructure:"aws_ses_secret_key"`               // aws iam secret key for corresponding access id
	AwsSesRegion           string        `json:"aws_ses_region" mapstructure:"aws_ses_region"`                       // AWS region
	FromDomain             string        `json:"from_domain" mapstructure:"from_domain"`                             // ie: example.com
	FromName               string        `json:"from_name" mapstructure:"from_name"`                                 // ie: No Reply
	FromUsername           string        `json:"from_username" mapstructure:"from_username"`                         // ie: no-reply
	MailgunAPIBase         string        `json:"mailgun_api_base" mapstructure:"mailgun_api_base"`                   // optional mailgun api base (ie: https://api.eu.mailgun.net for the EU region)
	MailgunAPIKey          string        `json:"mailgun_api_key" mapstructure:"mailgun_api_key"`                     // mailgun api key
	MailgunDomain          string        `json:"mailgun_domain" mapstructure:"mailgun_domain"`                       // optional mailgun sending domain (ie: mg.example.com); defaults to the from address domain
	MandrillAPIKey         string        `json:"mandrill_api_key" mapstructure:"mandrill_api_key"`                   // mandrill api key
	PostmarkServerToken    string        `json:"postmark_server_token" mapstructure:"postmark_server_token"`         // ie: abc123...
	ResendAPIKey           string        `json:"resend_api_key" mapstructure:"resend_api_key"`                       // resend api key (ie: re_xxxx...)
	SMTPHost               string        `json:"smtp_host" mapstructure:"smtp_host"`                                 // ie: example.com
	SMTPPassword           string        `json:"smtp_password" mapstructure:"smtp_password"`                         // ie: secretPassword
	SendGridAPIKey         string        `json:"sendgrid_api_key" mapstructure:"sendgrid_api_key"`                   // sendgrid api key
	SMTPUsername           string        `json:"smtp_username" mapstructure:"smtp_username"`                         // ie: testuser (leave empty for a relay without authentication)
	MaxAttachmentSize      int64         `json:"max_attachment_size" mapstructure:"max_attachment_size"`             // max total attachment bytes per email (0: 40 MiB, negative: unlimited)
	SendTimeout            time.Duration `json:"send_timeout" mapstructure:"send_timeout"`                           // max time for one provider send (0: 1 minute, negative: none)
	MaxBccRecipients       int           `json:"max_bcc_recipients" mapstructure:"max_bcc_recipients"`               // max amount for BCC
	MaxCcRecipients        int           `json:"max_cc_recipients" mapstructure:"max_cc_recipients"`                 // max amount for CC
	MaxToRecipients        int           `json:"max_to_recipients" mapstructure:"max_to_recipients"`                 // max amount for TO
	SMTPPort               int           `json:"smtp_port" mapstructure:"smtp_port"`                                 // ie: 587 (default), 465 (implicit TLS) or 25
	AutoText               bool          `json:"auto_text" mapstructure:"auto_text"`                                 // whether to automatically generate a text part for messages that are not given text
	Important              bool          `json:"important" mapstructure:"important"`                                 // whether this message is important, and should be delivered ahead of non-important messages
	TrackClicks            bool          `json:"track_clicks" mapstructure:"track_clicks"`                           // whether to turn on click tracking for the message
	TrackOpens             bool          `json:"track_opens" mapstructure:"track_opens"`                             // whether to turn on open tracking for the message
	AwsSesUseIAMRole       bool          `json:"aws_ses_use_iam_role" mapstructure:"aws_ses_use_iam_role"`           // load AWS SES using the default credential chain (IAM role) instead of static access keys
	SMTPImplicitTLS        bool          `json:"smtp_implicit_tls" mapstructure:"smtp_implicit_tls"`                 // connect to the SMTP server over TLS (SMTPS); always on for port 465
	StrictFeatures         bool          `json:"strict_features" mapstructure:"strict_features"`                     // return ErrUnsupportedFeature instead of logging a warning when a provider does not support a requested feature
	// contains filtered or unexported fields
}

MailService is the configuration to use for loading the service and provider's clients

Secrets (API keys, tokens and passwords) are redacted when a MailService is marshaled to JSON or formatted with fmt/slog.

DO NOT CHANGE ORDER - Optimized for memory (maligned)

func (MailService) GoString added in v1.6.0

func (m MailService) GoString() string

GoString returns the service with every secret redacted (used by %#v)

func (MailService) MarshalJSON added in v1.6.0

func (m MailService) MarshalJSON() ([]byte, error)

MarshalJSON marshals the service with every secret redacted

func (*MailService) NewEmail

func (m *MailService) NewEmail() (email *Email)

NewEmail creates a new email using defaults from the service configuration

Example

ExampleMailService_NewEmail example using the NewEmail()

service := new(MailService)
service.FromUsername = testUsernameEmail
service.FromName = testFromNameEmail
service.FromDomain = testDomainEmail

email := service.NewEmail()
fmt.Printf("new email with from address: %s", email.FromAddress)
Output:
new email with from address: no-reply@example.com

func (*MailService) RegisterProvider added in v1.6.0

func (m *MailService) RegisterProvider(id ServiceProvider, provider Provider) error

RegisterProvider registers a provider under the given ID, replacing any provider already registered under it, and adds the ID to AvailableProviders.

Use it to add a custom provider (with your own ServiceProvider value), to supply a built-in provider with a custom client (ie: a SendGrid client with EU data residency), or to replace a provider with a fake in tests. Register providers before sending; registration is not safe to run concurrently with sends.

func (*MailService) Send added in v1.6.0

func (m *MailService) Send(ctx context.Context, email *Email, providers ...ServiceProvider) (*SendResult, error)

Send validates and sends an email, returning the provider's message id.

With several providers, each is tried in order until one accepts the email (failover); with none, every available provider is tried in the order they were loaded. Failover resends the whole email, so a provider that fails after accepting it (ie: a timeout on the response) can cause a duplicate.

Reader-based attachments are read into Attachment.Content first, so the same email can be retried or sent again.

func (*MailService) SendEmail

func (m *MailService) SendEmail(ctx context.Context, email *Email, provider ServiceProvider) error

SendEmail will send an email using the given provider

func (*MailService) StartUp

func (m *MailService) StartUp() (err error)

StartUp is fired once to load the email service.

A provider is loaded for every service with credentials configured. Calling StartUp again is safe, and a provider already registered with RegisterProvider (ie: a custom client or a test fake) is kept.

func (MailService) String added in v1.6.0

func (m MailService) String() string

String returns the service with every secret redacted (used by %v and %+v)

type MailgunClient added in v1.7.0

type MailgunClient interface {
	Send(ctx context.Context, message mailgun.Message) (mtypes.SendMessageResponse, error)
}

MailgunClient is the Mailgun API used by MailgunProvider; *mailgun.Client satisfies it

type MailgunOption added in v1.7.0

type MailgunOption func(message *mailgun.PlainMessage)

MailgunOption customizes the Mailgun message (ie: template, test mode, require TLS)

func (MailgunOption) ServiceProvider added in v1.7.0

func (MailgunOption) ServiceProvider() ServiceProvider

ServiceProvider returns Mailgun

type MailgunProvider added in v1.7.0

type MailgunProvider struct {
	// contains filtered or unexported fields
}

MailgunProvider sends email through Mailgun.

Tags become Mailgun tags (at most 10 per email) and Metadata becomes user variables, which Mailgun returns in webhooks and events. Open and click tracking are always set explicitly from the email, so the domain defaults do not apply.

Mailgun detects an attachment's content type from its file name, and uses the file name as the content id of an inline attachment, so inline attachments are sent with their ContentID as the file name (use a content id with an extension, ie: logo.png, so the image type is detected).

func NewMailgunProvider added in v1.7.0

func NewMailgunProvider(client MailgunClient, domain string) *MailgunProvider

NewMailgunProvider creates a Mailgun provider, ie: NewMailgunProvider(mailgun.NewMailgun(key), "mg.example.com").

The domain is the Mailgun sending domain; when empty, the domain of each email's FromAddress is used. For the EU region, set the client's API base with client.SetAPIBase(mailgun.APIBaseEU).

func (*MailgunProvider) Send added in v1.7.0

func (p *MailgunProvider) Send(ctx context.Context, email *Email) (*SendResult, error)

Send sends the email through Mailgun; the result MessageID is the Mailgun message id (ie: <20260101.1@mg.example.com>) and Response is the mtypes.SendMessageResponse

func (*MailgunProvider) SupportsFeature added in v1.7.0

func (p *MailgunProvider) SupportsFeature(feature Feature) bool

SupportsFeature reports whether Mailgun supports the feature

type MandrillClient added in v1.6.0

type MandrillClient interface {
	MessageSendWithOptions(message gochimp.Message, opts gochimp.MessageSendOptions) ([]gochimp.SendResponse, error)
}

MandrillClient is the Mandrill API used by MandrillProvider; *gochimp.MandrillAPI satisfies it

type MandrillOption added in v1.6.0

type MandrillOption func(message *gochimp.Message)

MandrillOption customizes the Mandrill message (ie: merge vars, subaccount)

func (MandrillOption) ServiceProvider added in v1.6.0

func (MandrillOption) ServiceProvider() ServiceProvider

ServiceProvider returns Mandrill

type MandrillProvider added in v1.6.0

type MandrillProvider struct {
	// contains filtered or unexported fields
}

MandrillProvider sends email through Mandrill (Mailchimp Transactional).

Messages are sent synchronously so rejected recipients are reported as errors. Recipients are not preserved: each To recipient only sees their own address (set PreserveRecipients with a MandrillOption to change this).

func NewMandrillProvider added in v1.6.0

func NewMandrillProvider(client MandrillClient) *MandrillProvider

NewMandrillProvider creates a Mandrill provider

func (*MandrillProvider) Send added in v1.6.0

func (p *MandrillProvider) Send(ctx context.Context, email *Email) (*SendResult, error)

Send sends the email through Mandrill; the result MessageID is the id of the first recipient's message and Response holds every []gochimp.SendResponse

func (*MandrillProvider) SupportsFeature added in v1.6.0

func (p *MandrillProvider) SupportsFeature(feature Feature) bool

SupportsFeature reports whether Mandrill supports the feature

type PostmarkClient added in v1.6.0

type PostmarkClient interface {
	SendEmail(ctx context.Context, email postmark.Email) (postmark.EmailResponse, error)
}

PostmarkClient is the Postmark API used by PostmarkProvider; *postmark.Client satisfies it

type PostmarkOption added in v1.6.0

type PostmarkOption func(email *postmark.Email)

PostmarkOption customizes the Postmark email (ie: MessageStream)

func (PostmarkOption) ServiceProvider added in v1.6.0

func (PostmarkOption) ServiceProvider() ServiceProvider

ServiceProvider returns Postmark

type PostmarkProvider added in v1.6.0

type PostmarkProvider struct {
	// contains filtered or unexported fields
}

PostmarkProvider sends email through Postmark.

Postmark supports a single tag per email, so multiple Tags are joined with a comma into one tag. Use a PostmarkOption to set the MessageStream.

func NewPostmarkProvider added in v1.6.0

func NewPostmarkProvider(client PostmarkClient) *PostmarkProvider

NewPostmarkProvider creates a Postmark provider

func (*PostmarkProvider) Send added in v1.6.0

func (p *PostmarkProvider) Send(ctx context.Context, email *Email) (*SendResult, error)

Send sends the email through Postmark; the result MessageID is the Postmark message id

func (*PostmarkProvider) SupportsFeature added in v1.6.0

func (p *PostmarkProvider) SupportsFeature(feature Feature) bool

SupportsFeature reports whether Postmark supports the feature

type Provider added in v1.6.0

type Provider interface {
	Send(ctx context.Context, email *Email) (*SendResult, error)
}

Provider sends an email through a single email service.

Every built-in service (AWS SES, Mailgun, Mandrill, Postmark, SendGrid, Resend and SMTP) implements Provider, and custom providers (or test fakes) can be added to a MailService with RegisterProvider. The email passed to Send has already been validated by MailService.

type ProviderOption added in v1.6.0

type ProviderOption interface {
	ServiceProvider() ServiceProvider
}

ProviderOption customizes the native request a single provider builds for an email. Options are applied after go-mail has mapped the Email onto the provider's request, so they can set anything the provider SDK exposes. Options for other providers are ignored, so one Email can carry options for several providers (useful with failover).

Custom providers may define their own ProviderOption types and read them from Email.ProviderOptions.

type ResendClient added in v1.6.0

type ResendClient interface {
	SendWithOptions(ctx context.Context, params *resend.SendEmailRequest, options *resend.SendEmailOptions) (*resend.SendEmailResponse, error)
}

ResendClient is the Resend API used by ResendProvider; the Emails service of a *resend.Client (*resend.EmailsSvcImpl) satisfies it

type ResendOption added in v1.6.0

type ResendOption func(request *resend.SendEmailRequest)

ResendOption customizes the Resend send request (ie: template, topic)

func (ResendOption) ServiceProvider added in v1.6.0

func (ResendOption) ServiceProvider() ServiceProvider

ServiceProvider returns Resend

type ResendProvider added in v1.6.0

type ResendProvider struct {
	// contains filtered or unexported fields
}

ResendProvider sends email through Resend.

Tags and Metadata become Resend tags (sanitized to the characters Resend allows). Open/click tracking is configured per domain in Resend, not per email.

func NewResendProvider added in v1.6.0

func NewResendProvider(client ResendClient) *ResendProvider

NewResendProvider creates a Resend provider, ie: NewResendProvider(resend.NewClient(key).Emails)

func (*ResendProvider) Send added in v1.6.0

func (p *ResendProvider) Send(ctx context.Context, email *Email) (*SendResult, error)

Send sends the email through Resend; the result MessageID is the Resend email id

func (*ResendProvider) SupportsFeature added in v1.6.0

func (p *ResendProvider) SupportsFeature(feature Feature) bool

SupportsFeature reports whether Resend supports the feature (Resend builds the plain-text part from the HTML natively, so auto text is supported)

type SESClient added in v1.6.0

type SESClient interface {
	SendRawEmail(ctx context.Context, params *ses.SendRawEmailInput, optFns ...func(*ses.Options)) (*ses.SendRawEmailOutput, error)
}

SESClient is the AWS SES API used by SESProvider; *ses.Client satisfies it

type SESOption added in v1.6.0

type SESOption func(input *ses.SendRawEmailInput)

SESOption customizes the AWS SES SendRawEmail request (ie: FromArn, Tags)

func (SESOption) ServiceProvider added in v1.6.0

func (SESOption) ServiceProvider() ServiceProvider

ServiceProvider returns AwsSes

type SESProvider added in v1.6.0

type SESProvider struct {
	// contains filtered or unexported fields
}

SESProvider sends email through AWS SES (SendRawEmail).

Tags and Metadata become SES message tags. Open/click tracking is configured on an SES configuration set rather than per email.

func NewSESProvider added in v1.6.0

func NewSESProvider(client SESClient, configurationSet string) *SESProvider

NewSESProvider creates an AWS SES provider; configurationSet is optional (use it for event publishing, ie: open/click tracking)

func (*SESProvider) Send added in v1.6.0

func (p *SESProvider) Send(ctx context.Context, email *Email) (*SendResult, error)

Send sends the email through AWS SES; the result MessageID is the SES message id

func (*SESProvider) SupportsFeature added in v1.6.0

func (p *SESProvider) SupportsFeature(feature Feature) bool

SupportsFeature reports whether AWS SES supports the feature

type SMTPConfig added in v1.6.0

type SMTPConfig struct {
	TLSConfig   *tls.Config // optional TLS settings (ServerName defaults to Host)
	Host        string      // ie: smtp.example.com
	LocalName   string      // name sent with EHLO/HELO (default: localhost)
	Password    string      // ie: secretPassword
	Username    string      // when empty, no authentication is attempted (ie: a local relay)
	Port        int         // default 587, or 465 when ImplicitTLS is set
	ImplicitTLS bool        // connect over TLS (SMTPS); always on for port 465. Otherwise STARTTLS is used when offered
}

SMTPConfig configures an SMTPProvider

DO NOT CHANGE ORDER - Optimized for memory (maligned)

type SMTPProvider added in v1.6.0

type SMTPProvider struct {
	// contains filtered or unexported fields
}

SMTPProvider sends email over SMTP.

Every send opens a new connection that honors the context deadline and cancellation. STARTTLS is used whenever the server offers it, and credentials are never sent over an unencrypted connection (except to localhost). PLAIN authentication is preferred, with LOGIN as a fallback for servers that only offer LOGIN.

func NewSMTPProvider added in v1.6.0

func NewSMTPProvider(config SMTPConfig) *SMTPProvider

NewSMTPProvider creates an SMTP provider from the given configuration

func (*SMTPProvider) Send added in v1.6.0

func (p *SMTPProvider) Send(ctx context.Context, email *Email) (*SendResult, error)

Send sends the email over SMTP; the result MessageID is the Message-ID header

func (*SMTPProvider) SupportsFeature added in v1.6.0

func (p *SMTPProvider) SupportsFeature(_ Feature) bool

SupportsFeature reports whether SMTP supports the feature (it supports none)

type SendGridClient added in v1.6.0

type SendGridClient interface {
	SendWithContext(ctx context.Context, email *sgmail.SGMailV3) (*rest.Response, error)
}

SendGridClient is the SendGrid API used by SendGridProvider; *sendgrid.Client satisfies it

type SendGridOption added in v1.6.0

type SendGridOption func(message *sgmail.SGMailV3)

SendGridOption customizes the SendGrid message (ie: template id, ASM group)

func (SendGridOption) ServiceProvider added in v1.6.0

func (SendGridOption) ServiceProvider() ServiceProvider

ServiceProvider returns SendGrid

type SendGridProvider added in v1.6.0

type SendGridProvider struct {
	// contains filtered or unexported fields
}

SendGridProvider sends email through SendGrid.

Tags become categories and Metadata becomes custom args. Open and click tracking are always set explicitly from the email, so the account defaults do not apply.

func NewSendGridProvider added in v1.6.0

func NewSendGridProvider(client SendGridClient) *SendGridProvider

NewSendGridProvider creates a SendGrid provider.

A *sendgrid.Client stores each request body on itself while sending, so it is not safe for concurrent use; it is wrapped so every send uses its own copy of the request (keeping any custom host, subuser or data residency setting).

func (*SendGridProvider) Send added in v1.6.0

func (p *SendGridProvider) Send(ctx context.Context, email *Email) (*SendResult, error)

Send sends the email through SendGrid; the result MessageID is the X-Message-Id response header and Response is the *rest.Response

func (*SendGridProvider) SupportsFeature added in v1.6.0

func (p *SendGridProvider) SupportsFeature(feature Feature) bool

SupportsFeature reports whether SendGrid supports the feature

type SendResult added in v1.6.0

type SendResult struct {
	Response  any             // native provider response (ie: postmark.EmailResponse, *rest.Response)
	MessageID string          // provider message id (the Message-ID header for SMTP)
	Provider  ServiceProvider // the provider that accepted the email
}

SendResult describes an email that was accepted by a provider

DO NOT CHANGE ORDER - Optimized for memory (maligned)

type ServiceProvider

type ServiceProvider int

ServiceProvider is the provider

const (
	AwsSes   ServiceProvider = iota // AWS SES Email Service
	Mandrill                        // Mandrill Email Service
	Postmark                        // Postmark Email Service
	SMTP                            // SMTP Email Service
	SendGrid                        // SendGrid Email Service
	Resend                          // Resend Email Service
	Mailgun                         // Mailgun Email Service
)

Email Service Providers

func (ServiceProvider) String added in v1.3.0

func (s ServiceProvider) String() string

String returns the human-readable name of the service provider

type TemplateExecutor added in v1.6.0

type TemplateExecutor interface {
	ExecuteTemplate(wr io.Writer, name string, data any) error
	Name() string
}

TemplateExecutor is a parsed template; both *text/template.Template and *html/template.Template implement it

Directories

Path Synopsis
Package main is examples using the go-mail package
Package main is examples using the go-mail package

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL
⌂ 换网址