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.