Troubleshooting
Common issues and their solutions when using postal-mime.
Parsing Errors
"Can not reuse parser, create a new PostalMime object"
Cause: Attempting to use the same parser instance twice.
Solution: Create a new parser instance for each email:
// Wrong
const parser = new PostalMime();
await parser.parse(email1);
await parser.parse(email2); // Error!
// Correct
const email1Parsed = await PostalMime.parse(email1);
const email2Parsed = await PostalMime.parse(email2);
// Or with instances
const parser1 = new PostalMime();
const parser2 = new PostalMime();
await parser1.parse(email1);
await parser2.parse(email2);
"Maximum MIME nesting depth exceeded"
Cause: The email contains more nested MIME parts than allowed (default: 256).
Solutions:
- Increase the limit (use with caution):
const email = await PostalMime.parse(rawEmail, {
maxNestingDepth: 512
});
- The email may be malicious - consider rejecting it:
try {
const email = await PostalMime.parse(rawEmail);
} catch (error) {
if (error.message.includes('nesting depth')) {
console.log('Rejecting potentially malicious email');
return;
}
throw error;
}
"Maximum header size exceeded"
Cause: Headers exceed the size limit (default: 2MB).
Solutions:
- Increase the limit:
const email = await PostalMime.parse(rawEmail, {
maxHeadersSize: 5 * 1024 * 1024 // 5MB
});
- Check if the email is malformed or malicious.
Content Issues
HTML content is empty but email has HTML
Possible causes:
- The HTML is in an attachment with
Content-Disposition: attachment:
// Check attachments for HTML
const htmlAttachment = email.attachments.find(
att => att.mimeType === 'text/html'
);
if (htmlAttachment) {
const decoder = new TextDecoder();
const html = decoder.decode(htmlAttachment.content);
}
- The email uses
forceRfc822Attachmentsand HTML is in a nested email.
Text content has strange characters
Cause: Character encoding issues.
Solution: Verify the email has correct Content-Type charset:
const contentType = email.headers.find(h => h.key === 'content-type');
console.log('Content-Type:', contentType?.value);
If the charset is missing or wrong, the content may not decode correctly. postal-mime attempts to detect encoding but can't always succeed.
Missing subject or other headers
Check: The header might have a different casing or format:
// Check all headers
email.headers.forEach(h => {
console.log(`${h.key}: ${h.value}`);
});
// Find by case-insensitive search
const subject = email.headers.find(
h => h.key.toLowerCase() === 'subject'
);
Attachment Issues
Attachments array is empty
Possible causes:
-
Email doesn't have attachments (check raw email)
-
All attachments are inline (related to HTML):
// Check for related attachments
const relatedAttachments = email.attachments.filter(a => a.related);
console.log('Related attachments:', relatedAttachments.length);
- Nested email attachments with default settings:
// By default, message/rfc822 parts are inlined
// Use this option to treat them as attachments:
const email = await PostalMime.parse(rawEmail, {
forceRfc822Attachments: true
});
Attachment content is corrupted
Check the encoding:
const email = await PostalMime.parse(rawEmail);
email.attachments.forEach(att => {
console.log('Filename:', att.filename);
console.log('Content type:', typeof att.content);
console.log('Size:', att.content.byteLength);
});
Solution: Ensure you're handling the ArrayBuffer correctly:
// For saving in Node.js
import { writeFile } from 'fs/promises';
const buffer = Buffer.from(att.content);
await writeFile('file.pdf', buffer);
// For downloading in browser
const blob = new Blob([att.content], { type: att.mimeType });
const url = URL.createObjectURL(blob);
Filename is null
Cause: The attachment doesn't have a filename in Content-Disposition or Content-Type.
Solution: Generate a filename based on MIME type:
function getFilename(attachment) {
if (attachment.filename) return attachment.filename;
const extensions = {
'application/pdf': 'pdf',
'image/jpeg': 'jpg',
'image/png': 'png',
'text/plain': 'txt',
'text/html': 'html'
};
const ext = extensions[attachment.mimeType] || 'bin';
return `attachment.${ext}`;
}
Address Parsing Issues
Group addresses not parsed correctly
Solution: Use type checking to handle groups:
import { addressParser } from 'postal-mime';
const addresses = addressParser(headerValue);
addresses.forEach(addr => {
if (addr.group) {
console.log(`Group: ${addr.name}`);
addr.group.forEach(member => {
console.log(` Member: ${member.address}`);
});
} else {
console.log(`Address: ${addr.address}`);
}
});
Encoded names not decoded
Check: Ensure the encoded-word format is correct:
import { decodeWords } from 'postal-mime';
const encoded = '=?UTF-8?B?SGVsbG8=?=';
const decoded = decodeWords(encoded);
console.log(decoded); // "Hello"
If decoding fails, the charset might be unsupported.
Environment Issues
Module not found / import errors
For ESM (recommended):
import PostalMime from 'postal-mime';
For CommonJS:
const PostalMime = require('postal-mime');
For browser direct import:
import PostalMime from './node_modules/postal-mime/src/postal-mime.js';
TypeScript errors
Solution: Ensure types are properly imported:
import PostalMime from 'postal-mime';
import type { Email, PostalMimeOptions } from 'postal-mime';
const options: PostalMimeOptions = {
attachmentEncoding: 'base64'
};
const email: Email = await PostalMime.parse(rawEmail, options);
Blob not defined (Node.js)
Cause: Using Blob type in Node.js < 18.
Solution: Use Buffer or ArrayBuffer instead:
import { readFile } from 'fs/promises';
const buffer = await readFile('email.eml');
const email = await PostalMime.parse(buffer);
Performance Issues
Parsing large emails is slow
Solutions:
-
Use Web Workers for browser environments (see Web Worker example)
-
Stream processing is coming - for now, the entire email must be in memory
-
Reduce attachment processing overhead:
// Use base64 to avoid ArrayBuffer copying
const email = await PostalMime.parse(rawEmail, {
attachmentEncoding: 'base64'
});
Memory usage is high
Causes:
- Large attachments are kept in memory
- Multiple emails parsed without releasing memory
Solutions:
-
Process one email at a time and allow garbage collection
-
Extract and save attachments immediately, then clear references:
const email = await PostalMime.parse(rawEmail);
// Save attachments to disk/storage
for (const att of email.attachments) {
await saveAttachment(att);
}
// Clear the email object
email = null;
Still Having Issues?
- Check the raw email: Use a text editor to verify the email format
- Validate the MIME structure: Tools like
munpackcan help - Enable debugging: Add console.log statements to trace the issue
- Report a bug: GitHub Issues
When reporting issues, please include:
- postal-mime version
- Node.js/browser version
- Minimal reproducible example
- Sample email (if possible, anonymized)