# Receiving emails

> Receive inbound email on a MailBlastr domain: every message is parsed and delivered to your webhook as an email.received event.

MailBlastr supports **receiving** email (commonly called *inbound*) alongside sending. Inbound is useful for building support inboxes, processing forwarded receipts and attachments, and replying to customers in-thread — all driven by your own code.

MailBlastr accepts every incoming message for your receiving domain, parses the body and attachments, stores the message, and then sends a `POST` request to a webhook endpoint you choose. Your application reacts to that callback.

## How it works

MailBlastr processes all incoming mail for your receiving domain, parses the contents and attachments, and delivers an `email.received` webhook to your endpoint. You can either use a MailBlastr-managed domain or [set up a custom receiving domain](https://www.mailblastr.com/docs/receiving/custom-domains).

> **Note:** **Any** email sent to your receiving domain is accepted and forwarded to your webhook. Route intelligently on the `to` field of the event — if your domain is `inbox.mailblastr.app`, you receive mail for `anything@inbox.mailblastr.app`. The same applies to a [custom domain](https://www.mailblastr.com/docs/receiving/custom-domains): if your domain is `yourdomain.tld`, you receive mail for `anything@yourdomain.tld`.

## 1. Get your receiving domain

Any email sent to an `<anything>@<id>.mailblastr.app` address is received by MailBlastr and forwarded to your webhook. To find your MailBlastr-managed receiving address:

1. **Open Emails** — Go to the Emails page in the MailBlastr dashboard.
2. **Select the Receiving tab** — Switch to the "Receiving" tab to see inbound configuration.
3. **Copy your receiving address** — Open the row menu and choose "Receiving address" to copy your `.mailblastr.app` address.

## 2. Configure a webhook

Create a webhook endpoint that subscribes to the `email.received` event:

1. **Open Webhooks** — Go to the Webhooks page in the dashboard.
2. **Add a webhook** — Click "Add Webhook" and enter the public URL of your endpoint.
3. **Subscribe to email.received** — Select the `email.received` event type and save.

> **Note:** For local development, expose your localhost server with a tunnel such as [ngrok](https://ngrok.com/download) or VS Code Port Forwarding. These give your dev machine a public URL (e.g. `https://example123.ngrok.io/api/webhook`) that MailBlastr can call.

## 3. Receive email events

In your application, create a route that accepts `POST` requests and reacts when the event `type` is `email.received`:

**Node.js**

```js
// app/api/events/route.ts (Next.js route handler)
import type { NextRequest } from 'next/server';
import { NextResponse } from 'next/server';

export const POST = async (request: NextRequest) => {
  const event = await request.json();

  if (event.type === 'email.received') {
    // event.data.email_id, event.data.from, event.data.to, ...
    return NextResponse.json(event);
  }

  return NextResponse.json({});
};
```

**Express**

```js
import express from 'express';

const app = express();
app.use(express.json());

app.post('/api/events', (req, res) => {
  const event = req.body;

  if (event.type === 'email.received') {
    // process the inbound email by id
    console.log(event.data.email_id, event.data.from, event.data.subject);
    return res.json(event);
  }

  res.json({});
});
```

**Python**

```python
from flask import Flask, request, jsonify

app = Flask(__name__)

@app.post("/api/events")
def events():
    event = request.get_json()

    if event.get("type") == "email.received":
        data = event["data"]
        print(data["email_id"], data["from"], data["subject"])
        return jsonify(event)

    return jsonify({})
```

Once you receive the event you can fetch the full message and process its body and attachments. We strongly recommend [verifying the webhook signature](https://www.mailblastr.com/docs/webhooks/verify) so only genuine MailBlastr requests are accepted.

## The email.received payload

The webhook body carries the event envelope plus a `data` object with the message **metadata** — id, addressing, `message_id`, subject, and attachment metadata:

```json
{
  "type": "email.received",
  "created_at": "2026-02-22T23:41:12.126Z",
  "data": {
    "email_id": "56761188-7520-42d8-8898-ff6fc54ce618",
    "created_at": "2026-02-22T23:41:11.894719+00:00",
    "from": "onboarding@mailblastr.dev",
    "to": ["delivered@mailblastr.dev"],
    "bcc": [],
    "cc": [],
    "received_for": ["forwarded@example.com"],
    "message_id": "<111-222-333@email.example.com>",
    "subject": "Sending this example",
    "attachments": [
      {
        "id": "2a0c9ce0-3112-4728-976e-47ddcd16a318",
        "filename": "avatar.png",
        "content_type": "image/png",
        "content_disposition": "inline",
        "content_id": "img001"
      }
    ]
  }
}
```

> **Warning:** The webhook does **not** include the email body, headers, or attachment content — only metadata. Call the [Retrieve received email](https://www.mailblastr.com/docs/receiving/get-email-content) API for the body and headers, or the [List attachments](https://www.mailblastr.com/docs/receiving/attachments) API for attachment content. This keeps payloads small enough for serverless platforms with limited request-body sizes.

### Envelope fields

The top-level envelope wraps every webhook and identifies the event:

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `type` | string | No | The event type. For inbound mail this is always `email.received`. |
| `created_at` | string | No | ISO 8601 timestamp for when the event was generated. |
| `data` | object | No | The message metadata (fields below). |

### data fields

The `data` object carries the parsed addressing and threading metadata for the received message:

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `email_id` | string | No | The received-email id. Pass it to `GET /emails/receiving/:id` to fetch the body/headers, or to `GET /emails/receiving/:id/attachments` for files. |
| `created_at` | string | No | ISO 8601 timestamp (with timezone offset) for when the message was received and stored. |
| `from` | string | No | The envelope/header `From` address of the inbound message. |
| `to` | string[] | No | The `To` recipients the message was addressed to. Route or filter on this to decide how to handle the mail. |
| `cc` | string[] | No | The `Cc` recipients, if any (empty array when none). |
| `bcc` | string[] | No | The `Bcc` recipients exposed to MailBlastr, if any (empty array when none). |
| `received_for` | string[] | No | The address(es) the message was actually delivered for at the SMTP envelope level — useful when the mail was forwarded or aliased and the visible `to` differs from the delivery target. |
| `message_id` | string | No | The original `Message-ID` header (angle-bracketed, e.g. `<111-222-333@email.example.com>`). Use it as `In-Reply-To` to [reply in thread](https://www.mailblastr.com/docs/receiving/reply-to-emails). |
| `subject` | string | No | The decoded `Subject` header. |
| `attachments` | object[] | No | Attachment **metadata** only (id, filename, content_type, content_disposition, content_id) — not the bytes. See [attachment fields](https://www.mailblastr.com/docs/receiving/attachments). |

## What you can do with a received email

- [Get the email content](https://www.mailblastr.com/docs/receiving/get-email-content) — HTML, plain text, and headers.
- [Process attachments](https://www.mailblastr.com/docs/receiving/attachments) — download and inspect attached files.
- [Forward the email](https://www.mailblastr.com/docs/receiving/forward-emails) to another address.
- [Reply in the same thread](https://www.mailblastr.com/docs/receiving/reply-to-emails) using the original `message_id`.

## FAQ

### Will I receive mail for any address at my domain?

Yes. Once the MX record is in place for your [custom domain](https://www.mailblastr.com/docs/receiving/custom-domains), MailBlastr receives mail for *any* address at that domain — `<anything>@yourdomain.tld`. Filter or route on the `to` field of the event. The same applies to a MailBlastr-managed domain such as `inbox.mailblastr.app`.

### Can I receive on a subdomain?

Yes. Add the MX record to any subdomain (e.g. `subdomain.yourdomain.tld`) and receive mail there.

### Will I lose mail if my webhook endpoint is down?

No. MailBlastr stores every inbound message as soon as it arrives, so you can always retrieve it from the dashboard or via the [Receiving API](https://www.mailblastr.com/docs/receiving/get-email-content) even if your endpoint was unavailable. Failed webhook deliveries are retried, and you can replay individual events from the [Webhooks](https://www.mailblastr.com/docs/webhooks/overview) page.

### How do I confirm a webhook really came from MailBlastr?

Every webhook is signed. Verify the signature headers before trusting the payload — see [Verify webhook requests](https://www.mailblastr.com/docs/webhooks/verify).
