[{"data":1,"prerenderedAt":12},["ShallowReactive",2],{"$fQmhioxI0TJVOb8LSTKVIF4Z8HFEjxw18Xa03HEz73EI":3},{"title":4,"slug":5,"excerpt":6,"category":7,"order":8,"screens":9,"html":11},"Email processing","email-processing","How EmailConnect receives, processes, and delivers emails to your webhooks","configuration",3,[10],"logs","\u003Cp>EmailConnect transforms incoming emails into structured webhook payloads. This guide explains the processing pipeline from email receipt to webhook delivery.\u003C\u002Fp>\n\u003Ch2>Processing pipeline\u003C\u002Fh2>\n\u003Ch3>1. Email reception\u003C\u002Fh3>\n\u003Cp>When an email arrives at your configured domain:\u003C\u002Fp>\n\u003Col>\n\u003Cli>\u003Cstrong>SMTP connection\u003C\u002Fstrong> - Sender&#39;s mail server connects to \u003Ccode>mx1.emailconnect.eu\u003C\u002Fcode>\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Spam &amp; virus check\u003C\u002Fstrong> - Email is scanned for spam. On Business+ plans, attachments are also scanned for viruses using ClamAV\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Rule evaluation\u003C\u002Fstrong> - Alias rules are checked (Maker+ feature)\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Acceptance\u003C\u002Fstrong> - Email is accepted for processing\u003C\u002Fli>\n\u003C\u002Fol>\n\u003Ch3>2. Parsing and extraction\u003C\u002Fh3>\n\u003Cp>EmailConnect extracts structured data from the raw email and enriches it based on your plan.\u003C\u002Fp>\n\u003Cp>\u003Cstrong>Message parsing\u003C\u002Fstrong> (all plans):\u003C\u002Fp>\n\u003Cul>\n\u003Cli>Sender and recipient addresses, display names\u003C\u002Fli>\n\u003Cli>Subject line, date, and timestamps\u003C\u002Fli>\n\u003Cli>HTML and plain text body\u003C\u002Fli>\n\u003Cli>Link extraction from both HTML and plain text\u003C\u002Fli>\n\u003Cli>Attachments with filenames, MIME types, and sizes (Base64 inline or S3 URL)\u003C\u002Fli>\n\u003Cli>Email classification by type (\u003Ccode>normal\u003C\u002Fcode>, \u003Ccode>transactional\u003C\u002Fcode>, \u003Ccode>marketing\u003C\u002Fcode>, \u003Ccode>notification\u003C\u002Fcode>, \u003Ccode>automated\u003C\u002Fcode>)\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Cp>\u003Cstrong>Content enrichment\u003C\u002Fstrong> (Maker+):\u003C\u002Fp>\n\u003Cul>\n\u003Cli>Markdown conversion — HTML body converted to clean Markdown, useful for LLM pipelines and content extraction\u003C\u002Fli>\n\u003Cli>Classification confidence and signals (e.g. \u003Ccode>has_attachment\u003C\u002Fcode>, \u003Ccode>has_unsubscribe_link\u003C\u002Fcode>)\u003C\u002Fli>\n\u003Cli>Integrity hashes — SHA-256 hashes of both the processed content and the raw email for audit trails and deduplication\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Cp>\u003Cstrong>Spam analysis\u003C\u002Fstrong> (Maker+):\u003C\u002Fp>\n\u003Cul>\n\u003Cli>rspamd composite score and verdict\u003C\u002Fli>\n\u003Cli>SPF, DKIM, and DMARC authentication results\u003C\u002Fli>\n\u003Cli>Matched rules with individual weights\u003C\u002Fli>\n\u003Cli>Configurable threshold for automatic filtering\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Cp>\u003Cstrong>Security scanning\u003C\u002Fstrong> (Business+):\u003C\u002Fp>\n\u003Cul>\n\u003Cli>ClamAV virus scanning on all attachments\u003C\u002Fli>\n\u003Cli>Infected files are excluded from delivery with \u003Ccode>excludeReason: &quot;virus-detected&quot;\u003C\u002Fcode>\u003C\u002Fli>\n\u003Cli>Per-attachment and summary-level scan results\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Ch3>3. Webhook delivery\u003C\u002Fh3>\n\u003Cp>The structured payload is delivered to your configured endpoint:\u003C\u002Fp>\n\u003Col>\n\u003Cli>\u003Cstrong>Payload construction\u003C\u002Fstrong> - JSON payload is built\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Signing\u003C\u002Fstrong> - Request is signed for verification\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Delivery\u003C\u002Fstrong> - POST request sent to your webhook URL\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Retry handling\u003C\u002Fstrong> - Failed deliveries are retried\u003C\u002Fli>\n\u003C\u002Fol>\n\u003Ch2>Webhook payload structure\u003C\u002Fh2>\n\u003Cblockquote>\n\u003Cp>\u003Cstrong>Looking for the full field-by-field reference?\u003C\u002Fstrong> See \u003Ca href=\"\u002Fhelp\u002Fwebhook-payload-reference\u002F\">What&#39;s in your webhook payload\u003C\u002Fa> for every field, enrichment feature, and plan availability.\u003C\u002Fp>\n\u003C\u002Fblockquote>\n\u003Ch3>Basic payload\u003C\u002Fh3>\n\u003Cpre>\u003Ccode class=\"language-json\">{\n  &quot;message&quot;: {\n    &quot;date&quot;: &quot;2026-02-12T10:30:00.000Z&quot;,\n    &quot;sender&quot;: {\n      &quot;name&quot;: &quot;Alice Martin&quot;,\n      &quot;email&quot;: &quot;alice@example.com&quot;\n    },\n    &quot;content&quot;: {\n      &quot;text&quot;: &quot;Hi there!\\n\\nJust wanted to follow up on our conversation.\\n\\nBest regards,\\nAlice&quot;,\n      &quot;html&quot;: &quot;&lt;p&gt;Hi there!&lt;\u002Fp&gt;&lt;p&gt;Just wanted to follow up on our conversation.&lt;\u002Fp&gt;&lt;p&gt;Best regards,&lt;br&gt;Alice&lt;\u002Fp&gt;&quot;,\n      &quot;links&quot;: []\n    },\n    &quot;subject&quot;: &quot;Following up&quot;,\n    &quot;recipient&quot;: {\n      &quot;name&quot;: null,\n      &quot;email&quot;: &quot;support@yourdomain.com&quot;\n    },\n    &quot;attachments&quot;: []\n  },\n  &quot;classification&quot;: {\n    &quot;type&quot;: &quot;normal&quot;\n  }\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch3>Full payload with all options\u003C\u002Fh3>\n\u003Cpre>\u003Ccode class=\"language-json\">{\n  &quot;spam&quot;: {\n    &quot;score&quot;: -0.99,\n    &quot;action&quot;: &quot;default&quot;,\n    &quot;engine&quot;: &quot;rspamd&quot;,\n    &quot;isSpam&quot;: false,\n    &quot;symbols&quot;: [\n      { &quot;name&quot;: &quot;DMARC_POLICY_ALLOW&quot;, &quot;weight&quot;: -0.5, &quot;description&quot;: &quot;example.com,none&quot; },\n      { &quot;name&quot;: &quot;R_DKIM_ALLOW&quot;, &quot;weight&quot;: -0.2, &quot;description&quot;: &quot;example.com:s=selector1&quot; }\n    ],\n    &quot;threshold&quot;: 0,\n    &quot;authentication&quot;: {\n      &quot;spf&quot;: { &quot;result&quot;: &quot;pass&quot; },\n      &quot;dkim&quot;: { &quot;result&quot;: &quot;pass&quot; },\n      &quot;dmarc&quot;: { &quot;result&quot;: &quot;pass&quot; }\n    }\n  },\n  &quot;message&quot;: {\n    &quot;date&quot;: &quot;2026-02-12T10:30:00.000Z&quot;,\n    &quot;sender&quot;: {\n      &quot;name&quot;: &quot;Alice Martin&quot;,\n      &quot;email&quot;: &quot;alice@example.com&quot;\n    },\n    &quot;content&quot;: {\n      &quot;text&quot;: &quot;Hi team,\\n\\nPlease find invoice #2026-0042 attached.\\n\\nBest,\\nAlice&quot;,\n      &quot;html&quot;: &quot;&lt;p&gt;Hi team,&lt;\u002Fp&gt;&lt;p&gt;Please find invoice #2026-0042 attached.&lt;\u002Fp&gt;&lt;p&gt;Best,&lt;br&gt;Alice&lt;\u002Fp&gt;&quot;,\n      &quot;markdown&quot;: &quot;Hi team,\\n\\nPlease find invoice #2026-0042 attached.\\n\\nBest,\\nAlice&quot;,\n      &quot;links&quot;: [\n        { &quot;url&quot;: &quot;https:\u002F\u002Fbilling.example.com\u002Finv\u002F2026-0042&quot;, &quot;text&quot;: &quot;View it online&quot; }\n      ]\n    },\n    &quot;subject&quot;: &quot;Invoice #2026-0042 attached&quot;,\n    &quot;recipient&quot;: {\n      &quot;name&quot;: null,\n      &quot;email&quot;: &quot;invoices@yourdomain.com&quot;\n    },\n    &quot;attachments&quot;: [\n      {\n        &quot;filename&quot;: &quot;invoice-2026-0042.pdf&quot;,\n        &quot;contentType&quot;: &quot;application\u002Fpdf&quot;,\n        &quot;size&quot;: 245680,\n        &quot;content&quot;: &quot;JVBERi0xLjQK...&quot;,\n        &quot;virusScan&quot;: { &quot;status&quot;: &quot;clean&quot; }\n      }\n    ]\n  },\n  &quot;integrity&quot;: {\n    &quot;contentHash&quot;: &quot;a3f2b8c1d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1&quot;,\n    &quot;rawEmailHash&quot;: &quot;9f8e7d6c5b4a3f2e1d0c9b8a7f6e5d4c3b2a1f0e9d8c7b6a5f4e3d2c1b0a9f8e&quot;\n  },\n  &quot;classification&quot;: {\n    &quot;type&quot;: &quot;normal&quot;,\n    &quot;signals&quot;: [&quot;has_attachment&quot;, &quot;single_recipient&quot;],\n    &quot;confidence&quot;: &quot;definite&quot;\n  },\n  &quot;security&quot;: {\n    &quot;virusScan&quot;: {\n      &quot;scanned&quot;: true,\n      &quot;engine&quot;: &quot;clamav&quot;,\n      &quot;engineVersion&quot;: &quot;1.5.1&quot;,\n      &quot;attachmentsScanned&quot;: 1,\n      &quot;attachmentsSkipped&quot;: 0,\n      &quot;threatsFound&quot;: 0\n    }\n  }\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch2>Delivery and retries\u003C\u002Fh2>\n\u003Ch3>Successful delivery\u003C\u002Fh3>\n\u003Cp>A delivery is considered successful when your endpoint returns:\u003C\u002Fp>\n\u003Cul>\n\u003Cli>HTTP 200-299 status code\u003C\u002Fli>\n\u003Cli>Response within timeout period (30 seconds)\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Ch3>Retry policy\u003C\u002Fh3>\n\u003Cp>If delivery fails, EmailConnect retries with exponential backoff (±10% jitter):\u003C\u002Fp>\n\u003Ctable>\n\u003Cthead>\n\u003Ctr>\n\u003Cth>Attempt\u003C\u002Fth>\n\u003Cth>Delay\u003C\u002Fth>\n\u003C\u002Ftr>\n\u003C\u002Fthead>\n\u003Ctbody>\u003Ctr>\n\u003Ctd>1\u003C\u002Ftd>\n\u003Ctd>Immediate\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>2\u003C\u002Ftd>\n\u003Ctd>~1 minute\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>3\u003C\u002Ftd>\n\u003Ctd>~5 minutes\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>4\u003C\u002Ftd>\n\u003Ctd>~30 minutes\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>5\u003C\u002Ftd>\n\u003Ctd>~2 hours\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>6\u003C\u002Ftd>\n\u003Ctd>~12 hours\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003C\u002Ftbody>\u003C\u002Ftable>\n\u003Cp>Actual delays vary by ±10% from the listed values to prevent thundering-herd effects.\u003C\u002Fp>\n\u003Cp>\u003Cstrong>Retries are capped by your data retention policy.\u003C\u002Fstrong> If the next retry would fall after your retention window expires, the email is marked as failed instead. For example, Free and Maker plans (1-hour retention) get up to 4 attempts — attempt 5 would be at +2h 36m, past the retention window. Business and Platform plans with longer retention (up to 30 or 365 days) can use all 6 attempts.\u003C\u002Fp>\n\u003Cp>After 6 failed attempts or retention expiry (whichever comes first), the email is marked as failed and no further retries occur.\u003C\u002Fp>\n\u003Ch3>Failure reasons\u003C\u002Fh3>\n\u003Cp>Common delivery failures:\u003C\u002Fp>\n\u003Cul>\n\u003Cli>Endpoint not reachable (network error)\u003C\u002Fli>\n\u003Cli>Endpoint returns 4xx\u002F5xx error\u003C\u002Fli>\n\u003Cli>Timeout (response takes &gt; 30 seconds)\u003C\u002Fli>\n\u003Cli>SSL\u002FTLS certificate errors\u003C\u002Fli>\n\u003Cli>Payload too large for endpoint\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Ch2>Webhook security\u003C\u002Fh2>\n\u003Ch3>Request signing\u003C\u002Fh3>\n\u003Cp>EmailConnect signs webhook requests following the \u003Ca href=\"https:\u002F\u002Fgithub.com\u002Fstandard-webhooks\u002Fstandard-webhooks\">Standard Webhooks\u003C\u002Fa> convention. Each request includes three headers:\u003C\u002Fp>\n\u003Cpre>\u003Ccode>webhook-id: msg_2KWPBgLl...\nwebhook-timestamp: 1716300000\nwebhook-signature: v1,K5oZfzN95Z9UVu1EsfQmfVNQhnkZ2pj9o9NDN\u002FH\u002FpI4=\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>The signed content is \u003Ccode>{webhook-id}.{webhook-timestamp}.{body}\u003C\u002Fcode>, signed with HMAC-SHA256 using your base64-decoded secret.\u003C\u002Fp>\n\u003Ch3>Node.js\u003C\u002Fh3>\n\u003Cpre>\u003Ccode class=\"language-javascript\">const crypto = require(&#39;crypto&#39;);\n\nfunction verifyWebhook(headers, rawBody, secret) {\n  const signedContent = `${headers[&#39;webhook-id&#39;]}.${headers[&#39;webhook-timestamp&#39;]}.${rawBody}`;\n  const secretBytes = Buffer.from(secret.replace(\u002F^whsec_\u002F, &#39;&#39;), &#39;base64&#39;);\n  const expected = crypto.createHmac(&#39;sha256&#39;, secretBytes).update(signedContent).digest(&#39;base64&#39;);\n\n  return headers[&#39;webhook-signature&#39;].split(&#39; &#39;).some(sig =&gt; {\n    const [v, val] = sig.split(&#39;,&#39;);\n    return v === &#39;v1&#39; &amp;&amp; crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(val));\n  });\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch3>Python\u003C\u002Fh3>\n\u003Cpre>\u003Ccode class=\"language-python\">import hmac, hashlib, base64\n\ndef verify_webhook(headers, raw_body, secret):\n    signed_content = f&quot;{headers[&#39;webhook-id&#39;]}.{headers[&#39;webhook-timestamp&#39;]}.{raw_body}&quot;\n    secret_bytes = base64.b64decode(secret.removeprefix(&#39;whsec_&#39;))\n    expected = base64.b64encode(\n        hmac.new(secret_bytes, signed_content.encode(), hashlib.sha256).digest()\n    ).decode()\n\n    return any(\n        v == &#39;v1&#39; and hmac.compare_digest(expected, val)\n        for sig in headers[&#39;webhook-signature&#39;].split(&#39; &#39;)\n        for v, _, val in [sig.partition(&#39;,&#39;)]\n    )\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>For full verification examples including timestamp checks, see the \u003Ca href=\"\u002Fhelp\u002Fwebhook-signing\u002F\">webhook signing guide\u003C\u002Fa>.\u003C\u002Fp>\n\u003Ch2>Processing order\u003C\u002Fh2>\n\u003Cp>Emails are processed in order of receipt. However, webhook delivery may complete out of order due to:\u003C\u002Fp>\n\u003Cul>\n\u003Cli>Retry delays for failed deliveries\u003C\u002Fli>\n\u003Cli>Processing time variations\u003C\u002Fli>\n\u003Cli>Network latency differences\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Cp>If order matters for your application, use the \u003Ccode>timestamp\u003C\u002Fcode> field to sort emails chronologically.\u003C\u002Fp>\n\u003Ch2>Rate limits\u003C\u002Fh2>\n\u003Ctable>\n\u003Cthead>\n\u003Ctr>\n\u003Cth>Plan\u003C\u002Fth>\n\u003Cth>API requests per hour\u003C\u002Fth>\n\u003Cth>Effective per minute\u003C\u002Fth>\n\u003C\u002Ftr>\n\u003C\u002Fthead>\n\u003Ctbody>\u003Ctr>\n\u003Ctd>Free\u003C\u002Ftd>\n\u003Ctd>60\u003C\u002Ftd>\n\u003Ctd>1\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>Maker\u003C\u002Ftd>\n\u003Ctd>600\u003C\u002Ftd>\n\u003Ctd>10\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>Business\u003C\u002Ftd>\n\u003Ctd>3,000\u003C\u002Ftd>\n\u003Ctd>50\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>Platform\u003C\u002Ftd>\n\u003Ctd>Unlimited\u003C\u002Ftd>\n\u003Ctd>10,000 cap\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003C\u002Ftbody>\u003C\u002Ftable>\n\u003Cp>Emails exceeding rate limits are queued and processed when capacity is available.\u003C\u002Fp>\n\u003Ch2>Monitoring and debugging\u003C\u002Fh2>\n\u003Ch3>Email logs\u003C\u002Fh3>\n\u003Cp>View processed emails in your dashboard:\u003C\u002Fp>\n\u003Cul>\n\u003Cli>Delivery status (success\u002Ffailed\u002Fpending)\u003C\u002Fli>\n\u003Cli>Response codes from your endpoint\u003C\u002Fli>\n\u003Cli>Retry history\u003C\u002Fli>\n\u003Cli>Full payload preview\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Ch3>Webhook testing\u003C\u002Fh3>\n\u003Cp>EmailConnect integrates directly with \u003Ca href=\"https:\u002F\u002Fwebhooktest.eu\">WebhookTest.eu\u003C\u002Fa> — click &quot;Use WebhookTest&quot; when creating an alias and you can inspect the full payload without leaving your dashboard. No external tools or tab-switching needed.\u003C\u002Fp>\n\u003Cp>See \u003Ca href=\"\u002Fhelp\u002Fwebhooktest-integration\u002F\">Testing webhooks with WebhookTest\u003C\u002Fa> for detailed setup instructions.\u003C\u002Fp>\n\u003Ch2>Related topics\u003C\u002Fh2>\n\u003Cul>\n\u003Cli>\u003Ca href=\"\u002Fhelp\u002Fwebhook-payload-reference\u002F\">What&#39;s in your webhook payload\u003C\u002Fa> - Complete field reference with enrichment features by plan\u003C\u002Fli>\n\u003Cli>\u003Ca href=\"\u002Fhelp\u002Fwebhook-configuration\u002F\">Webhook configuration\u003C\u002Fa> - Set up webhook endpoints\u003C\u002Fli>\n\u003Cli>\u003Ca href=\"\u002Fhelp\u002Fcustom-webhook-headers\u002F\">Custom webhook headers\u003C\u002Fa> - Add authentication headers\u003C\u002Fli>\n\u003Cli>\u003Ca href=\"\u002Fhelp\u002Falias-options-explained\u002F\">Alias options\u003C\u002Fa> - Configure processing options\u003C\u002Fli>\n\u003Cli>\u003Ca href=\"\u002Fhelp\u002Fattachment-processing\u002F\">Attachment processing\u003C\u002Fa> - Handle file attachments\u003C\u002Fli>\n\u003C\u002Ful>\n",1781207681435]