Pular para o conteúdo principal

Inbox

Uma Inbox é um endereço de e-mail roteável com uma política de processamento. Cada inbox pertence a um workspace e pode associar um único agente para processamento automatizado.

Propósito​

  • Prover um endereço único para um caso de uso (triagem de suporte, intake de faturas, revisão de contratos, etc.).
  • Definir filtros que decidem se um e-mail de entrada é approved ou rejected.
  • Controlar política de anexos (quantidade, tamanho por arquivo, tamanho total).
  • Opcionalmente rotear todo e-mail aprovado para um Agent para processamento por LLM.

Importante: provisionamento só no banco​

Criar uma inbox não chama a AWS. O SES inbound trabalha por domínio — com a Domain Identity verificada e o MX apontado, todo endereço *@inbox.{env}.kobana.com.br chega ao SES independente de existir no banco. O registro de inbox é o que torna o endereço roteável adiante; sem ele o e-mail é descartado em process-email com rejection_reason=recipient_unknown.

Schema​

CampoTipoDescrição
idUUIDID interno.
external_idUUIDID estável do sistema de origem. Unique.
workspace_idUUIDWorkspace dono.
agent_idUUID | nullAgent opcional para e-mails aprovados.
labelstringLabel humano.
emailstringO endereço roteável. Globalmente único.
statusenumactive ou inactive.
allowed_recipientsstring[]Quando não-vazio, somente e-mails cujo to contém um destes endereços são aprovados. Wildcards (*@acme.com) suportados.
filtersJSONArray de regras de filtro (veja abaixo).
attachments_allowboolSe anexos são permitidos.
attachments_max_file_numberintMáx de anexos por e-mail. Default 10.
attachments_max_file_sizeintBytes. Default 10485760 (10 MiB).
attachments_max_total_sizeintBytes. Default 41943040 (40 MiB).
attachments_allow_rulesarray|nullLista de anexos permitidos. null processa todos os anexos. Ver Regras de anexos permitidos.
custom_metadataobjectFree-form.
metadataobjectControlado pelo sistema.
created_at / updated_at / deleted_atdatetime

Filtros​

O campo filters é um array JSON. Cada elemento é uma regra como:

{ "field": "from", "op": "matches", "value": "^.*@acme\\.com$" }
fieldopvalue
from, subject, header.<name>equals, contains, matches (regex)string
headers.list-idpresent, absent(sem value)
body.textcontainsstring

Regras são AND'd. Se qualquer regra falhar, o e-mail é rejeitado com rejection_reason=filters.

Regras de anexos permitidos​

attachments_allow_rules decide quais anexos de um e-mail são processados. Cada regra pode ter:

ChaveTipoSignificado
extensionsstring[]Extensões sem o ponto, sem diferenciar maiúsculas: ["pdf", "xml"].
filename_patternstringExpressão regular JavaScript testada contra o nome do arquivo, até 200 caracteres: ^GUIA_. Quantificadores aninhados são recusados.
case_sensitiveboolVale para filename_pattern. Padrão false.

Uma regra precisa de extensions, filename_pattern ou dos dois; dentro de uma regra, todas as chaves informadas precisam ser atendidas. Um anexo é processado quando atende a qualquer regra. Até 20 regras.

[{ "extensions": ["pdf"], "filename_pattern": "^GUIA_" }]

processa só os PDFs cujo nome começa com GUIA_ (sem diferenciar maiúsculas).

Um anexo fora da lista é ignorado, nunca um motivo para rejeitar o e-mail:

  • o agente não o vê — os outros anexos mantêm o número (Anexo 1, Anexo 3);
  • os attachments_max_* contam só os anexos que passaram;
  • um passo de workflow que o referencia (${{email.attachments.N}}) falha antes de qualquer requisição;
  • o e-mail registra o anexo em metadata.ignoredAttachments, como { "index": N, "reason": "not_allowed" } (a partir de 0, o N de ${{email.attachments.N}}). Um reprocessamento refaz a lista com as regras atuais; quando rejeita o e-mail, a chave é removida.

Um anexo sem nome (o logo inline de uma assinatura, por exemplo) nunca atende a uma regra. Quando nenhum anexo passa, o agente roda mesmo assim sobre o corpo. null ou [] processa todos os anexos.

Exemplo​

{
"id": "b3c4d5e6-7a89-4b0c-9d1e-2f3a4b5c6d7e",
"external_id": "00000000-0000-0000-0000-00000000001a",
"workspace_id": "a8b2c1d4-9e7f-4a3b-8c5d-1f2e3a4b5c6d",
"agent_id": "c4d5e6f7-8a9b-4c0d-9e1f-2a3b4c5d6e7f",
"label": "Suporte — Triagem",
"email": "triage-3f4a@inbox.kobana.com.br",
"status": "active",
"allowed_recipients": ["support@acme.com"],
"filters": [{ "field": "from", "op": "matches", "value": ".*@(acme|partner)\\.com$" }],
"attachments_allow": true,
"attachments_max_file_number": 10,
"attachments_max_file_size": 10485760,
"attachments_max_total_size": 41943040,
"attachments_allow_rules": null,
"custom_metadata": { "team": "support" },
"metadata": {},
"created_at": "2026-01-04T12:00:00.000Z",
"updated_at": "2026-01-04T12:00:00.000Z",
"deleted_at": null
}

Ciclo de vida​

  • POST /inboxes — cria (sem efeitos na AWS).
  • PATCH /inboxes/{id} — atualiza label, filtros, destinatários permitidos, política de anexos, agente associado.
  • DELETE /inboxes/{id} — soft-delete. E-mails futuros para o endereço são rejeitados com recipient_unknown.

Setar status: "inactive" mantém a linha mas rejeita novos e-mails com recipient_unknown — útil para suspensões temporárias onde você pretende reativar.