Skip to content
CH SCShop classdrupal · intermediate · ~45 min · 5 steps

How to make Drupal send email reliably

Route Drupal's mail through an authenticated SMTP or API service instead of bare PHP mail, so password resets and notifications actually arrive.

August 10, 2026 · by Dane Petersen

Out of the box, Drupal hands mail to the web server’s PHP mail function and hopes. Gmail and Outlook treat mail from an unauthenticated web server the way you’d treat a stranger’s cooler left on your dock — politely, into the spam folder. The fix is routing mail through a real transactional service that signs what it sends. You’ll need drush, Composer access, and DNS control for your domain — and it goes much smoother if you’ve already set up SPF, DKIM, and DMARC.

Send a test and see where it lands

Establish the baseline before changing anything. Request a password reset for your own account and send yourself a test:

drush user:password-reset-url admin

Better: trigger an actual reset email from the login form to a Gmail address you control. Check where it lands and open the headers (“Show original” in Gmail). If you see spf=fail or no dkim= line at all, you’ve found why the contact form has been so quiet.

Pick a transactional mail service

You want a service built for application mail — password resets, receipts, notifications — not a newsletter tool. Postmark, SendGrid, Mailgun, Brevo, and Amazon SES all do the job; free tiers cover most small sites’ volume comfortably. Two things worth checking before you commit: that the service gives you SMTP credentials or a supported API, and that your host allows outbound SMTP at all — some platforms (Pantheon among them) push you toward the API route, which is fine and often faster. Sign up and note your credentials somewhere safer than a sticky note.

Install and configure the mail module

Drupal Symfony Mailer is the modern choice — it replaces Drupal’s aging mail system with the same mailer Symfony itself uses:

composer require drupal/symfony_mailer
drush pm:install symfony_mailer -y

Then at Configuration → System → Mailer, add a transport: choose SMTP, and enter the host, port (587 with TLS is the usual answer), and the credentials from your service. Set it as the default transport. If your service pushes its API instead, install its companion module the same way. Keep the password out of exported config — put the override in settings.php so it never lands in git:

$config['symfony_mailer.mailer_transport.smtp']['configuration']['pass'] = getenv('SMTP_PASSWORD');

Line up your DNS with the new sender

Your mail now leaves from the service’s servers, so your DNS has to vouch for them. In the service’s dashboard, find the domain verification page — it will hand you a DKIM record (sometimes two) and may ask for an SPF include like include:spf.example-mailer.com. Add them where your DNS lives, and make sure the site’s from-address uses your real domain, not the service’s. The service’s dashboard will show “verified” when the records propagate, usually within the hour.

Verify with a password-reset round trip

The proof is a real message through the real pipe. Request a password reset to your Gmail test address and open the headers again. You’re looking for three things: spf=pass, dkim=pass with your domain, and a Received line showing the mail went through your new service. Landed in the inbox with all three? You’re done — and the service’s dashboard now logs every send, so the next time someone says “I never got the email,” you’ll have an answer instead of a shrug.

That's the lesson. Back to the shop for more — or if this is the chore your organization never gets to,that's literally what we're for.