Skip to content
Receiving

Receive email at your own domain, over an API

You do not poll for mail. A webhook fires the moment a message arrives, you read the parts you want, and you give the storage back when you are done.

Handle one received message

// 1. verify the delivery, as with every Rasket eventconst event = verify(rawBody, headers, process.env.RASKET_WEBHOOK_SECRET);if (event.type !== "email.received") return;
// 2. route on what the payload already carries, with no call at allconst queue = event.data.received_for.some(  (address) => address.startsWith("billing@"),) ? "billing" : "support";
// 3. read the parts the payload deliberately leaves outconst { body: message } = await rasket.emails.receiving.get(id);const { body: files } = await rasket.emails.receiving.attachments.list(id);
// 4. each part carries a fresh signed link, good for fifteen minutesfor (const file of files.data) {  if (file.download_url === undefined) continue;  await archive(file.filename, await fetch(file.download_url));}
// 5. give the storage backawait rasket.emails.receiving.remove(id);
What you get

What the inbound email API gives you

Inbound mail as a resource your code reads, with the same signed events, the same keys and the same domains as everything you send.

  • One event carries enough to route

    The email.received payload has the sender, the subject, the attachment list and received_for: the addresses of yours the message was accepted for. Route on that and the common case needs no call at all.

  • Attachments behind signed links

    Ask for the attachments when you want the bytes. Each part comes back with a link good for fifteen minutes, and following it needs no API key: the signed link is the credential.

  • Route on the address we accepted

    received_for is what the message was actually delivered to. The to header is whatever the sender wrote, and a sender can write anything, so routing reads the first and not the second.

  • A record even when we keep nothing

    A message that fails the virus scan, or arrives over your storage quota or daily cap, is still recorded with a dropped_reason and no content, so nothing arriving and something we would not keep are never the same silence.

  • An API surface, not a mailbox

    There is nothing to live in: no folders, no replies, no seat to buy. Mail arrives as an event your code handles and files where it belongs, and the dashboard lists what arrived so you can watch it while you build.

How receiving works, end to end

Three steps, and after the first one there is no setup left to do.

  1. 1

    Be reachable

    Turn receiving on for a verified domain and publish the one MX record we hand back. Every team also gets a managed receiving address, so you can build the handler before you touch DNS.

  2. 2

    Subscribe a webhook to email.received

    The event arrives signed, like every other one, and carries the envelope and the attachment list. Verify it, read received_for, and send the message wherever it belongs in your product.

  3. 3

    Read what you need, then delete it

    Fetch the message for its headers and bodies, fetch the attachments for links to the bytes, and delete it when you are done. Deleting is the only way to free inbound storage before retention does.

Choosing where your domain receives mail

The address people write to is yours to choose. Everything downstream is identical whichever you pick.

  • The address you already have

    Every team is given a managed receiving address the first time it opens the Receiving screen. Anything before the @ reaches you, so you can tag threads and build the whole loop without registering a name or publishing a record.

  • A label on your own domain

    Turn receiving on for a verified domain and it sits at inbound unless you say otherwise, so anything@inbound.acme.example lands with us. Any other label works just as well: pick the word your product already uses.

  • The domain itself

    Set the receiving host to the domain and anything@acme.example reaches us. That takes the domain's mail away from whichever mailbox provider has it today, so choose it only for a domain whose every address should come to you here.

Receiving is available in two of the regions a domain can sit in. A verified domain outside them says so on its page, rather than offering a toggle that would do nothing.

Dropped messages, retention and inbound storage

What happens to a message we accept but would not keep, and how the space it uses comes back.

Received mail counts against your plan's inbound storage, and there is a daily message cap as well. Over either, a new message is recorded with a dropped_reason instead of being stored, so the loop keeps running and you learn about it from the payload.

Why a message was recorded without content
dropped_reasonWhat it means
virusScanned and refused. The envelope is kept, the content is not.
storage_quotaYour inbound storage was full. Delete some mail, or raise the cap.
daily_capYou had already received your plan's messages for the day.
parse_failedWe could not read the structure. The raw source is still downloadable.

Deleting a message is the only way to free inbound storage before retention does. It removes the stored bytes as well as the record and returns the space to your quota, and there is no undo. Retention takes away what you leave behind, whole: a message past it answers 404 rather than coming back with an empty body.

Related features and receiving documentation

The parts of the product the inbound loop leans on, and the reference pages behind every claim on this page.

Plans, quotas and what each one includes are on the pricing page.

Questions about receiving email

How do I start receiving mail?

Turn receiving on for a verified domain and publish the one MX record we hand back. Every team is also given a managed receiving address without publishing anything, so you can build and test the handler before you touch DNS.

Where does my domain receive mail?

Wherever you choose. It sits at inbound by default, so anything@inbound.acme.example lands with us. Any other label works, and so does the domain itself, for anything@acme.example. That last one takes the domain's mail from whichever mailbox provider has it today, so pick it only for a domain whose every address should reach us.

Does the webhook carry the message body?

No, and that is a decision rather than an omission. A webhook is retried until your endpoint accepts it, and a body that was retried for hours is that content arriving again and again for a message you may not even want. The event carries enough to route on, and you read the rest when you need it.

How long do attachment links last?

Fifteen minutes, and every read mints fresh ones. Following a link needs no Authorization header, so a browser can fetch the bytes without an API key ever reaching one. A part we would not store is listed with no link at all, so check for the field rather than assuming it.

What happens to a message with a virus, or one over my quota?

It is recorded without content and with a dropped_reason saying which: virus, storage_quota, daily_cap or parse_failed. The loop keeps running and you find out from the payload rather than from a gap in what arrived.

Is there a size limit on an inbound message?

Yes. A message over 150 KB, attachments included, is refused at the sending server, so there is no event and no record. We do not hold it and we do not truncate it.

Start receiving mail today

Take the managed address your team already has, point a webhook at your handler, and run the loop before you touch DNS.