Understanding how emails flow through Ark from send to delivery
Every email sent through Ark goes through a series of states from initial submission to final delivery (or failure). Understanding this lifecycle helps you build robust email handling in your application.
A temporary delivery failure occurred. Ark will automatically retry with exponential backoff up to 18 times over approximately 48 hours. If all retries fail, the message transitions to hardfail and the recipient is added to the suppression list.
A permanent delivery failure occurred. The email will not be retried and the recipient is immediately added to the suppression list.Hard failures occur in two scenarios:
Immediate rejection: The recipient’s mail server permanently rejected the email (SMTP 5xx error). Common reasons include non-existent mailbox, invalid domain, or policy rejection.
Retry exhaustion: A soft failure that couldn’t be resolved after 18 retry attempts over ~48 hours.
Copy
{ "id": "msg_abc123", "status": "hardfail", "timestampIso": "2024-01-15T10:00:02Z", "details": "550 5.1.1 The email account does not exist"}
Immediate suppression on hard fail. When an email hard fails, the recipient is immediately added to the suppression list with reason hard fail. This prevents future delivery attempts to invalid addresses and protects your sender reputation.
A bounce notification (NDR - Non-Delivery Report) was received after the email was initially accepted. This happens when the recipient’s server accepts the message but later determines it cannot be delivered.The recipient is immediately added to the suppression list when a bounce is received.
Copy
{ "id": "msg_abc123", "status": "bounced", "timestampIso": "2024-01-15T10:00:02Z", "bounce_details": { "original_recipient": "[email protected]", "diagnostic_code": "smtp; 550 User not found" }}
”Requested action aborted: local error in processing”
452
Insufficient storage
”Mailbox full”, “Quota exceeded”
Soft bounces convert to hard fails after 18 retries. When a soft bounce exhausts all retry attempts, the message status changes to HardFail and the recipient is added to the suppression list with reason too many soft fails. This prevents indefinite retry attempts to persistently unreachable addresses.
app.post('/webhooks/ark', async (req, res) => { const event = req.body; switch (event.event) { case 'MessageSent': console.log(`Email ${event.payload.message.token} sent`); await updateEmailStatus(event.payload.message.token, 'sent'); break; case 'MessageBounced': console.log(`Email bounced: ${JSON.stringify(event.payload)}`); await handleBounce(event.payload); break; case 'MessageDelayed': console.log('Email delayed, will retry'); break; case 'MessageDeliveryFailed': console.log('Email delivery failed'); break; } res.status(200).send('OK');});
Copy
post '/webhooks/ark' do event = JSON.parse(request.body.read) case event['event'] when 'MessageSent' puts "Email #{event['payload']['message']['token']} sent" update_email_status(event['payload']['message']['token'], 'sent') when 'MessageBounced' puts "Email bounced: #{event['payload']}" handle_bounce(event['payload']) when 'MessageDelayed' puts 'Email delayed, will retry' when 'MessageDeliveryFailed' puts 'Email delivery failed' end 'OK'end
For temporary failures (softfail), Ark automatically retries using exponential backoff. The delay between retries follows the formula: (1.3^attempts) × 5 minutes.
Attempt
Approximate Delay
Cumulative Time
1
5 minutes
5 min
2
6.5 minutes
12 min
3
8.5 minutes
20 min
5
14 minutes
45 min
8
32 minutes
1.5 hours
10
69 minutes
3.5 hours
12
2.4 hours
7 hours
15
5.6 hours
18 hours
18
14 hours
~48 hours
After 18 failed attempts (configurable), the email is marked as hardfail and the recipient is automatically added to the suppression list with reason “too many soft fails”.
The maximum delivery attempts can be configured per installation. The default is 18 attempts, which spans approximately 48 hours of retry attempts.
Hard failures result in automatic suppression. Whether the failure is immediate (SMTP 5xx error) or after retry exhaustion, the recipient is automatically added to the suppression list. Future emails to this address will be held with status “Recipient is on the suppression list” until manually removed.
Bounced status does NOT auto-suppress. When an NDR is received and the message status changes to bounced, the recipient is NOT automatically added to the suppression list. Handle the MessageBounced webhook to manually suppress if desired.
Successful delivery clears suppression. If you manually retry a message to a suppressed address and it succeeds, the address is automatically removed from the suppression list.