How to Receive Email via Webhook

A complete guide to receiving inbound email as HTTP webhooks. Set up in minutes with code examples for Node.js, Python, and cURL.

How It Works

Mailhooks acts as a bridge between the email world and your application. When someone sends an email to your domain, Mailhooks receives it, parses it into structured JSON, and forwards it to your application via an HTTP POST webhook. Here's the flow:

1

Email arrives

Someone sends an email to any address at your domain (e.g., [email protected]).

2

Parsed to JSON

Mailhooks receives the raw MIME, parses headers, body, and attachments into a clean, consistent JSON structure.

3

Webhook sent

An HTTP POST request is sent to your endpoint with the JSON payload. Your app processes it like any other API request.

Step 1

Add Your Domain

After signing up, navigate to the Domains section in your dashboard and click "Add Domain". Enter the domain you want to receive email on — for example, mail.yourdomain.com.

Step 2

Configure DNS Records

Mailhooks provides the DNS records you need to add to your domain. These tell other mail servers to route inbound email to Mailhooks. You'll typically need:

MX

MX Record

Points inbound email to Mailhooks' mail servers. Add the provided MX record to your DNS configuration.

TXT

TXT Record (SPF)

Authorizes Mailhooks to receive email on your domain's behalf.

DNS changes typically propagate within 5-30 minutes. Once verified, you can start receiving email immediately.

Step 3

Create a Webhook Endpoint

Your webhook endpoint is a URL on your server that receives HTTP POST requests from Mailhooks. It should accept JSON, verify the request, and return a 200 status quickly.

See the code examples below for complete implementations in Node.js, Python, and more.

Step 4

Connect in Mailhooks

Go to the Webhooks section in your dashboard and create a new webhook. Enter your endpoint URL and select the events you want to receive (e.g., email.received).

For integrations like Notion, Discord, or n8n, you can use our built-in connectors instead of a custom webhook — no code required.

Step 5

Send a Test Email

Send an email to any address at your domain. Mailhooks will receive it, parse it, and deliver it to your webhook. You should see the JSON payload arrive at your endpoint within seconds.

Example test addresses:

Code Examples

Here are complete examples for receiving Mailhooks webhooks in popular languages and frameworks. Each example shows how to set up a webhook endpoint, verify the request, and process the email payload.

Node.js / Express

const express = require('express');
const app = express();

// Parse JSON bodies
app.use(express.json());

// Webhook endpoint for Mailhooks
app.post('/api/webhooks/mailhooks', async (req, res) => {
  const { event, data } = req.body;

  if (event === 'email.received') {
    const { from, to, subject, text, html, attachments } = data;

    console.log(`New email from ${from}`);
    console.log(`Subject: ${subject}`);
    console.log(`Body: ${text || '(HTML only)'}`);

    // Process attachments
    for (const attachment of attachments) {
      console.log(`Attachment: ${attachment.filename} (${attachment.contentType})`);
      // Download from attachment.url when needed
      // const file = await fetch(attachment.url);
    }

    // Your business logic here:
    // - Create a support ticket
    // - Forward to Slack
    // - Store in database
    // - Trigger automation
  }

  // Always return 200 quickly
  res.status(200).json({ received: true });
});

app.listen(3000, () => {
  console.log('Webhook server running on port 3000');
});

Prefer TypeScript? Use our official @mailhooks/sdk package for type-safe API access.

Python / Flask

from flask import Flask, request, jsonify
import requests

app = Flask(__name__)

@app.route('/api/webhooks/mailhooks', methods=['POST'])
def handle_mailhooks_webhook():
    payload = request.json
    event = payload.get('event')
    data = payload.get('data', {})

    if event == 'email.received':
        from_addr = data.get('from')
        subject = data.get('subject')
        text_body = data.get('text', '(HTML only)')
        attachments = data.get('attachments', [])

        print(f"New email from {from_addr}")
        print(f"Subject: {subject}")
        print(f"Body: {text_body}")

        # Process attachments
        for attachment in attachments:
            filename = attachment.get('filename')
            content_type = attachment.get('contentType')
            url = attachment.get('url')
            print(f"Attachment: {filename} ({content_type})")
            # Download when needed:
            # response = requests.get(url)

        # Your business logic here:
        # - Create a support ticket
        # - Forward to Slack
        # - Store in database
        # - Trigger automation

    return jsonify({'received': True}), 200

if __name__ == '__main__':
    app.run(port=3000)

cURL / REST API

You can also retrieve emails via the REST API without webhooks:

# List all received emails
curl -H "x-api-key: mh_your_api_key_here" \
     https://api.mailhooks.dev/v1/emails

# Get a specific email
curl -H "x-api-key: mh_your_api_key_here" \
     https://api.mailhooks.dev/v1/emails/msg_abc123

# Filter by sender
curl -H "x-api-key: mh_your_api_key_here" \
     "https://api.mailhooks.dev/v1/[email protected]"

# Get email body only
curl -H "x-api-key: mh_your_api_key_here" \
     https://api.mailhooks.dev/v1/emails/msg_abc123/body

Webhook Payload

Every webhook delivery contains a consistent JSON payload with all email data structured and ready to use:

{
  "event": "email.received",
  "timestamp": "2025-01-15T10:30:00Z",
  "data": {
    "id": "msg_abc123",
    "from": "[email protected]",
    "fromName": "John Smith",
    "to": "[email protected]",
    "subject": "Question about my order",
    "text": "Hi, I have a question about order #12345...",
    "html": "

Hi, I have a question about order #12345...

", "headers": { "message-id": "", "date": "Wed, 15 Jan 2025 10:30:00 +0000", "content-type": "multipart/mixed; boundary=..." }, "attachments": [ { "filename": "invoice.pdf", "contentType": "application/pdf", "size": 45678, "url": "https://files.mailhooks.dev/..." } ] } }

Best Practices

1

Return 200 quickly

Process the webhook asynchronously. Return a 200 status as fast as possible — put the payload on a queue and process it in the background.

2

Verify webhook signatures

Use the webhook signing secret from your dashboard to verify that incoming requests are genuinely from Mailhooks. This prevents abuse and ensures data integrity.

3

Use idempotent handlers

Mailhooks may deliver the same webhook more than once in rare cases. Design your handler to be idempotent — use the email ID to deduplicate.

4

Download attachments on demand

Attachment URLs are signed and time-limited. Download them within 24 hours. Don't store the URLs — download the file and store it in your own system.

Common Use Cases

Once you're receiving email webhooks, here are some popular patterns:

Next Steps

© 2026 Mailhooks. All rights reserved.