Skip to main content

messageBounce

The messageBounce webhook event is triggered when EmailEngine detects a bounce response email in a monitored mailbox. Bounce emails are generated by mail servers when they cannot deliver a message to the intended recipient. This event helps you track email deliverability by identifying messages that failed to reach their recipients.

When This Event is Triggered

The messageBounce event fires when:

  • A bounce response email is received in a monitored mailbox
  • EmailEngine successfully parses the bounce and extracts delivery failure information
  • The bounce contains identifiable information about the failed recipient and original message

EmailEngine analyzes incoming messages for bounce patterns from various email providers including:

  • Standard RFC 3464 delivery status notifications
  • Amazon WorkMail bounce notifications
  • Gmail bounce messages
  • Microsoft Exchange bounce reports
  • Postfix mailer-daemon responses
  • Zoho Mail bounce notifications
  • Generic SMTP server bounces

Common Use Cases

  • Deliverability monitoring - Track bounce rates across your email campaigns
  • List hygiene - Automatically remove or flag invalid email addresses
  • Reputation management - Identify and address delivery issues before they impact sender reputation
  • Customer notification - Alert users when their messages fail to deliver
  • Analytics - Build dashboards showing delivery success rates
  • Retry logic - Implement custom retry strategies for soft bounces

Payload Schema

Top-Level Fields

FieldTypeRequiredDescription
serviceUrlstringNoThe configured EmailEngine service URL
accountstringYesAccount ID that received the bounce message
datestringYesISO 8601 timestamp when the webhook was generated
eventstringYesEvent type, always "messageBounce" for this event
eventIdstringYesUnique identifier for this webhook delivery
dataobjectYesBounce data object (see below)

Bounce Data Fields (data object)

FieldTypeRequiredDescription
idstringNoEmailEngine message ID of the original bounced message (if found)
bounceMessagestringYesEmailEngine message ID of the bounce notification email itself
recipientstringYesEmail address that bounced
actionstringYesBounce action type (typically "failed" for hard bounces, "delayed" for soft bounces)
responseobjectNoSMTP response details from the receiving server
mtastringNoMail Transfer Agent (server) that reported the bounce
queueIdstringNoQueue ID from the sending MTA (e.g., Postfix queue ID)
messageIdstringNoMessage-ID header of the original message that bounced
messageHeadersobjectNoHeaders from the original bounced message

Response Object Structure

The response object contains details about the SMTP error:

FieldTypeDescription
sourcestringSource of the diagnostic code (typically "smtp")
messagestringThe full SMTP error message from the receiving server
statusstringEnhanced status code (e.g., "5.1.1" for invalid mailbox, "5.2.2" for mailbox full)

Message Headers Object Structure

The messageHeaders object contains headers from the original bounced message (when available):

FieldTypeDescription
return-patharrayReturn-Path header values
receivedarrayReceived header chain
dkim-signaturearrayDKIM signature headers
content-typearrayContent-Type header
fromarrayFrom header
toarrayTo header
subjectarraySubject header
message-idarrayMessage-ID header
datearrayDate header
mime-versionarrayMIME-Version header

Example Payload

{
"serviceUrl": "https://emailengine.example.com",
"account": "user123",
"date": "2025-10-17T06:46:29.436Z",
"event": "messageBounce",
"eventId": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"data": {
"id": "AAAAAQAAAeE",
"bounceMessage": "AAAAAQAABy8",
"recipient": "missing@example.com",
"action": "failed",
"response": {
"source": "smtp",
"message": "550 5.1.1 The email account that you tried to reach does not exist",
"status": "5.1.1"
},
"mta": "mx.example.com",
"queueId": "9441D8220E",
"messageId": "<305eabf4-9538-2747-acec-dc32cb651a0e@example.com>",
"messageHeaders": {
"return-path": ["<sender@example.com>"],
"from": ["Sender Name <sender@example.com>"],
"to": ["Recipient <missing@example.com>"],
"subject": ["Your original message subject"],
"message-id": ["<305eabf4-9538-2747-acec-dc32cb651a0e@example.com>"],
"date": ["Mon, 17 Oct 2025 09:46:25 +0300"],
"mime-version": ["1.0"]
}
}
}

