Using webhooks with EmailEngine
These are the available events that EmailEngine sends webhooks for.
Type | Name | Description |
---|---|---|
messageNew | New Email | A new email is found from a folder (new email) |
messageDeleted | Deleted Message | A previously present email is not found from a folder (deleted email) |
messageUpdated | Flag Change | Email flags are changed (flag change) |
messageMissing |
Missing Message | A message that should exist, was not found. Indicates syncing errors. |
messageSent | Message Accepted | Queued email is accepted by the MTA server (message accepted) |
messageDeliveryError | SMTP error | EmailEngine failed to send an email to the SMTP server. This action might be retried. (SMTP error) |
messageFailed | Message Bounced | EmailEngine fails to deliver a queued email to the MTA server (message bounced) |
messageBounce | Bounce Received | Bounce response email is received (bounce received) |
messageComplaint | Complaint received | FBL complaint was detected |
mailboxReset |
Mailbox Reset | UIDValidity for a folder changes (mailbox reset) |
mailboxDeleted |
Folder Deleted | A previously present folder is not found (folder deleted) |
mailboxNew |
New Folder | A new folder is found (new folder) |
authenticationError |
Authentication Failure | EmailEngine fails to authenticate an email account |
authenticationSuccess |
Authentication Success | An email account is successfully authenticated |
connectError |
Connection Failure | EmailEngine fails to establish a connection to an email server |
accountAdded |
Account added | a new email account was registered with EmailEngine |
accountInitialized |
Account initialized | Account has been connected and the first sync is completed |
accountDeleted |
Account deleted | an email account was removed from EmailEngine |
trackOpen | Email open tracked | recipient opened an email |
trackClick | Link click tracked | recipient clicked on a link |
listUnsubscribe | Recipient unsubscribed | recipient unsubscribed from a list |
listSubscribe |
Recipient subscribed | recipient re-subscribed to a list |
A new message was added to a folder. This event is generated by incoming emails, uploaded emails, and emails moved or copied from one folder to another. IMAP does not distinguish "incoming" emails from messages that are added to a folder by other means.
NB! Content text webhook setting is enabled for this example, so there are
data.text.plain
anddata.text.html
fields set. The default would be to not include content text in the payload. To enable text processing, you can set it in the UI with Configuration → Webhooks → Text content → "Include text content in new email webhooks" or by settingnotifyText
totrue
with the Settings API.
{
"serviceUrl": "https://emailengine-dev.apps.srv.dev",
"account": "postalsys",
"date": "2023-03-14T11:13:10.609Z",
"path": "[Gmail]/All Mail",
"specialUse": "\\All",
"event": "messageNew",
"data": {
"id": "AAAAAQABDFI",
"uid": 68690,
"path": "[Gmail]/All Mail",
"emailId": "1760341395373354319",
"threadId": "1760341395373354319",
"date": "2023-03-14T11:12:45.000Z",
"flags": [],
"labels": [
"\\Important",
"\\Inbox"
],
"unseen": true,
"size": 8271,
"subject": "Impressed by the new features of EmailEngine!",
"from": {
"name": "Andris Reinman",
"address": "andris.reinman@gmail.com"
},
"replyTo": [
{
"name": "Andris Reinman",
"address": "andris.reinman@gmail.com"
}
],
"sender": {
"name": "Andris Reinman",
"address": "andris.reinman@gmail.com"
},
"to": [
{
"name": "",
"address": "andris@postalsys.com"
}
],
"messageId": "<CAPacwgwKMETwvftKuQyieSKmp1C+NJcZtqjZ2pSALZkjB-CCbQ@mail.gmail.com>",
"text": {
"id": "AAAAAQABDFKTkaExkaEykA",
"encodedSize": {
"plain": 1535,
"html": 1630
},
"plain": "Dear Postal Systems OÜ,\n\nI hope this email finds you well. I am writing to express my excitement and\nadmiration for the new features of EmailEngine. As a regular user of email\nservices, I have found it difficult to manage my multiple email accounts on\ndifferent apps. However, EmailEngine has proved to be a game-changer in\nthis regard.\n\nI am amazed by how EmailEngine allows other apps to access regular email\naccounts, making the process of managing emails much easier and efficient.\nThe user-friendly interface and advanced security features make it a\nreliable choice for anyone who wants to manage their emails in a\nhassle-free manner.\n\nOne of the most impressive features of EmailEngine is its compatibility\nwith different email service providers. It seamlessly integrates with\nGmail, Outlook, Yahoo, and many other popular email services, allowing\nusers to manage their emails in one place without having to switch between\ndifferent apps.\n\nFurthermore, the customizable API and SDKs of EmailEngine make it possible\nfor developers to integrate it into their apps, enabling their users to\naccess their email accounts without leaving the app. This feature is not\nonly convenient but also saves time and enhances the user experience.\n\nOverall, I am thoroughly impressed by the new features of EmailEngine, and\nI believe it is a significant step towards making email management more\naccessible and efficient. Thank you for providing such a valuable service\nto users like me.\n\nBest regards,\nAndris\n",
"html": "<div dir=\"ltr\">Dear Postal Systems OÜ,<br><br>I hope this email finds you well. I am writing to express my excitement and admiration for the new features of EmailEngine. As a regular user of email services, I have found it difficult to manage my multiple email accounts on different apps. However, EmailEngine has proved to be a game-changer in this regard.<br><br>I am amazed by how EmailEngine allows other apps to access regular email accounts, making the process of managing emails much easier and efficient. The user-friendly interface and advanced security features make it a reliable choice for anyone who wants to manage their emails in a hassle-free manner.<br><br>One of the most impressive features of EmailEngine is its compatibility with different email service providers. It seamlessly integrates with Gmail, Outlook, Yahoo, and many other popular email services, allowing users to manage their emails in one place without having to switch between different apps.<br><br>Furthermore, the customizable API and SDKs of EmailEngine make it possible for developers to integrate it into their apps, enabling their users to access their email accounts without leaving the app. This feature is not only convenient but also saves time and enhances the user experience.<br><br>Overall, I am thoroughly impressed by the new features of EmailEngine, and I believe it is a significant step towards making email management more accessible and efficient. Thank you for providing such a valuable service to users like me.<br><br>Best regards,<br>Andris<br></div>\n",
"hasMore": false
},
"category": "primary",
"isAutoReply": false,
"seemsLikeNew": true,
"messageSpecialUse": "\\Inbox",
"summary": {
"id": "chatcmpl-6twsSdxRdTVq8uWPfbsdWSgQViJI3",
"tokens": 512,
"summary": "Andris is impressed with the new features of EmailEngine and finds it easier to manage his multiple email accounts on different apps with EmailEngine. He appreciates its user-friendly interface, advanced security features, compatibility with different email service providers, customizable API and SDKs, and its ability to allow other apps to access regular email accounts.",
"sentiment": "positive"
}
},
"_route": {
"id": "AAABhpMgNhsAAAAE"
}
}
\All
, so check the messageSpecialUse
property for better indicationspecialUse
property, but for Gmail accounts, where emails mostly reside in the \All
folder, it is different.Gmail sorts incoming emails into different categories like promotions, social, and primary and displays emails under these category tabs. For IMAP, all these emails still look like regular INBOX folder emails. EmailEngine can resolve the category of incoming emails and include this information in the payload of the messageNew
webhook.
Category resolving is not enabled by default. To enable it, navigate to Configuration -> Service, and then to the Labs section. Mark the "Resolve Gmail categories" checkbox, and save the settings.
Now, whenever an email lands in the Inbox of an email account that EmailEngine tracks, the messageNew
webhook for that email will include a property called category
, and the value is one of the following: social, promotions, updates, forums, and primary.
A message was deleted from a folder. This happens when a message was either deleted or moved to another folder.
{
"account": "pangalink",
"date": "2022-01-17T11:54:02.089Z",
"path": "[Gmail]/All Mail",
"specialUse": "\\All",
"event": "messageDeleted",
"data": {
"id": "AAAAAQAANJc",
"uid": 13463
}
}
This event is fired when a change is detected with a message. Most commonly, when the user marks a message as read or unread.
{
"account": "pangalink",
"date": "2022-01-17T11:56:13.146Z",
"path": "[Gmail]/All Mail",
"specialUse": "\\All",
"event": "messageUpdated",
"data": {
"id": "AAAAAQAANJY",
"uid": 13462,
"changes": {
"flags": {
"added": [
"\\Seen"
]
}
}
}
}
EmailEngine managed to deliver the email to the MTA server. In this case, the webhooks should arrive pretty much immediately.
{
"account": "example",
"date": "2021-12-23T10:32:39.499Z",
"event": "messageSent",
"data": {
"messageId": "<a00576bd-f757-10c7-26b8-885d7bbd9e83@ekiri.ee>",
"response": "250 2.0.0 Ok: queued as 5755482356",
"envelope": {
"from": "andris@ekiri.ee",
"to": [
"andris@ethereal.email"
]
}
}
}
EmailEngine retries sending multiple times, so receiving the webhook takes a long time (EmailEngine sends the failure webhook once it has given up retrying the message).
{
"account": "example",
"date": "2021-12-23T11:58:50.181Z",
"event": "messageFailed",
"data": {
"messageId": "<97ac5d9a-93c7-104b-8d26-6b25f8d644ec@ekiri.ee>",
"queueId": "610c2c93e608bd37",
"error": "Error: Invalid login: 535 5.7.8 Error: authentication failed: "
}
}
EmailEngine found an ARF formatted FBL report from the Inbox folder. If such an email is found, then EmailEngine parses it and posts parsed information as the messageComplaint
webhook.
{
"serviceUrl": "http://127.0.0.1:3000",
"account": "example",
"date": "2022-09-27T12:33:42.635Z",
"event": "messageComplaint",
"data": {
"complaintMessage": "AAAAAQAABvE",
"arf": {
"source": "Hotmail",
"feedbackType": "abuse",
"abuseType": "complaint",
"originalRcptTo": [
"recipient@hotmail.co.uk"
],
"sourceIp": "1.2.3.4",
"arrivalDate": "2021-10-22T13:04:36.017Z"
},
"headers": {
"messageId": "<67d3846d-b819-9c54-5053-a81fdc432425@example.com>",
"from": "user@example.com",
"to": [
"recipient@hotmail.co.uk"
],
"subject": "Hello world",
"date": "2021-10-22T16:04:33.000Z"
}
}
}
NB! included fields depend on the reporting server. Sometimes important information like the source email Message-ID value might be missing.
EmailEngine retries sending multiple times. For every failing try a messageDeliveryError
is sent.
{
"serviceUrl": "http://127.0.0.1:3000",
"account": "example",
"date": "2022-09-14T15:07:35.832Z",
"event": "messageDeliveryError",
"data": {
"queueId": "1833c8a88a86109a1bf",
"envelope": {
"from": "andris@ekiri.ee",
"to": [
"andris@ethereal.email"
]
},
"messageId": "<29e26263-7125-ff56-4f80-83a5cf737d5e@ekiri.ee>",
"error": "400 Message Not Accepted",
"errorCode": "EPROTOCOL",
"smtpResponseCode": 400,
"job": {
"attemptsMade": 1,
"attempts": 10,
"nextAttempt": "2022-09-14T15:07:45.465Z"
}
}
}
A new bounce response message was found from the account. The bounce data includes messageId
value but no id
value, so you have to look up the bounced message using the Message-ID header value.
If multiple recipients for the same message bounce, you get a separate bounce event for each of these recipients.
{
"account": "pangalink",
"date": "2021-11-28T10:17:29.728Z",
"event": "messageBounce",
"data": {
"bounceMessage": "AAAAAQAABWw",
"recipient": "failed.recipient@example.com",
"action": "failed",
"response": {
"source": "smtp",
"message": "550 5.1.1 <failed.recipient@example.com>: Recipient address rejected: User unknown in relay recipient table",
"status": "5.1.1"
},
"mta": "mx.example.com",
"queueId": "BFC608226A",
"messageId": "<4dbe4a40f37e9c2ba5b25912bc7c8997@example.com>"
}
}
Some fields might be missing from a bounce webhook depending on how EmailEngine can parse the information out from the bounce.
Email client loaded the open tracking beacon. This only works if the email client loads external images. There might be false positives, for example, when a web-based email client caches linked images.
NB! Opens and clicks tracking is not enabled by default. You can enable it by navigating to Configuration → Service → Labs → Track opens and clicks.
{
"account": "example",
"date": "2022-03-24T08:28:32.992Z",
"event": "trackOpen",
"data": {
"messageId": "<2d4696ea-cb47-7af4-0bc3-81ea7a8008be@example.com>",
"remoteAddress": "1.2.3.4",
"userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.83 Safari/537.36"
}
}
A tracked link was clicked. False positives might occur when security software scans links in an incoming email.
NB! Opens and clicks tracking is not enabled by default. You can enable it by navigating to Configuration → Service → Labs → Track opens and clicks.
{
"account": "example",
"date": "2022-03-24T08:27:24.572Z",
"event": "trackClick",
"data": {
"messageId": "<49b6cdb1-5d43-e100-0833-bd61867b7bb3@example.com>",
"url": "https://google.com/",
"remoteAddress": "1.2.3.4",
"userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.83 Safari/537.36"
}
}
A recipient clicked on the unsubscribe link, or the email client posted the one-click unsubscribe request.
{
"account": "example",
"date": "2022-03-24T08:27:24.572Z",
"event": "listUnsubscribe",
"data": {
"recipient": "recipient@example.com",
"messageId": "<49b6cdb1-5d43-e100-0833-bd61867b7bb3@example.com>",
"listId": "my-customers-list",
"remoteAddress": "1.2.3.4",
"userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.83 Safari/537.36"
}
}
You can set custom headers for webhook requests with the webhooksCustomHeaders
setting, or from the webhook setting page in EmailEngine's admin dashboard.
In addition to custom headers, EmailEngine also includes some additional debugging headers, as shown below.
Header | Example value | Description |
---|---|---|
X-EE-Wh-Event-Id | "af8435d9-ceee-4715-be71-08ac9d2dc04a" |
UUID assigned to the event. All webhook instances of the same event have the same event ID |
X-EE-Wh-Custom-Route | "AAABiL8tBKsAAAAG" |
Id of the custom webhook route used for this webhook |
X-EE-Wh-Queued-Time | "0s" |
How much time was this webhook queued |
X-EE-Wh-Attempts-Made | "1" |
The attempt counter for this webhook. Anything over 1 means that posting this webhook failed previously |
X-EE-Wh-Id | "907889" |
ID of the queued webhook entry |
EmailEngine makes up to 10 webhook delivery attempts before it considers a webhook payload undeliverable.
EmailEngine makes retry attempts with an exponential backoff strategy. The delay is 5000ms, and the formula to calculate the delay between attempts is the following:
2 ^ (attempts - 1) * delay milliseconds
Webhook jobs can be found from the notify
queue (Tools → Arena → notify).
You can find failed webhooks that are yet to be retried from the Delayed
job queue section and undeliverable webhooks from the Failed
section. By default, EmailEngine does not store failed jobs. You can set the number of Completed/Failed jobs to keep in the Configuration → Service → Queue Settings configuration section.