Two approaches to receiving inbound email. Which one is right for your application?
When your application needs to receive inbound email, you typically choose between polling a mailbox (IMAP) or receiving webhooks (HTTP callbacks). The difference comes down to push vs pull.
Your application connects to a mail server and asks "are there new emails?" at regular intervals. You pull the data when you want it.
The mail server sends an HTTP request to your endpoint the moment an email arrives. The data is pushed to you immediately.
| Factor | IMAP | Webhooks |
|---|---|---|
| Latency | Depends on polling interval (seconds to minutes) | Real-time (milliseconds) |
| Connection management | Must maintain persistent connections, handle reconnects | No connections to manage |
| Data format | Raw MIME format, requires parsing | Pre-parsed JSON payload |
| Attachments | Base64 encoded within MIME, must extract | Downloadable URLs |
| Scaling | One connection per mailbox | Standard HTTP scaling |
| Server requirements | Long-running process for polling | Serverless compatible |
| Implementation complexity | High | Low |
IMAP (Internet Message Access Protocol) is the standard protocol for reading email from a mail server. To receive emails via IMAP, your application needs to:
const Imap = require('imap');
const { simpleParser } = require('mailparser');
const imap = new Imap({
user: '[email protected]',
password: 'your-password',
host: 'imap.example.com',
port: 993,
tls: true
});
imap.on('mail', (numNewMsgs) => {
// Fetch new messages
const fetch = imap.seq.fetch(
`${imap.seq.lastSync}:*`,
{ bodies: '' }
);
fetch.on('message', (msg) => {
msg.on('body', (stream) => {
simpleParser(stream, (err, parsed) => {
// Finally, your email data
console.log(parsed.subject);
console.log(parsed.from);
console.log(parsed.text);
});
});
});
});
imap.connect();
// Plus error handling, reconnection logic...With webhooks, an email service receives inbound email on your behalf and forwards it to your application as an HTTP POST request. Your application just needs an endpoint:
// That's it. No connections, no parsing.
app.post('/webhook/email', (req, res) => {
const { from, to, subject, text, html, attachments } = req.body;
console.log(`Email from ${from}: ${subject}`);
// Attachments are already URLs
for (const attachment of attachments) {
console.log(`Download: ${attachment.url}`);
}
// Process the email
await processEmail(req.body);
res.status(200).send('OK');
});