Skip to content

Add Mailtrap email transport#27873

Open
tsokolovs wants to merge 4 commits into
directus:mainfrom
tsokolovs:feat/mailtrap-email-transport
Open

Add Mailtrap email transport#27873
tsokolovs wants to merge 4 commits into
directus:mainfrom
tsokolovs:feat/mailtrap-email-transport

Conversation

@tsokolovs

@tsokolovs tsokolovs commented Jul 10, 2026

Copy link
Copy Markdown

What's Changed

Adds Mailtrap as a native option for EMAIL_TRANSPORT, alongside the existing sendmail, smtp, ses, and mailgun transports. It uses Mailtrap's official mailtrap package, which ships a Nodemailer transport (MailtrapTransport).

The transport supports all three Mailtrap modes:

  • Live sending via an API token.
  • Sandbox / Email Testing by capturing messages in a test inbox.
  • Bulk stream for high-volume sending.

Implementation mirrors the existing Mailgun transport in api/src/mailer.ts (lazy require, env-driven options). Options are only passed to the SDK when their env vars are set.

New environment variables

Variable Type Description
EMAIL_MAILTRAP_TOKEN string Mailtrap API token
EMAIL_MAILTRAP_SANDBOX boolean Send to a test inbox instead of delivering
EMAIL_MAILTRAP_INBOX_ID number Inbox ID used when sandbox is enabled
EMAIL_MAILTRAP_BULK boolean Use the bulk sending stream

Tested Scenarios

  • Unit test added for the new transport; api/src/mailer.test.ts passes (5/5), @directus/env passes (78/78).
  • Live sandbox send: message delivered to a Mailtrap test inbox (verified via the API).
  • Live production send: delivered to a real mailbox.
  • Bulk stream: 10 live messages sent via EMAIL_MAILTRAP_BULK=true, all succeeded.
  • ESLint + Prettier clean on changed files.

Review Notes / Questions / Concerns

  • Adding the mailtrap dependency pulls in axios, which dedupes qs to 6.15.2 in the lockfile. This is the only transitive change beyond the direct addition.

Checklist

Leave unchecked where not applicable

  • Tests added/updated
  • Documentation PR created in directus/docs Document Mailtrap email transport docs#768
  • OpenAPI updated
  • SDK (@directus/sdk) updated to reflect the changes
  • Types (@directus/types) updated to reflect the changes
  • GraphQL schema updated to reflect the changes
  • System data (@directus/system-data) updated for changes to system collections/fields/relations
  • Database migration added for schema/system changes
  • Environment variables documented for new/changed config
  • App translations added for new user-facing strings
  • Security implications apply

@tsokolovs

tsokolovs commented Jul 10, 2026

Copy link
Copy Markdown
Author

I've used an AI agent to create a PR for me (via the gh cli) to make it easier for me to ensure I've fulfilled all the guidelines outlined in contributing.md file. The code itself was written manually. Happy to answer all the questions you have.

@codecov

codecov Bot commented Jul 11, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 68.43%. Comparing base (68b4567) to head (adeb5aa).

Additional details and impacted files
@@           Coverage Diff           @@
##             main   #27873   +/-   ##
=======================================
  Coverage   68.42%   68.43%           
=======================================
  Files        2381     2381           
  Lines      164253   164270   +17     
  Branches    15209    15212    +3     
=======================================
+ Hits       112392   112411   +19     
+ Misses      51861    51859    -2     
Flag Coverage Δ
api 57.38% <100.00%> (+<0.01%) ⬆️
app 76.97% <ø> (ø)
composables 83.87% <ø> (ø)
constants 4.66% <ø> (ø)
create-directus-extension 96.55% <ø> (ø)
create-directus-project 98.43% <ø> (ø)
env 99.74% <100.00%> (+<0.01%) ⬆️
errors 96.17% <ø> (ø)
extensions 35.63% <ø> (ø)
extensions-registry 95.43% <ø> (ø)
extensions-sdk 14.37% <ø> (ø)
format-title 100.00% <ø> (ø)
memory 100.00% <ø> (ø)
pressure 77.63% <ø> (ø)
release-notes-generator 80.91% <ø> (ø)
schema-builder 81.42% <ø> (ø)
sdk 33.28% <ø> (ø)
storage 92.00% <ø> (ø)
storage-driver-azure 73.33% <ø> (ø)
storage-driver-cloudinary 80.62% <ø> (ø)
storage-driver-gcs 66.95% <ø> (ø)
storage-driver-local 69.76% <ø> (ø)
storage-driver-s3 52.16% <ø> (ø)
storage-driver-supabase 67.25% <ø> (ø)
system-data 32.42% <ø> (ø)
update-check 55.67% <ø> (ø)
utils 91.72% <ø> (ø)
validation 43.78% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@tsokolovs tsokolovs changed the title Add Mailtrap email transport 🤖🤖🤖 Add Mailtrap email transport Jul 14, 2026
@tsokolovs
tsokolovs force-pushed the feat/mailtrap-email-transport branch from 18c73ed to 23ab361 Compare July 20, 2026 07:23
Add a native `mailtrap` option for `EMAIL_TRANSPORT` using Mailtrap's official nodemailer transport. Supports live sending, the bulk stream, and the sandbox testing inbox via EMAIL_MAILTRAP_TOKEN, EMAIL_MAILTRAP_SANDBOX, EMAIL_MAILTRAP_INBOX_ID, and EMAIL_MAILTRAP_BULK.
Re-import getMailer in the Mailtrap test so the module-scoped transporter cache doesn't short-circuit the new branch, ensuring it actually executes under coverage.
@tsokolovs
tsokolovs force-pushed the feat/mailtrap-email-transport branch from 23ab361 to adeb5aa Compare July 21, 2026 06:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant