Recebimento
Receba e-mails no seu próprio domínio, leia pela API compatível com o Resend, espere por eles, responda e seja avisado pelo webhook email.received a cada mensagem. Beta.
O recebimento transforma um domínio que você verificou num lugar que recebe
e-mails. Um e-mail enviado para os endereços dele chega ao servidor de e-mail
do MillionSend, fica guardado com criptografia e volta para você pela API,
pelo webhook email.received, pelo painel (Caixas de entrada → Todos os
recebidos) e pelo servidor MCP. A API é a de recebimento do
Resend, então os SDKs oficiais do Resend funcionam com o MillionSend sem
mudanças, forward() incluído.
Quais endereços recebem é você quem decide: o endereço de cada caixa de entrada que você criar, que guarda os e-mails em conversas com respostas, rascunhos e regras de segurança para um agente de IA ou para pessoas, e, com o pega-tudo ligado, todos os outros endereços do domínio.
O recebimento está em beta público e aparece com o selo Beta no painel. Toda mensagem ganha uma nota de spam e um nível de confiança no remetente, e passa por um antivírus onde a instância roda um. E-mail infectado fica retido; fora isso, o e-mail num endereço do pega-tudo é guardado do jeito que chegou, com esses resultados para o seu código decidir o que fazer.
Como funciona
O e-mail chega até você do mesmo jeito que chega a qualquer caixa de entrada: o servidor de quem envia consulta o registro MX do domínio do destinatário e entrega no host que ele indica.
- O servidor de quem envia lê o registro MX do seu domínio e se conecta ao MX do MillionSend.
- Para cada destinatário (
RCPT TO), o MX confere se o domínio recebe aqui e se o endereço tem uma caixa de entrada, a não ser que o pega-tudo do domínio esteja ligado. Um endereço de qualquer outro domínio é recusado, então o MX nunca repassa e-mail para lugar nenhum. - A mensagem vai chegando (no máximo 40 MB). O MX verifica SPF, DKIM, DMARC
e ARC; o MillionSend passa a mensagem pelo antivírus, onde a instância roda
um, dá uma nota de spam e a guarda antes de o MX responder
250. A partir daí a mensagem é sua, e o servidor de quem enviou terminou o trabalho. - O
email.receiveddispara, e a mensagem aparece na API e no painel. O e-mail que uma caixa retém, na quarentena ou durante a análise, dispara quando é entregue ou liberado.
Toda recusa acontece durante essa conversa SMTP, então o servidor de quem envia continua com a mensagem e decide o que fazer com ela. O MillionSend nunca envia um bounce por conta própria.
| Resposta | Quando | O servidor de quem envia |
|---|---|---|
550 5.1.1 | O domínio não recebe aqui: é desconhecido ou está com o recebimento desligado. | Devolve a mensagem ao remetente. |
550 5.1.1 | O endereço não tem caixa de entrada, ou a caixa dele expirou, e o pega-tudo do domínio está desligado ("No such recipient here"). | Devolve a mensagem ao remetente. |
550 5.7.1 | A equipe dona do domínio está suspensa. | Devolve a mensagem ao remetente. |
552 5.3.4 | A mensagem passa de 40 MB. | Devolve a mensagem ao remetente. |
452 4.2.2 | A franquia de recebimento da equipe acabou (veja preços), ou a caixa recebeu mais e-mails do que pode numa hora (200 mensagens numa caixa de agente, 2.000 numa caixa de pessoas). | Guarda a mensagem e tenta de novo mais tarde. |
Outros 4xx, como 451 4.3.0 | Um problema temporário do lado do MillionSend, ou mais destinatários do que uma entrega aceita (50). | Guarda a mensagem e tenta de novo, por dias se precisar. |
Configuração
Domínios de recebimento apontam o registro MX para mx.millionsend-dns.com.
1. Escolha um subdomínio
Quem envia entrega no registro MX com o menor número de prioridade do domínio
do destinatário, então o MX de recebimento assume todos os endereços do nome
em que for publicado. Publique-o num nome que ainda não recebe e-mail, como
inbound.example.com: suas caixas em example.com continuam no seu provedor
atual. Só receba num domínio raiz quando nada mais recebe e-mail lá.
2. Adicione e verifique
O recebimento pertence a um nome de domínio exato, e só a um domínio que a
sua equipe verificou. Para receber em inbound.example.com, adicione o próprio
inbound.example.com em Domínios (ou com POST /domains) e verifique-o
com os registros DKIM e MAIL FROM dele, como no
envio. Verificar example.com não
cobre os subdomínios. Depois de verificado, o subdomínio também pode enviar,
então as respostas podem sair dos mesmos endereços.
3. Ative o recebimento
Abra o domínio e ligue Ativar recebimento, ou use a API:
curl -X PATCH "https://api.millionsend.com/domains/{id}" \
-H "Authorization: Bearer ms_..." \
-H "Content-Type: application/json" \
-d '{ "capabilities": { "receiving": "enabled" } }'Toda resposta de domínio informa o estado, por exemplo { "sending": "enabled", "receiving": "enabled" }. Um nome de domínio recebe em uma equipe
só: um nome em que outra equipe já recebe é recusado com 409.
4. Publique o registro MX
Os registros do domínio ganham uma linha de recebimento, junto da opção
Ativar recebimento na página do domínio (record: "Receiving" na API).
Adicione-a no seu provedor de DNS:
| Tipo | Nome | Valor | Prioridade |
|---|---|---|---|
| MX | inbound.example.com | mx.millionsend-dns.com | 10 |
A linha fica verificada quando o DNS público lista mx.millionsend-dns.com
entre os registros MX do nome com o menor número de prioridade. O número em
si é só uma sugestão; o que importa é que nenhum outro registro MX desse nome
tenha um número menor. A checagem é feita ao vivo e nunca afeta o status de
envio do domínio. Na auto-hospedagem, o valor é o RECEIVING_MX_HOST da sua
instância.
5. Escolha quais endereços recebem
Crie uma caixa de entrada para cada endereço que deve receber, ou ligue o Pega-tudo na página do domínio para receber em todos os endereços (veja Quais endereços recebem). Sem nenhum dos dois, o domínio recusa todos os e-mails.
6. Faça um teste
De qualquer caixa de e-mail, mande uma mensagem para um desses endereços,
como hello@inbound.example.com. Ela aparece em Caixas de entrada → Todos
os recebidos em segundos, e todo endpoint de webhook inscrito em
email.received recebe uma entrega.
Para parar de receber, desligue o recebimento ("receiving": "disabled").
E-mails novos passam a ser recusados em até um minuto; o que já chegou fica
até a retenção apagar. Remova também o registro MX.
Quais endereços recebem
Um domínio de recebimento recebe e-mails:
- no endereço de cada caixa de entrada dele, e
nas variações com
+tag:orders+4821@chega à caixa deorders@; - com o pega-tudo ligado, em todos os outros endereços também.
support@,invoices@,reply+ticket-4821@: qualquer parte local funciona, sem nada para criar antes; decida no seu código o destino de cada mensagem pelo endereço em que ela chegou.
Com o pega-tudo desligado, qualquer outro endereço é recusado durante a
conversa SMTP com 550 5.1.1 No such recipient here, então o servidor de
quem envia devolve a mensagem ao remetente e nada é guardado. O e-mail para
uma caixa aparece nas conversas dela e em Todos os recebidos; o e-mail
para um endereço do pega-tudo aparece só em Todos os recebidos.
Donos e admins ligam o pega-tudo na página do domínio, ou com
PATCH /domains/{id} e { "receiving_catch_all": true }; as respostas de
domínio trazem receiving_catch_all. Ele começa desligado, e foi ligado em
todo domínio que já recebia e-mail antes de as caixas existirem. No
MillionSend Cloud ele exige um plano pago (o Free responde
403 plan_limit_reached); depois de ligado, continua ligado mesmo depois de
um downgrade.
received_forlista os endereços dos seus domínios para os quais o servidor de quem envia de fato entregou (os destinatários do envelope SMTP), incluindo quem estava em Cco.toeccsão o que os cabeçalhos da mensagem dizem e podem citar qualquer pessoa, então usereceived_forpara decidir o destino.- Uma mensagem é guardada uma vez por equipe. Enviada para três endereços seus,
ela vira um e-mail recebido com os três em
received_for, uma entrega de webhook e uma mensagem contada. Uma nova tentativa do servidor de quem envia também é reconhecida e guardada uma vez só. Quando a mesma mensagem chega de novo para outros endereços seus (o servidor de quem envia divide os destinatários em várias entregas, por exemplo passando de 50), eles entram emreceived_for, e chega mais umemail.receivedcom o mesmoemail_idsó com eles. - Só o nome exato recebe: e-mail para
x@eu.inbound.example.comé recusado, a não ser que esse subdomínio também receba. - Quando uma mensagem chega aos domínios de recebimento de duas equipes, cada equipe ganha a própria cópia, só com os próprios destinatários.
Limites
| Limite | Valor |
|---|---|
| Tamanho da mensagem | 40 MB (41.943.040 bytes) para a mensagem inteira como foi enviada: cabeçalhos, texto, HTML e anexos codificados para e-mail. A codificação base64 deixa os anexos cerca de um terço maiores, então cabem uns 30 MB de arquivos. Uma mensagem maior é recusada com 552 5.3.4 enquanto ainda está chegando. |
| Retenção | 30 dias na nuvem. Na auto-hospedagem, o conteúdo segue a retenção de e-mails da instância (Configurações → Instância, 30 dias por padrão), e remetente, destinatários e assunto seguem EMAIL_METADATA_RETENTION_DAYS (30 por padrão). |
| Filtro | E-mail infectado fica retido. Fora isso, o e-mail num endereço do pega-tudo é guardado do jeito que chegou: confira authentication, screening e spam_verdict antes de confiar num remetente. As caixas de entrada somam as próprias regras. |
Quando a retenção do conteúdo termina, html, text, headers e raw
passam a vir null, attachments fica vazio e os links de download param de
funcionar; remetente, destinatários e assunto ficam até a própria linha ser
apagada.
Preços
O e-mail recebido conta uma vez por mensagem por equipe, não importa para quantos endereços seus ela foi enviada, num contador de uso próprio, ao lado dos seus envios. Quanto custa depende do plano:
| Plano | Recebimento grátis | Depois disso |
|---|---|---|
| Free | Divide a cota diária de envio de 100 | Adiado com 452 4.2.2 até a meia-noite UTC |
| Starter | 3.000 por dia UTC (o dobro da cota diária de 1.500), contados à parte dos envios | Adiado com 452 4.2.2 até a meia-noite UTC |
| Pro, Scale | O dobro do volume mensal do plano por período de cobrança (200.000 no Pro 100K) | Cada e-mail recebido conta como um décimo de e-mail no volume e no excedente |
- Free: e-mails recebidos e envios enchem a mesma contagem diária, com a mesma tolerância de 50% dos envios, então e-mails novos são adiados quando os dois juntos chegam a 150 num dia UTC. Essa contagem é dividida entre todas as equipes Free que você criou. Ou seja, o recebimento pode gastar o dia: envios além da cota esperam até a meia-noite UTC como quaisquer outros, e o recebimento também conta para os avisos de cota.
- Pro e Scale: depois da franquia grátis, cada décimo e-mail recebido soma
um e-mail à contagem do período de cobrança, então mais 1.000 e-mails
recebidos contam como 100 e-mails: dentro do volume incluído eles o
consomem, além dele são cobrados pela taxa de excedente do seu plano.
Depois da franquia, o e-mail recebido é adiado com
452 4.2.2quando a contagem do período chega a 5 vezes o volume incluído com o excedente ligado, ou ao volume incluído com o excedente desligado ou pausado por um pagamento pendente. - Um adiamento é temporário: o servidor de quem envia guarda a mensagem e tenta de novo, normalmente por vários dias, então ela chega assim que houver espaço.
Configurações → Uso mostra os e-mails recebidos e a franquia grátis. Uma instância auto-hospedada conta os e-mails recebidos e nunca os limita. As caixas de entrada em si são grátis.
Lendo e-mails recebidos
Use um SDK do MillionSend a partir da 0.9.0
(emails.receiving), o SDK oficial do Resend apontado para o MillionSend
(RESEND_BASE_URL) ou HTTP direto. Todo endpoint abaixo exige uma chave de
acesso total; uma chave de somente envio recebe
403 restricted_api_key. Uma chave restrita a um domínio só lê os e-mails
recebidos nesse domínio, e uma chave restrita a uma caixa só os e-mails
entregues nela.
import { Resend } from "resend";
// RESEND_API_KEY=ms_... RESEND_BASE_URL=https://api.millionsend.com
const resend = new Resend(process.env.RESEND_API_KEY);
const { data: page } = await resend.emails.receiving.list({ limit: 20 });
const { data: email } = await resend.emails.receiving.get(page.data[0].id);
const { data: files } = await resend.emails.receiving.attachments.list({ emailId: email.id });Listar
GET /emails/receiving lista do mais novo para o mais antigo, como o
Resend: after avança para e-mails mais antigos, before volta para os mais
novos. Aceita limit (1–100, padrão 20; o Resend devolve todos quando falta
o limit) e um cursor after ou before, como toda
listagem, além destes filtros:
| Parâmetro | Lista |
|---|---|
inbox_id | Os e-mails entregues nessa caixa. Uma caixa que a chave não alcança responde 404, sem esperar o wait; uma chave restrita a uma caixa que pede outra recebe 403 restricted_api_key. |
to | Os e-mails com esse endereço em received_for. |
from | Os e-mails desse endereço, ou de um domínio e dos subdomínios dele. |
subject_contains | Os e-mails cujo assunto contém o texto (até 200 caracteres). |
since | Os e-mails recebidos depois desse momento (ISO 8601). |
unread | true ou false, junto com inbox_id (uma chave restrita a uma caixa não precisa dele). |
wait | Veja Esperar por e-mails novos. |
include_quarantined=true | Os retidos também. |
quarantined=true | Só os retidos. |
curl "https://api.millionsend.com/emails/receiving?limit=20" \
-H "Authorization: Bearer ms_..."{
"object": "list",
"has_more": false,
"data": [
{
"id": "4ef9a417-02e9-4d39-ad75-9611e0fcc33c",
"to": ["support@inbound.example.com"],
"from": "ada@example.org",
"created_at": "2026-10-11T14:37:40.951Z",
"subject": "Order #1042",
"bcc": [],
"cc": [],
"reply_to": [],
"received_for": ["support@inbound.example.com"],
"message_id": "<CAF1x7Qm9@mail.example.org>",
"attachments": [
{
"id": "b344102e-962e-8943-aef6-271c7743e1dd",
"filename": "invoice.pdf",
"content_type": "application/pdf",
"content_id": null,
"content_disposition": "attachment",
"size": 48213
}
],
"inbox_id": null,
"thread_id": null,
"inboxes": [],
"screening": { "verdict": "clean", "sender_trust": "external" },
"spam_verdict": "pass",
"virus_verdict": "pass",
"extracted": { "kinds": [] }
}
]
}A listagem mostra os e-mails de endereços do pega-tudo e os entregues numa caixa; os retidos ficam de fora, a não ser que você peça. Os itens trazem os campos do MillionSend depois dos do Resend:
inbox_idethread_id: a caixa em que a mensagem foi entregue (com uma chave restrita a uma caixa, a dela), senãonull.inboxeslista todas as caixas a que ela chegou, cominbox_id,thread_ideverdict, nas leituras com acesso total.screening:verdictesender_trust(veja Segurança de agentes).spam_verdict,virus_verdict: veja Spam, vírus e confiança.extracted.kinds:codeelinkquando a mensagem traz um código de verificação ou um link de acesso; os valores em si só aparecem em Ler um.read, quando a leitura é sobre uma caixa (inbox_id, ou uma chave restrita a uma caixa).
include_quarantined e quarantined pedem uma chave de acesso total que não
esteja restrita a uma caixa; uma chave restrita, e o servidor MCP, recebem
403 restricted_api_key.
Esperar por e-mails novos
O wait (de 1 a 50 segundos) segura a requisição até chegar um e-mail que
bata com os filtros, e aí responde na hora; no fim do prazo, responde uma
lista vazia. Ele funciona junto com os filtros acima, então um agente pode
esperar a próxima mensagem para uma caixa, de um remetente:
curl "https://api.millionsend.com/emails/receiving?inbox_id=7eeb9517-aed7-40d7-ad65-500be42ed147&from=example.org&wait=30" \
-H "Authorization: Bearer ms_..."- Ele devolve e-mails mais novos que o
before, o cursor desta listagem em direção aos mais novos, ou mais novos que osince. Sem nenhum dos dois, contam os últimos 60 segundos, então uma mensagem que chegou logo antes da chamada não se perde. - Se houver mais e-mails do que o
limit, ele devolve os mais novos, até olimit, comhas_more: true. Para ler todos, liste sem owait: passe o mesmobeforee, depois, o primeiro id de cada página enquanto ohas_morefortrue. - A resposta traz também
held: as mensagens que bateram e ficaram retidas desde então, como{ id, inbox_id, reason, quarantine_reason, created_at }e nada mais, para o agente saber que deve parar de esperar e avisar uma pessoa. Para uma chave restrita a uma caixa ou um cliente MCP, osubject_containsnão filtra oheld: um e-mail retido nunca é comparado pelo que ele diz. - Quando o prazo acaba, a resposta é
200com{ "object": "list", "has_more": false, "data": [], "held": [] }. - Uma equipe segura 20 esperas ao mesmo tempo em cada processo da API, e
todas as equipes juntas, 200; mais uma responde
429 too_many_waitscomretry-after: 1.
50 segundos fica abaixo dos limites de 60 segundos dos clientes MCP e de
proxies comuns, como o proxy_read_timeout padrão do nginx.
Ler um
GET /emails/receiving/{id} acrescenta o conteúdo, os resultados de
autenticação e um link de download da mensagem original:
{
"object": "email",
"id": "4ef9a417-02e9-4d39-ad75-9611e0fcc33c",
"to": ["support@inbound.example.com"],
"from": "ada@example.org",
"created_at": "2026-10-11T14:37:40.951Z",
"subject": "Order #1042",
"html": "<p>Hi! The invoice is attached.</p>",
"html_format": "data_uri",
"text": "Hi! The invoice is attached.",
"headers": {
"from": "Ada Lovelace <ada@example.org>",
"to": "support@inbound.example.com",
"subject": "Order #1042",
"mime-version": "1.0"
},
"bcc": [],
"cc": [],
"reply_to": [],
"received_for": ["support@inbound.example.com"],
"authentication": { "spf": "pass", "dkim": "pass", "dmarc": "pass" },
"message_id": "<CAF1x7Qm9@mail.example.org>",
"raw": {
"download_url": "https://api.millionsend.com/receiving/raw/4ef9a417-02e9-4d39-ad75-9611e0fcc33c?expires=1791733061&signature=…",
"expires_at": "2026-10-11T15:37:41.000Z"
},
"attachments": [
{
"id": "b344102e-962e-8943-aef6-271c7743e1dd",
"filename": "invoice.pdf",
"content_type": "application/pdf",
"content_id": null,
"content_disposition": "attachment",
"size": 48213
}
],
"inbox_id": null,
"thread_id": null,
"inboxes": [],
"screening": {
"verdict": "clean",
"sender_trust": "external",
"quarantine_reason": null,
"reasons": [],
"injection_score": null,
"phishing_score": null,
"hidden_text_removed": false
},
"spam_verdict": "pass",
"spam_score": 0,
"virus_verdict": "pass",
"virus_signature": null,
"extracted_text": "Hi! The invoice is attached.",
"extracted": {
"kinds": [],
"code": null,
"link": null,
"link_domain_matches_sender": null,
"ambiguous": false
}
}html_format:data_uri, o padrão, troca as referênciascid:de imagem do HTML pelas próprias imagens inline.?html_format=cidmantém as referências; relacione-as aocontent_iddos anexos. Qualquer outro valor dá422. Quando colocar as imagens no HTML passaria de 40 MB (em geral uma conversa longa que repete a mesma imagem muitas vezes), as referências ficam ehtml_formatvemcid, seja qual for o pedido, como o Resend faz a partir de 100 MB: confira ohtml_formatem vez de contar com ele.fromé só o endereço; o nome de exibição fica emheaders.from.headerstraz os cabeçalhos de nível superior com nomes em minúsculas, um valor por nome; um cabeçalho repetido, comoreceived, tem os valores unidos por quebras de linha. Quando a mensagem não trazReturn-Path,return-pathmostra o remetente do envelope que o servidor de quem envia informou,<>para um bounce.htmloutextvemnullquando a mensagem não tem essa parte. Uma mensagem cujo MIME não dá para interpretar ainda é guardada e listada; o que não dá para ler dela vemnull(headerstambém, quando nenhum cabeçalho é reconhecido), e orawtraz a mensagem inteira.- O
htmlvem exatamente como chegou. Otextvem sem caracteres invisíveis (de largura zero, de direção do texto, tags Unicode), com as quebras de linha mantidas. message_idvem do cabeçalhoMessage-IDda mensagem. Quando ela não tem um, o MillionSend cria<id@received.invalid>.extracted_texté a parte da resposta da mensagem, sem o texto que uma pessoa não vê, com o histórico citado e as assinaturas separados (veja Segurança de agentes).extractedtraz ocodede verificação ou olinkde acesso da mensagem (comlink_domain_matches_sender), ouambiguous: truequando dois são igualmente prováveis. Eles nunca saem de e-mail retido nem de um remetente que falhou na autenticação, e toda leitura de um deles fica registrada na atividade da caixa.
O e-mail retido responde 403 email_quarantined ("This email is
quarantined; a person can release it in the dashboard") para chaves
restritas a uma caixa e clientes MCP, e o e-mail ainda em análise responde
404 para eles.
authentication informa SPF, DKIM e DMARC com as palavras do Resend:
| Valor | Significa | Resultados da checagem |
|---|---|---|
pass | A checagem passou. | pass |
fail | A checagem falhou. | fail |
gray | Sem resposta clara: não havia registro ou assinatura para checar, ou o resultado foi neutro. | none, neutral, policy, softfail |
processing_failed | A checagem não terminou, por exemplo por um erro de DNS ou um registro quebrado. | temperror, permerror |
unknown | Não foi checado. |
Como no Resend, o DKIM só passa com uma assinatura do domínio do from (ou
de outro domínio da mesma organização): uma assinatura válida de qualquer
outro domínio vem gray, e policy no painel. O DMARC vem gray quando o
domínio do from publica p=none e o SPF ou o DKIM passou, none no
painel.
dmarc: "pass" quer dizer que o domínio do from autorizou a mensagem.
Qualquer outro valor quer dizer que o from pode ser falso, mas gray
também aparece em e-mail legítimo de um domínio que pede para o DMARC não ser
aplicado.
O MX também guarda os detalhes por trás dessas palavras: o resultado do DMARC antes de ser resumido, a política que o domínio do remetente publica, os domínios cujas assinaturas DKIM estavam alinhadas e o domínio que o SPF checou. A API mantém as palavras do Resend; o painel usa os detalhes para explicar cada resultado cinza, e o nível de confiança no remetente é calculado a partir deles:
| Resultado cinza | O que quer dizer |
|---|---|
| DMARC, a mensagem passou | Passou no DMARC, mas o domínio do remetente usa p=none, então os servidores não são orientados a bloquear e-mails que falham. |
| DMARC, a mensagem falhou | Falhou no DMARC, e o domínio do remetente usa p=none, que não pede para bloquear. |
| DMARC, sem registro | O domínio do remetente não tem política DMARC. |
DKIM policy | Assinatura válida de outro domínio, não do domínio do remetente, então não prova quem escreveu. |
SPF softfail | O servidor de envio não está na lista do domínio do remetente, que só pede uma falha leve. |
SPF neutral ou none | O domínio do remetente não diz quais servidores podem enviar por ele. |
processing_failed quer dizer que não deu para verificar: o DNS demorou ou o
registro está malformado.
Spam, vírus e confiança
Cada mensagem traz mais três resultados:
spam_verdict:pass,grayoufail, a partir dospam_score, uma nota local montada com a autenticação, a saudação do servidor de envio, cabeçalhos que faltam, um nome de exibição que mostra outro endereço, um Reply-To de outra organização, texto oculto, encurtadores de link e links com endereço IP, links cujo texto cita outro domínio, e anexos de programas ou scripts. De 50 para cima é reprovado, de 25 a 49 é cinza. Nenhuma lista de bloqueio externa é consultada. Numa caixa, o e-mail reprovado vai para a pastaspam; num endereço do pega-tudo, ele só é informado.virus_verdict:pass,fail(comvirus_signature, o malware encontrado),processing_failed(o antivírus não terminou; a mensagem é entregue, com um aviso) ounull(a instância não verifica). O e-mail infectado fica retido: numa caixa ele vai para a quarentena, e num endereço do pega-tudo sai da listagem e não disparaemail.receivedaté uma pessoa liberá-lo no painel. Orawdele vemnull, os downloads respondem410 email_blocked, e o encaminhamento pelo servidor o recusa, mesmo depois de liberado.screening.sender_trust: o quanto o remetente está comprovado, deowneratéfailed; veja Segurança de agentes.
As mensagens recebidas antes de esses resultados existirem vêm com null.
Anexos
GET /emails/receiving/{email_id}/attachments lista todos os anexos de um
e-mail de uma vez, como o Resend (passe limit para paginar), e
GET /emails/receiving/{email_id}/attachments/{id} devolve um deles, cada um
com um link de download novo:
{
"object": "attachment",
"id": "b344102e-962e-8943-aef6-271c7743e1dd",
"filename": "invoice.pdf",
"size": 48213,
"content_type": "application/pdf",
"content_disposition": "attachment",
"download_url": "https://api.millionsend.com/receiving/attachments/4ef9a417-02e9-4d39-ad75-9611e0fcc33c/b344102e-962e-8943-aef6-271c7743e1dd?expires=1791733061&signature=…",
"expires_at": "2026-10-11T15:37:41.000Z"
}filename e content_id ficam de fora quando a parte não tem. Os ids de
anexo nunca mudam enquanto o e-mail existir. Os nomes de arquivo são limpos
antes de chegar a você: caracteres de controle são removidos, e / e \
viram _.
Downloads
raw.download_url e o download_url de cada anexo funcionam sem chave de
API: o próprio link é a credencial.
- Um link é assinado para um e-mail e um anexo (ou a mensagem original) de uma
equipe, e para de funcionar no seu
expires_at, uma hora depois da resposta da API; depois disso, ou se for alterado, responde403. Quem tiver o link consegue baixar até lá, então não o registre em log nem o repasse. Cada chamada aos endpoints acima assina links novos. - O download do
rawé a mensagem exatamente como o servidor de quem envia a transmitiu (message/rfc822), byte a byte. O download de um anexo traz os bytes decodificados dele, sempre comoapplication/octet-stream; o tipo que o remetente declarou fica emcontent_type. - Downloads sempre são servidos como arquivo (
Content-Disposition: attachment), nunca exibidos numa aba do navegador. - Uma mensagem com vírus responde
410 email_blocked("This email carries malware; downloads are blocked") antes de qualquer coisa ser descriptografada.
Encaminhar e responder
resend.emails.receiving.forward() funciona como no Resend: lê o e-mail,
baixa o raw.download_url e envia a mensagem de novo por POST /emails.
await resend.emails.receiving.forward({
emailId: "4ef9a417-02e9-4d39-ad75-9611e0fcc33c",
from: "Support <support@inbound.example.com>",
to: "success@simulator.amazonses.com",
});Por padrão o encaminhamento leva o assunto, o texto, o HTML, as imagens
inline e os anexos originais; com passthrough: false e o seu próprio text
ou html, o original vai anexado como forwarded_message.eml, com assunto
Fwd:. Um encaminhamento é um envio comum: o from precisa ser de um
domínio verificado, e ele conta na sua cota de envio. POST /emails aceita
imagens inline (content_id), então o encaminhamento padrão mantém as
imagens. Mas um envio leva no máximo 10 MiB de anexos (no Resend, 40 MB): o
modo padrão funciona quando os anexos do original cabem em 10 MiB, e o
passthrough: false, que anexa a mensagem inteira, quando a própria mensagem
cabe. Um encaminhamento maior é recusado com 422 antes de entrar na fila.
Para responder na mesma conversa, envie com In-Reply-To e References
iguais ao message_id recebido:
await resend.emails.send({
from: "Support <support@inbound.example.com>",
to: email.from,
subject: `Re: ${email.subject}`,
text: "Thanks, we're on it.",
headers: { "In-Reply-To": email.message_id, References: email.message_id },
});Responder e encaminhar pelo servidor
POST /emails/receiving/{id}/reply e POST /emails/receiving/{id}/forward
fazem isso numa chamada só, com os cabeçalhos da conversa já preenchidos:
curl -X POST "https://api.millionsend.com/emails/receiving/4ef9a417-02e9-4d39-ad75-9611e0fcc33c/reply" \
-H "Authorization: Bearer ms_..." \
-H "Content-Type: application/json" \
-H "Idempotency-Key: order-1042-reply" \
-d '{ "text": "Thanks, we are on it." }'- Responder aceita
textouhtml,subject,cc,bccereply_all. Vai para oReply-Toda mensagem, ou então para o remetente; oreply_allacrescenta os outros destinatários comocc, e obccnunca é copiado. - Encaminhar aceita
to(obrigatório),cc,bcc, um recado emtextouhtml,subjectemode:inline, o padrão, cita o original abaixo de uma linha---------- Forwarded message ---------com os anexos dele;attachmentanexa a mensagem inteira comoforwarded_message.eml. Os dois contam nos 10 MiB de anexos que um envio leva. - O
fromé qualquer endereço de um domínio verificado da sua equipe; por padrão, o endereço da caixa a que a mensagem chegou, senão o primeiro endereço dereceived_for. Oinbox_idescolhe entre as caixas a que a mensagem chegou. requires_approval: truesegura o envio para uma pessoa.
Eles respondem 200 com { "object": "email", "id", "thread_id", "inbox_id" };
202 com um rascunho quando as regras da caixa retêm o envio; 403 para
e-mail retido ou infectado (email_quarantined), para as regras da caixa
(inbox_send_policy) ou para uma chave restrita fora da própria caixa
(restricted_api_key); 404; 409 para um Idempotency-Key reaproveitado;
422; e 429 inbox_send_cap_reached. O e-mail de um endereço do pega-tudo é
enviado como qualquer envio: nenhuma regra de caixa vale, a não ser que o
from seja o endereço de uma caixa. Veja
Caixas de entrada → Responder e encaminhar.
Excluir e-mails recebidos
DELETE /emails/receiving/{id} apaga um e-mail recebido agora, em vez de no
fim da retenção: a mensagem, os anexos e o lugar dela em caixas e conversas
(uma conversa que fica vazia vai junto). Responde
{ "object": "email", "id": "…", "deleted": true }. Exige uma chave de
acesso total que não esteja restrita a uma caixa, e no painel um dono ou
admin (Excluir agora). As entregas de webhook já feitas mantêm a cópia só
com metadados até a retenção do próprio log de entregas.
Webhook
email.received dispara uma vez para cada mensagem guardada para a sua
equipe, nos endpoints inscritos nele ou em todos os eventos, assim que a
mensagem fica visível: na hora para um endereço do pega-tudo, e na entrega
para uma caixa. O e-mail que uma caixa retém, na quarentena ou durante a
análise, e o e-mail infectado só disparam depois de entregues ou liberados,
mesmo quando uma cópia também foi para um endereço do pega-tudo.
Como o do Resend, ele só traz metadados: busque o conteúdo com
GET /emails/receiving/{email_id}. Quando uma entrega posterior da mesma
mensagem chega a mais endereços seus, chega mais um email.received com o
mesmo email_id, e o received_for dele só lista os endereços novos, para
cada endereço ser avisado uma vez só.
{
"type": "email.received",
"created_at": "2026-10-11T14:37:40.951Z",
"data": {
"email_id": "4ef9a417-02e9-4d39-ad75-9611e0fcc33c",
"created_at": "2026-10-11T14:37:40.951Z",
"from": "ada@example.org",
"to": ["support@inbound.example.com"],
"bcc": [],
"cc": [],
"received_for": ["support@inbound.example.com"],
"message_id": "<CAF1x7Qm9@mail.example.org>",
"subject": "Order #1042",
"attachments": [
{
"id": "b344102e-962e-8943-aef6-271c7743e1dd",
"filename": "invoice.pdf",
"content_type": "application/pdf",
"content_disposition": "attachment",
"content_id": null
}
]
}
}Um endpoint limitado a algumas caixas (inbox_ids) só recebe o
email.received dos e-mails entregues numa delas. Assinaturas, novas
tentativas e o log de entregas funcionam como em qualquer outro evento; veja
Webhooks.
Painel
Caixas de entrada → Todos os recebidos lista tudo o que os seus domínios receberam, com remetente, caixa, assunto e horário, uma indicação quando o e-mail traz um código ou um link, e um selo quando está em quarentena ou é spam; filtre por caixa (ou só pega-tudo) e por resultado. Ao abrir uma mensagem, o HTML aparece isolado, com scripts e imagens remotas bloqueados e imagens inline exibidas, junto com a versão em texto, os cabeçalhos e a mensagem original; os resultados de autenticação, cada cinza explicado; a confiança no remetente, os resultados de spam e de vírus e se saiu texto oculto; o código ou link extraído, com um botão de copiar; uma linha do tempo da chegada até a entrega, a liberação, a resposta ou o encaminhamento; e as ações Responder, Encaminhar, Liberar para e-mails retidos e Excluir agora para donos e admins. Links antigos para E-mails → Recebidos levam para lá.
Numa instância auto-hospedada, Configurações → Recebimento mostra para quem opera o host MX, a última mensagem recebida, o total do dia, o antivírus e o domínio compartilhado das caixas.
MCP
O servidor MCP lê e-mails recebidos sob a
permissão receiving:read: list_received_emails, get_received_email,
list_received_email_attachments, get_received_email_attachment,
wait_for_received_email e get_verification_code, junto com as leituras
de caixas. O get_received_email devolve por padrão o texto limpo da
resposta (format: "extracted"), e text, html ou raw quando você
pede. Responder e encaminhar pedem receiving:reply, e caixas e quarentena,
receiving:manage. O update_domain liga e desliga o recebimento e o
pega-tudo. Autorizações feitas antes de uma permissão existir não a incluem:
entre de novo pelo cliente para concedê-la.
Trate e-mails recebidos como não confiáveis
Qualquer pessoa pode mandar e-mail para um domínio de recebimento. O HTML pode
trazer scripts e imagens de rastreamento, links podem levar a páginas de
phishing, anexos podem trazer malware e o from pode ser falso;
authentication e screening.sender_trust dizem até onde confiar. Um agente
de IA que lê e-mails recebidos deve tratá-los como dados, nunca como
instruções: as ferramentas MCP os marcam assim, e uma
caixa de agente soma quarentena, análise e
regras de envio.
Domínios
Verifique domínios de envio com DNS guiado, BYODKIM e configuração por domínio.
Caixas de entrada
Endereços que guardam os e-mails em conversas e respondem pelo mesmo endereço, para um agente de IA ou para pessoas, com rascunhos que esperam aprovação, quarentena e análise, por uma API compatível com o Resend. Beta.