All posts
Build email automation in n8n that actually works
Gabe 3 min read

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:

  1. SMTP Send — sends email via any SMTP server. Works, but no DKIM signing, no delivery tracking, no retries.

  2. 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:

SettingValue
Hostsmtp.mailkite.dev
Port587
Usermailkite
PasswordYour API key (mk_live_…)
SSL/TLStrue (STARTTLS)
Fromnotifications@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:

  1. Add a Webhook node as your workflow trigger
  2. Set it to POST
  3. Copy the URL into your MailKite domain’s webhook settings
  4. 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 triggerMailKite webhook trigger
Latency3–15 seconds (polling)Seconds (push)
ReliabilityIMAP drops silentlyHTTPS, retried on failure
StructureRaw MIME, parse yourselfClean JSON, pre-parsed
AttachmentsLimited metadataFilename, size, signed URL
Auth resultsNot availableSPF, DKIM, DMARC
SendingBasic SMTPSMTP + 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

Discuss this post: Hacker News Share on X Share on LinkedIn

Related posts