SwooshDomainRouter

SwooshDomainRouter is a small Swoosh adapter that delegates email delivery according to the exact domains of envelope recipients. It is intended for staged deployments where selected test domains should remain in a local mailbox while real recipients receive email through a production provider.

The package has no Phoenix or Ash dependency. A Phoenix application may expose the normal Swoosh local mailbox separately.

Installation

Add swoosh_domain_router to your list of dependencies in mix.exs:

{:swoosh_domain_router, "~> 0.1.0"}

Configuration

config :my_app, MyApp.Mailer,
adapter: SwooshDomainRouter.Adapter,
routes: [
[domains: ["example.com"], adapter: Swoosh.Adapters.Local]
],
fallback: [
adapter: Swoosh.Adapters.Resend,
api_key: System.fetch_env!("RESEND_API_KEY")
],
mixed_recipients: :error
config :swoosh, :api_client, Swoosh.ApiClient.Req
config :swoosh, local: true

The router does not depend on any delivery provider. Replace :fallback with any Swoosh adapter configuration:

# Static Amazon SES credentials; the consuming application must include :gen_smtp.
fallback: [
adapter: Swoosh.Adapters.AmazonSES,
region: System.fetch_env!("AWS_SES_REGION"),
access_key: System.fetch_env!("AWS_SES_ACCESS_KEY_ID"),
secret: System.fetch_env!("AWS_SES_SECRET_ACCESS_KEY")
]
# ExAws-managed SES credentials, for instance-role or service-specific config.
fallback: [
adapter: Swoosh.Adapters.ExAwsAmazonSES
]

Provider-specific optional dependencies belong in the consuming application. Both Swoosh SES adapters require {:gen_smtp, "~> 1.0"}; the ExAws variant also requires :ex_aws.

The router evaluates all to, cc, and bcc recipients. Domain matching is case-insensitive and exact: user@example.com matches example.com, while user@example.com.attacker.test does not.

Messages containing recipients for multiple destinations return {:error, :mixed_recipient_routes}. Splitting such an email is intentionally not supported because a copied or blind-copied recipient should not change the delivery safety policy.