Skip to content

Repository files navigation

gas-email

Test Go Reference Go Version License

Email service for the Gas ecosystem. Provides a gas.EmailProvider implementation backed by AWS SES, plus a test mock for use in unit tests.

Install

go get github.com/gasmod/gas-email

Backends

Backend Package Use case
SES github.com/gasmod/gas-email/ses Production (AWS SES / LocalStack)

The SES backend implements gas.Service and gas.EmailProvider.

Usage

SES backend

package main

import (
	"github.com/gasmod/gas"
	emailses "github.com/gasmod/gas-email/ses"
)

func main() {
	app := gas.NewApp(
		gas.WithSingletonService[*emailses.Service](emailses.New()),
		// ...
	)

	app.Run()
}

With custom configuration:

cfg := &emailses.Config{
	Email: emailses.Settings{
		Region:    "eu-west-1",
		FromEmail: "noreply@example.com",
		Endpoint:  "http://localhost:4566", // LocalStack
	},
}

emailses.New(emailses.WithConfig(cfg))

With a pre-configured AWS client:

emailses.New(emailses.WithClient(mySESClient))

If your DI container resolves a concrete template provider type rather than the gas.TemplateProvider interface, use the generic variant:

emailses.NewWithCustomProvider[*mytemplates.Service]()

Dependency injection

Services receive the email sender through gas.EmailProvider via constructor injection:

type Service struct {
	email gas.EmailProvider
}

func New(email gas.EmailProvider) *Service {
	return &Service{email: email}
}

func (s *Service) Init() error {
	ctx := context.Background()
	_ = s.email.Send(ctx, &gas.Email{
		To:      []string{"user@example.com"},
		Subject: "Welcome",
		HTMLBody: "<h1>Hello!</h1>",
	})
	return nil
}

Sending emails

err := s.email.Send(ctx, &gas.Email{
	To:       []string{"alice@example.com"},
	Cc:       []string{"bob@example.com"},
	Bcc:      []string{"log@example.com"},
	Subject:  "Order Confirmation",
	HTMLBody: "<h1>Thank you for your order</h1>",
	TextBody: "Thank you for your order",
	ReplyTo:  "support@example.com",
	From:     "orders@example.com", // overrides cfg.Email.FromEmail
})

Sending from templates

Templates are fetched from the injected gas.TemplateProvider, parsed with Go's html/template (for HTML) or text/template (for subject and text), and executed with the provided data:

err := s.email.SendFromTemplate(ctx, &gas.TemplatedEmail{
	SubjectTemplate: "welcome-subject",
	HTMLTemplate:    "welcome-html",
	TextTemplate:    "welcome-text",
	Data:            map[string]string{"Name": "Alice"},
	Email: gas.Email{
		To: []string{"alice@example.com"},
	},
})

All three template fields are optional. If a template field is empty, the corresponding field on the embedded Email struct is used as-is.

Config

If WithConfig is not provided, the backend automatically binds configuration from the gas.ConfigProvider injected via DI. This lets you drive email settings from environment variables or a config file without any explicit wiring.

SES config

Field Default Description
Email.Region AWS region (required)
Email.FromEmail Default sender address (required)
Email.Endpoint Custom endpoint URL (e.g. LocalStack); empty = default AWS
Email.AccessKeyID Static AWS access key; empty = default credential chain
Email.SecretAccessKey Static AWS secret key; empty = default credential chain

Readiness

The SES Service implements gas.ReadyReporter. CheckReady returns email.ErrClosed once Close has been invoked (so a Kubernetes readinessProbe depools the pod during shutdown/drain) and nil otherwise. HealthReporter is intentionally not implemented — the SES client is stateless and has no broken-state condition that a process restart would resolve.

Sentinel Errors

The root email package defines sentinel errors used by all backends:

email.ErrClosed    // returned when an operation is attempted on a closed service
email.IsErrClosed(err) // helper: errors.Is(err, ErrClosed)

Testing

The emailtest package provides a mock implementation of gas.EmailProvider:

import "github.com/gasmod/gas-email/emailtest"

mock := &emailtest.MockEmail{}
mock.SendFn = func(ctx context.Context, msg *gas.Email) error {
	return nil
}

// pass mock as gas.EmailProvider
// assert calls:
if mock.CallCount("Send") != 1 {
	t.Error("expected one Send call")
}

About

Email service for the Gas ecosystem. Provides a gas.EmailProvider implementation backed by AWS SES, plus a test mock for use in unit tests.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages