Skip to content

Bring-your-own-key email: two ways to build the mailer

The two mailer strategies for a team's own email provider, laravel and dsn, and how they compare.

When a form uses a team’s own email provider, quickforms builds a mailer for that send from the team’s decrypted keys. There are two implementations. Both are in the codebase, both are tested, and you pick one with an env variable:

QUICKFORMS_MAIL_TRANSPORT=laravel   # default
QUICKFORMS_MAIL_TRANSPORT=dsn

Everything else stays the same either way: the delivery log, retries, sandbox previews and the provider UI/API.

laravel dsn
Code app/Services/Mail/LaravelMailerFactory.php app/Services/Mail/DsnMailerFactory.php
How Mail::build([...]) with Laravel’s own resend, postmark, mailgun, ses and smtp drivers, the same config shape as config/mail.php Mail::build(['transport' => 'dsn', 'dsn' => 'postmark+api://KEY@default']) through a small dsn transport registered in AppServiceProvider
Mailchimp Transactional Not a Laravel driver, so it uses the DSN path Native (mandrill+api://)

What each transport ends up being

From tests/Feature/Quickforms/MailTransportsTest.php:

Provider laravel dsn
Resend Laravel ResendTransport (official resend/resend-php SDK) Symfony ResendApiTransport
Postmark Symfony PostmarkApiTransport Same
Mailgun Symfony MailgunHttpTransport (sends raw MIME) Symfony MailgunApiTransport (JSON API)
Amazon SES Laravel SesTransport (AWS SDK for PHP) Symfony SesApiAsyncAwsTransport (AsyncAws)
SMTP Symfony EsmtpTransport Same
Mailchimp Transactional Symfony MandrillApiTransport Same

Postmark, SMTP and Mailchimp Transactional are identical either way. The real differences are Resend, Mailgun and SES.

Laravel drivers (laravel)

Pros

  • It’s the Laravel way. Anyone who knows config/mail.php can read the mapping, and the platform mailer and tenant mailers are configured the same way.
  • Laravel maintains the drivers, so fixes and new options (for example Postmark message streams, SES options) arrive with framework upgrades.
  • Resend and SES go through the providers’ official SDKs.

Cons

  • Platform key fallback. When a key is missing from the array, Laravel’s drivers quietly use the platform’s keys from config/services.php. For Mailgun it swaps in the whole platform config if secret is absent. Without a guard, a tenant with a gap in their credentials would send through your account. quickforms guards this: IncompleteMailCredentials refuses to build a tenant mailer with any required key blank, and the SES session token is pinned to null. There’s a test for each strategy that sets platform keys and checks they are never used. The risk is that a future driver or option added without the guard reopens the hole.
  • Heavier dependencies. It needs resend/resend-php (about 0.4 MB) and aws/aws-sdk-php (about 69 MB in vendor). That’s fine on Laravel Cloud, but it’s a big package to carry for one driver.
  • Mailchimp Transactional still needs the DSN path, so there are two mechanisms in play.

Symfony DSNs (dsn)

Pros

  • No fallback possible. A DSN carries every credential, and Symfony has no notion of your platform keys, so a missing key fails instead of borrowing yours. (The same guard runs anyway, for a clearer error.)
  • One uniform mechanism for all six providers, Mailchimp Transactional included.
  • Light dependencies: the Symfony bridges and symfony/http-client together come to about 1.7 MB, and SES uses AsyncAws instead of the full AWS SDK.

Cons

  • Less familiar to Laravel developers, and it relies on a custom dsn transport registered in AppServiceProvider.
  • Credentials have to be URL-encoded into the DSN. The factory does this, and the SES and SMTP tests cover keys with /, + and @ in them.
  • A DSN is a single string holding secrets, so it should never be logged. The delivery log records the exception message, never the DSN itself.

Recommendation

Either is fine to ship, and both are fully tested. If you’d rather stay close to Laravel and keep up with framework changes for free, use laravel (the default) and keep the guard. If you’d rather have the lighter install and fallback-proof credentials by construction, use dsn. Once you’ve picked one, the other factory and its packages can be deleted:

  • Keeping laravel: you can drop the symfony/resend-mailer and symfony/amazon-mailer bridges. Keep symfony/mailchimp-mailer, plus the Postmark and Mailgun bridges that Laravel’s drivers use.
  • Keeping dsn: you can drop resend/resend-php and aws/aws-sdk-php.

Type to search…

↑↓ navigate↵ selectEsc close