Build email automation in n8n that actually works
n8n's built-in email nodes use basic SMTP or IMAP polling — slow, unreliable, and no structured data. This tutorial shows how to connect n8n to MailKite for both sending (SMTP node with DKIM signing) and receiving (webhook trigger with clean JSON payload), so your email automation workflows fire in seconds, not minutes.
n8n is the open-source alternative to Zapier. You self-host it, you own the data, and you can build workflows that Zapier can’t — custom code nodes, branching logic, sub-workflows. But n8n’s email nodes have the same problem as every self-hosted tool: the SMTP and IMAP configuration is basic, and the “read email” trigger polls over IMAP.
MailKite fixes both sides. Send email through the SMTP node with DKIM signing and delivery logs. Receive inbound email through a webhook trigger that fires the moment the message arrives — no IMAP polling, no dropped connections, clean JSON.
The problem with n8n’s default email nodes
n8n has two email-related nodes:
-
SMTP Send — sends email via any SMTP server. Works, but no DKIM signing, no delivery tracking, no retries.
-
Email Trigger (IMAP) — polls an inbox over IMAP. Checks for new messages every few seconds. Problems: IMAP connections drop silently, Gmail rate-limits polling, Outlook’s IMAP has quirks, and you get raw MIME instead of structured data.
For basic notifications, this works. For production automation — support routing, order processing, lead capture — you need reliability and structure.
The fix: MailKite for both directions
1. Verify your domain in MailKite
Add your domain to the MailKite dashboard. Publish the DNS records (MX, SPF, DKIM, DMARC). Under 5 minutes.
2. Send email: SMTP node
In your n8n workflow, add an SMTP Send node:
| Setting | Value |
|---|---|
| Host | smtp.mailkite.dev |
| Port | 587 |
| User | mailkite |
| Password | Your API key (mk_live_…) |
| SSL/TLS | true (STARTTLS) |
| From | notifications@yourdomain.com |
Map the To, Subject, and Text/HTML fields from previous nodes. The email is sent through MailKite — DKIM-signed, logged, and trackable.
3. Receive email: Webhook trigger
Replace the IMAP trigger with a Webhook node:
- Add a Webhook node as your workflow trigger
- Set it to
POST - Copy the URL into your MailKite domain’s webhook settings
- Activate the workflow
Every inbound email fires the webhook with this payload:
{
"from": "customer@example.com",
"to": "support@yourdomain.com",
"subject": "Need help with my order",
"text": "Hi, I placed order #1234 but haven't received it yet.",
"html": "<p>Hi, I placed order #1234...</p>",
"attachments": [
{
"filename": "invoice.pdf",
"contentType": "application/pdf",
"size": 18213,
"url": "https://api.mailkite.dev/att/.../0?sig=..."
}
],
"auth": {
"spf": "pass",
"dkim": "pass",
"dmarc": "pass",
"spam": "ham"
}
}
No MIME parsing. No IMAP quirks. Clean, structured data ready for your workflow.
Three workflows that work
Support email → filter → auto-reply
1. Webhook trigger (MailKite inbound)
2. IF node: subject contains "support" or "help"
3. Code node: extract priority from keywords ("urgent" → high, "asap" → high)
4. HTTP Request: create ticket in your system
5. SMTP Send: auto-reply to customer
"Thanks for reaching out. Ticket #{{ticketId}} created. We'll respond within 24 hours."
Lead capture → CRM → Slack alert
1. Webhook trigger (MailKite inbound)
2. IF node: from ends with "@potential-client.com"
3. HTTP Request: create contact in HubSpot/Salesforce
4. Slack node: post to #leads channel
"New lead: {{from}} — {{subject}}"
Order reply → database → notification
1. Webhook trigger (MailKite inbound)
2. IF node: subject matches "Order #\d+"
3. Code node: extract order number from subject
4. PostgreSQL node: update order status, add customer reply
5. SMTP Send: confirm receipt to customer
Self-hosted n8n
If you run n8n on your own infrastructure, the webhook URL must be reachable from the internet. If n8n is behind a firewall, use a tunnel:
# Cloudflare Tunnel (recommended)
cloudflared tunnel --url http://localhost:5678
# Or ngrok (for testing)
npx localtunnel --port 5678
Set the tunnel’s public URL as your MailKite webhook. MailKite must be able to POST to it — local-only n8n instances won’t receive inbound email.
How it compares
| n8n IMAP trigger | MailKite webhook trigger | |
|---|---|---|
| Latency | 3–15 seconds (polling) | Seconds (push) |
| Reliability | IMAP drops silently | HTTPS, retried on failure |
| Structure | Raw MIME, parse yourself | Clean JSON, pre-parsed |
| Attachments | Limited metadata | Filename, size, signed URL |
| Auth results | Not available | SPF, DKIM, DMARC |
| Sending | Basic SMTP | SMTP + DKIM signing + logs |
FAQ
Can I use both MailKite and the IMAP trigger? Yes, but the webhook trigger is faster and more reliable. Use IMAP only if you need to read historical email (MailKite’s webhook only fires for new inbound messages).
Do I need n8n cloud for this? No. Self-hosted n8n works the same way. The only difference: self-hosted instances behind a firewall need a tunnel for MailKite to reach the webhook.
What about n8n’s SMTP Send node limits?
n8n’s SMTP node has no built-in rate limiting. MailKite handles rate limiting on the server side — you’ll get a 429 response if you exceed your plan’s limits. For high-volume sending, queue the emails with n8n’s Wait node or a queue.
Build email automation that fires in seconds, not minutes. Start free — unlimited domains, no credit card.
Related: Turn inbound email into Zapier workflows — the same pattern for Zapier · Email to webhook: the complete guide — the full payload reference · Receive email as a webhook in Python — building custom handlers