Skip to main content
Receiving emails from external sources introduces security considerations. This guide covers best practices for securing your inbound email processing pipeline. Apart from the auth token, everything here runs in your own handler: Lettr posts inbound mail to your forwarding URL as received and doesn’t sanitize, scan or filter it.

Forwarding URL Security

Verify the Auth Token

Always verify that requests to your forwarding URL come from Lettr, not malicious actors. When you create an inbound domain, or later on the domain’s Mail Forwarding card, set an Auth token. It is sent with every request in the X-MessageSystems-Webhook-Token header. Compare it against your stored value and reject anything that doesn’t match:
Lettr never shows your auth token again after you save it, so keep your own copy (for example in an environment variable). To rotate it, enter a new token on the Mail Forwarding card and click Save forwarding URL. Leaving the field blank keeps the token that is already set.

Don’t Rely on IP Allowlisting

Inbound mail is posted to your forwarding URL by SparkPost, the mail infrastructure behind Lettr’s inbound servers, and SparkPost publishes no fixed source IP addresses. An IP allowlist can’t reliably identify these requests, so use the auth token instead. If your endpoint sits behind Cloudflare or another firewall/WAF, allow server-to-server POST requests on your forwarding URL’s path. Otherwise the firewall may answer with a challenge page, and a non-2xx response makes the forwarding URL test fail when you create the domain or save a new URL.

Input Validation

Validate Email Addresses

Never trust email addresses from inbound emails. msg_from, friendly_from and the address headers are all set by the sender:

Sanitize Email Content

Sanitize HTML content before displaying or storing:

Validate and Sanitize Filenames

Attachment filenames come from the sender. Never use them directly as paths:

Attachment Security

Extract Attachments From the Raw Message

The payload has no attachments array and no attachment URLs. Attachments exist only inside the raw MIME message in content.email_rfc822, so your handler parses it with a MIME library such as mailparser. Every check below runs on the parsed attachments:
Lettr doesn’t store inbound messages or attachments, so validate and save what you need while handling the request, or from a queue job that received the payload. See Attachments for more.

Validate File Types

Never trust the declared content type. Detect the real type from the file’s bytes:

Scan for Malware

Integrate with a virus scanner:

Limit File Sizes

Set your own size limits to prevent resource exhaustion. The numbers below are example values for your application, not Lettr limits:
Putting the attachment checks together in your handler:
For large messages or slow scanners, acknowledge the request first and run these checks from a queue.

Content Security

Prevent XSS in Displayed Emails

When displaying email content in a web interface:

Block Tracking Pixels

Strip tracking pixels from received emails:

Rate Limiting

Protect against email flooding by limiting how many messages one sender, one sender domain, or all senders together can push through your pipeline:
Still answer the request with a 2xx when you drop a rate-limited message. Your response doesn’t reach the sender, so an error status can’t push the mail back to them.

Logging and Monitoring

Audit Logging

Log all inbound email processing. The payload has no event ID, so use the Message-ID header to identify a message:

Anomaly Detection

Monitor for suspicious patterns:

Security Checklist

  • Set an auth token and verify the X-MessageSystems-Webhook-Token header on every request
  • Store the token securely in environment variables
  • Use HTTPS for your forwarding URL
  • Allow server-to-server POST requests through your firewall or WAF instead of relying on an IP allowlist
  • Validate all email addresses
  • Sanitize HTML content before storage/display
  • Sanitize filenames before use
  • Validate attachment content types
  • Parse attachments from content.email_rfc822 with a MIME library
  • Verify file types from content, not headers
  • Scan attachments for malware
  • Enforce your own size limits
  • Store attachments outside web root
  • Log all inbound email processing
  • Monitor for rate limit violations
  • Alert on anomalous patterns
  • Track your own spam filtering decisions
Never trust any data from inbound emails. Senders can forge headers, spoof addresses, and include malicious content. Always validate and sanitize everything.

Inbound Setup

Set the forwarding URL and auth token

Spam Filtering

Handle spam in your own handler

Attachments

Handle attachments safely

Best Practices

Overall best practices