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