Mailhooks LogoMailhooks
Use CasesPricingDocsBlog
Use CasesPricingDocsBlog

Documentation

Getting Started

IntroductionQuick StartHow It Works

Guides

IMAP Client SetupBring Your Own StorageReal-time Notificationsn8n IntegrationDiscord IntegrationNotion IntegrationNotion CalendarCLI for Agents

API Reference

AuthenticationEmailsWebhooksInboxesDomainsReal-time (SSE)API Playground

Product

  • Features
  • Pricing

Legal

  • Terms of Service
  • Privacy Policy

Resources

  • Documentation
  • Blog
  • Discord

Contact

[email protected]

© 2026 Mailhooks. All rights reserved.

Getting Started

IntroductionQuick StartHow It Works

Guides

IMAP Client SetupBring Your Own StorageReal-time Notificationsn8n IntegrationDiscord IntegrationNotion IntegrationNotion CalendarCLI for Agents

API Reference

AuthenticationEmailsWebhooksInboxesDomainsReal-time (SSE)API Playground

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.

Tip: Use a subdomain like mail.yourdomain.com instead of your root domain to avoid conflicts with existing email services.
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:

  • [email protected]
  • [email protected]
  • Any address at your domain will work — no configuration needed per address

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/..." } ] } }
Key design choice: Attachments are provided as downloadable URLs instead of base64-encoded blobs. This keeps webhook payloads small and predictable. Download attachments on demand rather than inflating every webhook delivery.

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:

Reply-by-Email

Let users respond to notifications from their inbox.

Email to Webhook Triggers

Trigger workflows the moment an email arrives.

n8n Email Trigger

Use Mailhooks as the email trigger for n8n automations.

Email to Notion

Turn emails into Notion database entries automatically.

Next Steps

Quick Start Guide

Walk through the full setup process step by step.

Webhooks API Reference

Full API documentation for webhook configuration.

Use Cases

Explore what you can build with email webhooks.

Get Started for FreeAPI Reference