content.email_rfc822. To get them, decode that field if needed and parse it with a MIME library in your handler.
Lettr does not store attachments, so there is nothing to download later. Whatever your code does not keep when it handles the delivery is gone.
Where Attachments Live
Your forwarding URL receives a JSON array of events, each with amsys.relay_message object (see Email Parsing for every field). The fields that matter for attachments are:
The
text and html fields only carry the message body. There is no attachments field in the payload.
The whole message, attachments included, arrives in a single request body. Make sure your web server and framework accept request bodies as large as the biggest email you want to receive. Express’s
express.json(), for example, rejects bodies over 100 KB unless you raise its limit.Extracting Attachments
The steps are the same in every language:- Loop over the events in the JSON array.
- Read
content.email_rfc822and base64-decode it ifcontent.email_rfc822_is_base64istrue. - Parse the raw message with a MIME library and read its attachment parts.
Python’s
iter_attachments() only looks at the top level of the message. Inline images usually sit deeper, inside a multipart/related part, so use message.walk() to find them (see Inline Images). mailparser and mail-mime-parser return both regular attachments and inline images.Respond First, Process Later
Answer the delivery with a2xx as soon as you have the payload, and do slow work such as uploads, virus scans and file conversion in a background job. The same email can be delivered more than once, so key whatever you store on the email’s Message-ID header to avoid saving the same files twice.
Storing Attachments
Store every file you want to keep in your own storage while you handle the delivery. Use a key you generate yourself rather than the sender’s filename, and keep the original filename as metadata.Save to Local Filesystem
Save to Cloud Storage (AWS S3)
Save to Cloud Storage (Google Cloud)
Validating Attachments
Lettr passes on whatever the sender attached, so deciding which files you accept is up to your code. Check the type and size of each file before you process it, using limits that suit your application.Security Considerations
Virus Scanning
Scan files for malware in your handler before storing them, for example with ClamAV:File Type Verification
TheContent-Type of an attachment is whatever the sender’s mail client wrote. Check the actual bytes against it:
Inline Images
Images embedded in an HTML email (logos, signatures, pasted screenshots) are MIME parts with aContent-ID header. The HTML body refers to them as cid: URLs, for example <img src="cid:logo@example.com">, so content.html in the payload contains those references but not the images. You find the images in email_rfc822.
With mailparser, inline images are part of parsed.attachments. Each has cid set and related: true. By default simpleParser also rewrites the cid: links in parsed.html into data: URLs, so the HTML displays on its own. To store the images and point the HTML at your own copies, keep the links and replace them yourself:
Content-ID:
Processing Specific File Types
Once you have an attachment’s bytes, process them with whatever library fits. The examples below usemailparser attachments, where attachment.content is a Buffer.
PDF Documents
Images
CSV Files
Complete Example
An Express endpoint that acknowledges the delivery right away and a worker that extracts PDF and image attachments, deduplicates onMessage-ID, and uploads the files to S3:
Related Topics
Email Parsing
Every field in the inbound payload
Security
Security best practices
Best Practices
Inbound best practices
Sending Attachments
Attach files to outgoing emails