Many transactional emails need to include files — invoices after a purchase, receipts for payments, reports generated on demand, or contracts that need a signature. Lettr supports base64-encoded file attachments, so you can attach files directly in your API request.
Basic Attachment
Attach files using base64-encoded content:
import fs from 'fs';
const fileContent = fs.readFileSync('invoice.pdf');
const base64Content = fileContent.toString('base64');
await lettr.emails.send({
from: 'you@example.com',
to: ['recipient@example.com'],
subject: 'Your Invoice',
html: '<p>Please find your invoice attached.</p>',
attachments: [
{
name: 'invoice.pdf',
data: base64Content,
type: 'application/pdf'
}
]
});
Multiple Attachments
await lettr.emails.send({
from: 'you@example.com',
to: ['recipient@example.com'],
subject: 'Project Files',
html: '<p>Here are the requested files.</p>',
attachments: [
{
name: 'report.pdf',
data: reportBase64,
type: 'application/pdf'
},
{
name: 'data.xlsx',
data: excelBase64,
type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
},
{
name: 'image.png',
data: imageBase64,
type: 'image/png'
}
]
});
Inline Images
Embed images directly in your email HTML:
await lettr.emails.send({
from: 'you@example.com',
to: ['recipient@example.com'],
subject: 'Email with Image',
html: '<p>Check out this image:</p><img src="cid:logo" />',
attachments: [
{
name: 'logo.png',
data: logoBase64,
type: 'image/png'
}
]
});
Attachment Limits
| Limit | Value |
|---|
| Max total size (after Base64 encoding) | 5 MB |
| Max attachment name length | 255 characters |
Large attachments can affect deliverability and may be blocked by recipient email servers. Consider using download links for large files.
Attachments vs. Download Links
Not every file belongs as an attachment. Consider which approach fits your use case:
| Factor | Attachment | Download Link |
|---|
| File size | Best for files under 10 MB | Better for large files |
| Offline access | Recipient has the file immediately | Requires internet to download |
| Deliverability | Large attachments may be blocked | No impact on email delivery |
| Tracking | No download tracking | Can track link clicks |
| Expiration | File persists in recipient’s inbox | Link can expire for security |
Use attachments for: invoices, receipts, tickets, and small documents the recipient needs to keep.
Use download links for: large reports, media files, archives, and files that should expire after a set period.
Attachments are included as base64-encoded content in the API request. Each attachment requires three fields:
name — The filename the recipient will see (max 255 characters)
data — The file content encoded as base64 (must not contain \r\n characters)
type — The MIME type of the file
attachments: [{ name: 'invoice.pdf', data: base64String, type: 'application/pdf' }]
Error Handling
When an attachment fails validation, the API returns an error and the email is not sent:
{
"error_code": "validation_error",
"message": "The given data was invalid.",
"errors": {
"attachments.0.data": ["The attachments.0.data field must be a valid base64 string."],
"attachments.0.name": ["The attachments.0.name field is required."]
}
}
Validate file sizes and ensure base64 encoding does not contain \r\n characters before calling the API to avoid failed sends.
Common MIME Types
| Extension | MIME Type |
|---|
.pdf | application/pdf |
.doc | application/msword |
.docx | application/vnd.openxmlformats-officedocument.wordprocessingml.document |
.xls | application/vnd.ms-excel |
.xlsx | application/vnd.openxmlformats-officedocument.spreadsheetml.sheet |
.png | image/png |
.jpg | image/jpeg |
.gif | image/gif |
.zip | application/zip |
.csv | text/csv |