Mailgun Example Webhook
This example shows a webhook-triggered process that receives an inbound email notification from Mailgun and saves any attached files to a Datasource.
Mailgun POSTs the parsed email as form data to the webhook URL. Inside the Process's script, that data is available as a JSON string on WEBHOOK.body, so JSON.parse(WEBHOOK.body) gives back the fields Mailgun sent, including timestamp, token, signature, and any files.
Because a webhook URL can be called by anyone who has it, the script should verify the request actually came from Mailgun before acting on it. Mailgun signs every request with a value derived from your account's signing key, the request timestamp and the request token, hashed with HMAC-SHA256 and hex-encoded (see Mailgun's webhook security docs). The signing key is stored as a Process Secret named MAILGUN_WEBHOOK_SIGN_KEY and read with security.getSecret, then compared using security.sha256HmacHex, which produces the same hex format Mailgun sends in signature. If the computed value doesn't match, the script aborts the process with script.abort.
Once the payload is verified, the script loops over any files on the email and writes each one to the email_files/ folder of the process's Datasource under its original filename. Mailgun caps the total message size (body plus attachments) at 25MB, so attachments larger than that won't reach the webhook, see Mailgun's limits documentation for details.
Setup
- Create a scriptable process with the script below.
- Generate a webhook URL for that process.
- Submit a request to the MODLR Team and share the webhook URL with them - they'll set up an inbox address on your behalf that listens for inbound mail and forwards it to your webhook.
js
const body = JSON.parse(WEBHOOK.body);
const { timestamp, token, signature } = body;
// Example validate payload from Mailgun
const encodedToken = security.sha256HmacHex(security.getSecret("MAILGUN_WEBHOOK_SIGN_KEY"), `${timestamp}${token}`);
if (encodedToken != signature) {
script.abort('Invalid signature')
return
}
if (body.files) {
for (let i = 0; i < body.files.length; i++) {
const file = body.files[i];
console.log(file.filename)
datasource.binarySave(`email_files/${file.filename}`, file.content)
}
}