Drupal + MailKite
Drupal uses PHP's mail() function by default, which is unreliable
for transactional email. The SMTP Authentication module routes
all site email through MailKite — DKIM-signed, deliverable, and logged.
What you need
- A verified domain with SPF + DKIM published
- Your API key (
mk_live_…) - Drupal 9+ with Composer
Install the SMTP module
terminal
# Install the SMTP module
composer require drupal/smtp
drush en smtp -y
# Configure via Drush (optional)
drush config-set smtp.settings smtp_on TRUE -y
drush config-set smtp.settings smtp_host smtp.mailkite.dev -y
drush config-set smtp.settings smtp_port 587 -y
drush config-set smtp.settings smtp_protocol tls -y
drush config-set smtp.settings smtp_username mailkite -y
drush config-set smtp.settings smtp_password "mk_live_..." -y Configure via admin UI
Go to Configuration → System → SMTP Authentication and fill in:
SMTP Authentication settings
# Drupal SMTP Authentication module settings
# Admin → Configuration → System → SMTP Authentication
SMTP server: smtp.mailkite.dev
SMTP port: 587
Use encrypted protocol: Yes (STARTTLS)
SMTP username: mailkite
SMTP password: mk_live_...
From address: notifications@yourdomain.com
From name: Your Drupal Site
Turn this module on: Yes Configure via settings.php
For code-managed configuration (recommended for teams), add to
settings.php or a settings override:
sites/default/settings.php
// settings.php — for configuration management / code-based setup
$config['smtp.settings']['smtp_on'] = TRUE;
$config['smtp.settings']['smtp_host'] = 'smtp.mailkite.dev';
$config['smtp.settings']['smtp_port'] = '587';
$config['smtp.settings']['smtp_protocol'] = 'tls';
$config['smtp.settings']['smtp_username'] = 'mailkite';
$config['smtp.settings']['smtp_password'] = 'mk_live_...';
$config['smtp.settings']['smtp_from'] = 'notifications@yourdomain.com';
$config['smtp.settings']['smtp_fromname'] = 'Your Drupal Site'; What gets sent through MailKite
- User registration — account creation and verification emails
- Password resets — "reset your password" links
- Content notifications — comment alerts, content updates
- Contact form submissions — messages from Drupal's contact form
- Module-generated email — any module that calls
drupal_mail()
Receive inbound email
For inbound email (e.g., creating content from email), create a custom module with a webhook controller:
mailkite_inbound module
<?php
// Drupal custom module: receive inbound email via MailKite webhook
// File: web/modules/custom/mailkite_inbound/mailkite_inbound.routing.yml
mailkite_inbound.receive:
path: '/webhooks/mailkite'
defaults:
_controller: '\Drupal\mailkite_inbound\Controller\InboundController::handle'
requirements:
_access: 'TRUE'
methods: [POST]
// File: web/modules/custom/mailkite_inbound/src/Controller/InboundController.php
namespace Drupal\mailkite_inbound\Controller;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
class InboundController {
public function handle(Request $request) {
$payload = json_decode($request->getContent(), TRUE);
// Verify signature
$sig = $request->server->get('HTTP_X_MAILKITE_SIGNATURE');
$secret = \Drupal::config('mailkite_inbound.settings')->get('webhook_secret');
$computed = hash_hmac('sha256', json_encode($payload), $secret);
if (!hash_equals($computed, $sig)) {
return new JsonResponse(['error' => 'invalid signature'], 401);
}
// Process: create a node, log, or trigger a reaction
\Drupal::logger('mailkite_inbound')->notice(
'Inbound email from @from: @subject',
['@from' => $payload['from'], '@subject' => $payload['subject']]
);
return new JsonResponse(['ok' => TRUE]);
}
}
Register the route and set your domain's webhook
to https://yoursite.com/webhooks/mailkite.
Troubleshooting
- Module not found — run
composer require drupal/smtpthendrush en smtp. The module isn't in Drupal core. - Emails going to spam — the
Fromaddress must be on a verified domain. Drupal defaults tosite@yoursite.comwhich may not pass our checks. - 535 Authentication failed — the password must be your
mk_live_…API key, not a Drupal user credential. - PHP mail() still used — ensure the SMTP module is enabled and the "Turn this module on" setting is checked. The module overrides
drupal_mail()only when active.
See the SMTP relay docs for the full connection reference, or Send API for building custom Drupal modules.