Skip to main content

Módulo Notification (e-mail) — visão geral

Não existe um módulo NestJS único chamado "Notification". O que existe é uma infraestrutura de envio de e-mail compartilhada (shared/module/email) — um contrato genérico de "enviar uma mensagem" com duas implementações (SMTP e SES) — que cada domínio do backend usa à sua própria maneira, com seu próprio conteúdo e sua própria rota (quando há uma). Esta seção reúne a infraestrutura compartilhada e a única capacidade de envio de e-mail deste levantamento que tem rota HTTP própria: o envio de laudo por e-mail, no domínio de diagnóstico.

Sobre o legado. Os cards de negócio do funil de Notification (Bitrix, ex.: F-S02, F-S03) descrevem o sistema antigo (mm-pacs-portal-api/core/services/emailServiceOld.js): envio via Mailgun, templates HTML por idioma resolvidos pelo país da empresa, registro em tb_fila_email, data de nascimento do paciente na URL do link de entrega, nome do paciente no assunto. Nenhum desses cards tinha o campo de correspondência "status vs código real" preenchido — trate-os como especificação de legado, não como verdade do código atual. O código atual (branch integration/with-fixlaudo) é uma reescrita bem mais simples: sem Mailgun, sem template por país/idioma, sem fila de e-mail própria (o outbox existente é o de auditoria, não de e-mail) e sem data de nascimento na URL. O envio de laudo por e-mail manteve, do legado, apenas o comportamento de sempre incluir o e-mail do paciente como destinatário (ver Enviar laudo por e-mail, RN-01).

Infraestrutura compartilhada (shared/module/email)​

EmailModule (@Global(), registrado via forRoot() em cada app) expõe um único provider para o token MailSender, escolhido em runtime pelo transport da config (EmailTransport.SMTP ou EmailTransport.SES, default SES). O código de domínio nunca depende de SMTP ou SES diretamente — só do contrato abstrato:

ts
export abstract class MailSender {
abstract send(message: EmailMessage): Promise<void>;
}

EmailMessage é o único formato de mensagem aceito. Campos: to (string única — não existe cc, bcc nem attachments), subject (obrigatório, até 255 caracteres, sem quebra de linha), e text ou html (pelo menos um dos dois, cada um entre 1 e 1.000.000 de caracteres). Um destinatário por EmailMessage; enviar para vários endereços é sempre um laço no código chamador, um send() por destinatário — não há envio em lote nativo.

Envio é síncrono, sem fila e (quase) sem retry​

Diferente do módulo de auditoria, não há fila/outbox para e-mail. Cada mailSender.send(...) é uma chamada síncrona, feita inline dentro do caso de uso que está processando a requisição HTTP. Se o provedor falhar, SmtpMailSender e SesMailSender capturam o erro, logam e relançam como InfrastructureError (errorCode: EMAIL_DELIVERY_UNAVAILABLE, HTTP 503). O único retry existente é o retry interno do SDK da AWS para SES, configurável via EMAIL_MAX_ATTEMPTS (default 3); o transporte SMTP não tem nenhum retry — falhou, propagou o erro.

Não há verificação de "e-mail já enviado" em nenhum dos consumidores conhecidos: repetir a mesma chamada reenvia o e-mail.

Consumidores conhecidos​

DomínioUsoConteúdo/templateDocumentado em
identityConvite de acesso, e-mail concedido a admin de organização, verificação de e-mail, redefinição de senha, confirmação de e-mail de recuperação, aviso de senha alteradaIdentityEmailTemplateCatalog + MobilemedEmailRenderer (HTML com logo, botão de ação, nota de expiração, PT-BR/EN/ES) — exclusivo do identity, instanciado como classe simples (new IdentityEmailTemplateCatalog()), fora do DI do NestSenha, Convites — a concessão de acesso de admin (accessGranted, em provision-identity-tenant-root-access.service.ts) não tem página própria localizada neste levantamento; A confirmar — responsável: time de Identity; data: 24/09/2026.
diagnosis/reportEnvio do laudo/imagens do exame por e-mailHTML inline simples, fixo em português, sem i18n, montado no próprio serviçoEnviar laudo por e-mail (rota HTTP própria)

IdentityEmailTemplateCatalog, apesar de estar fisicamente em package/identity/shared/email, não é usado fora do identity — o diagnóstico monta seu próprio HTML e não passa pelo catálogo nem pelo MobilemedEmailRenderer. Não foi encontrado nenhum outro domínio que envie e-mail neste levantamento.

Variáveis de ambiente da infraestrutura de e-mail​

Cada app (identity, diagnosis, audit...) resolve essas variáveis no seu próprio escopo — os valores podem ser diferentes por app.

VariávelUsoDefault
EMAIL_TRANSPORTsmtp ou ses — escolhe a implementação de MailSenderses
EMAIL_FROMRemetente (from) usado em ambos os transportes— (obrigatório)
EMAIL_SMTP_HOST / EMAIL_SMTP_PORT / EMAIL_SMTP_SECUREConexão SMTP—
EMAIL_SMTP_USERNAME / EMAIL_SMTP_PASSWORDAutenticação SMTP (devem vir juntas)—
EMAIL_SMTP_CONNECTION_TIMEOUT_MSTimeout de conexão SMTP—
EMAIL_REGION (ou AWS_REGION)Região do SES—
EMAIL_ACCESS_KEY_ID / EMAIL_SECRET_ACCESS_KEY (ou AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY)Credenciais do SES (devem vir juntas)—
EMAIL_ENDPOINTEndpoint alternativo do SES (ex.: para teste local)—
EMAIL_MAX_ATTEMPTSTentativas internas do SDK da AWS para SES3

Limitações confirmadas no código atual​

  • Sem cc, bcc ou anexos em nenhum ponto do fluxo — inclusive o e-mail de laudo envia apenas links (imagens e laudo), nunca o PDF/HTML anexado.
  • Sem fila/outbox própria de e-mail; o outbox existente no repositório é o de auditoria (DiagnosisAuditOutboxRecorder), usado para registrar o evento de que um e-mail foi disparado, não para desacoplar o envio em si.
  • Sem idempotência: nada impede reenviar o mesmo e-mail várias vezes.

Páginas deste módulo​

PáginaCobre
Enviar laudo por e-mailPOST /exams/:id/report-emails e POST /exams/report-emails — único envio de e-mail deste levantamento com rota HTTP própria

Os demais consumidores de e-mail (identity) já têm suas rotas documentadas nos módulos Authentication e Usuário; esta página de visão geral existe para explicar a infraestrutura que todos eles compartilham, não para duplicar aquele conteúdo.