Understanding Bounce Types

Hard Bounces (Permanent Failures)

Hard bounces indicate permanent delivery failures. The action field will be "failed" and status codes typically start with "5":

Status CodeMeaning
5.1.1Invalid mailbox / User unknown
5.1.2Invalid domain
5.2.1Mailbox disabled
5.2.2Mailbox full (can also be temporary)
5.4.1No answer from host
5.7.1Delivery not authorized

Soft Bounces (Temporary Failures)

Soft bounces are temporary and may succeed on retry. The action field may be "delayed":

Status CodeMeaning
4.2.2Mailbox full (temporary)
4.4.1Connection timeout
4.4.2Connection dropped
4.7.1Temporary authentication failure

Handling the Event

Basic Handler

async function handleMessageBounce(event) {
const { account, data } = event;

console.log(`Bounce detected for ${account}:`);
console.log(` Recipient: ${data.recipient}`);
console.log(` Action: ${data.action}`);
console.log(` Original Message ID: ${data.messageId}`);

if (data.response) {
console.log(` Status: ${data.response.status}`);
console.log(` Message: ${data.response.message}`);
}

// Process based on bounce type
if (data.action === 'failed') {
await handleHardBounce(data);
} else if (data.action === 'delayed') {
await handleSoftBounce(data);
}
}

Updating Email Lists

async function handleHardBounce(bounceData) {
const { recipient, response } = bounceData;

// Mark email as invalid in your database
await db.contacts.update(
{ email: recipient },
{
$set: {
emailValid: false,
bounceReason: response?.message,
bounceCode: response?.status,
bouncedAt: new Date()
}
}
);

// Optionally notify the sender
if (bounceData.id) {
await notifySender(bounceData);
}
}

Tracking Bounce Metrics

async function trackBounceMetrics(event) {
const { account, data } = event;

// Extract bounce category from status code
const statusCode = data.response?.status || '';
const isHardBounce = statusCode.startsWith('5');
const category = getBounceCategory(statusCode);

await metrics.increment('email.bounces', {
account,
type: isHardBounce ? 'hard' : 'soft',
category,
mta: data.mta || 'unknown'
});
}

function getBounceCategory(status) {
if (!status) return 'unknown';

const [major, minor] = status.split('.');

if (minor === '1') return 'address'; // Address-related
if (minor === '2') return 'mailbox'; // Mailbox-related
if (minor === '3') return 'system'; // Mail system issues
if (minor === '4') return 'network'; // Network/routing
if (minor === '5') return 'protocol'; // Protocol issues
if (minor === '6') return 'content'; // Content issues
if (minor === '7') return 'security'; // Security/policy

return 'other';
}

Key Differences from messageFailed

The messageBounce and messageFailed events serve different purposes:

AspectmessageBouncemessageFailed
TriggerBounce email received in mailboxEmailEngine fails to deliver after all retries
SourceRemote mail server's bounce notificationEmailEngine's delivery system
TimingCan be minutes to days after sendingImmediate after final retry failure
DetectionRequires parsing bounce email formatDirect SMTP error response

Use messageBounce when you need to:

  • Track bounces from emails sent through other systems
  • Get detailed bounce information from the receiving server's perspective
  • Monitor mailboxes that receive bounce notifications

Use messageFailed when you need to:

  • Track delivery failures for emails sent through EmailEngine's queue
  • Get immediate feedback on delivery attempts
  • Handle failures before bounce notifications arrive

Best Practices

  1. Track both events - Use both messageBounce and messageFailed for complete deliverability monitoring
  2. Deduplicate bounces - The same delivery failure may trigger both events; use messageId to correlate
  3. Handle missing fields - Not all bounces include complete information; validate fields before use
  4. Distinguish bounce types - Hard bounces require different handling than soft bounces
  5. Update promptly - Remove hard-bounced addresses from mailing lists immediately
  6. Log for analysis - Store bounce data for deliverability trend analysis
  7. Monitor the MTA field - Track which receiving servers generate the most bounces

See Also