Skip to content

feat(mail): mise en place de MailDev et envoi des accusés de réception (#3177)#3231

Merged
Viczei merged 16 commits intoalphafrom
feat/issue-3177-maildev-setup
Apr 16, 2026
Merged

feat(mail): mise en place de MailDev et envoi des accusés de réception (#3177)#3231
Viczei merged 16 commits intoalphafrom
feat/issue-3177-maildev-setup

Conversation

@Viczei
Copy link
Copy Markdown
Contributor

@Viczei Viczei commented Apr 14, 2026

Summary

  • Ajoute un service MailDev en local (docker-compose.yml) et sur les environnements de dev Kontinuous (Deployment + Service dans .kontinuous/env/dev/templates/maildev.yaml).
  • Introduit un module ~/modules/mail basé sur nodemailer avec 3 templates d'accusé de réception (déclaration, seconde déclaration, avis CSE) en texte + HTML multipart et PDF récapitulatifs en pièces jointes.
  • Branche l'envoi effectif sur les 3 flux de soumission (declaration.submit, declaration.submitSecondDeclaration, cseOpinion.saveOpinions) et les 3 boutons « Renvoyer l'accusé de réception » via une nouvelle mutation mail.resendReceipt.
  • MAIL_ENABLED=false par défaut sur preprod et prod (no-op silencieux) tant qu'un vrai fournisseur SMTP n'est pas choisi — MailDev reste cantonné à dev.
  • Nouvelles actions d'audit MAIL_RECEIPT_SEND / MAIL_RECEIPT_RESEND (catégorie mutation, 365 jours).

Closes #3177

Test plan

  • docker compose up maildev → UI accessible sur http://localhost:1080
  • Soumettre une déclaration en local → mail reçu dans MailDev avec les deux PDF récapitulatifs attachés
  • Soumettre un avis CSE → mail reçu (sans PJ)
  • Cliquer « Renvoyer l'accusé de réception » sur chacune des 3 bannières → nouveau mail reçu
  • Déployer une review-app → MailDev déployé dans le namespace, accusé reçu
  • Vérifier audit.action_log : MAIL_RECEIPT_SEND (initial) + MAIL_RECEIPT_RESEND (resend)
  • Vérifier qu'en preprod/prod MAIL_ENABLED=false => aucun SMTP ouvert, sendMail renvoie {status: "disabled"}

Viczei added 4 commits April 14, 2026 16:50
MailDev listens on SMTP port 1025 and exposes a web UI on 1080, using
the MAILDEV_* env vars already declared in .env.
Deploys a MailDev Deployment + Service on dev namespaces so review apps
can send SMTP mail to a catcher. On preprod and prod the mail configmap
sets MAIL_ENABLED=false until a real SMTP provider is provisioned.
…t templates

Introduces a `~/modules/mail` module built on nodemailer. `sendMail`
is a no-op when MAIL_ENABLED is false so preprod and prod are safe
until a real SMTP provider is wired. `sendReceipt` orchestrates the
three receipt flavours (declaration, second declaration, CSE opinion),
attaches the récapitulatif PDFs when relevant, and self-audits every
send via the existing audit log. Adds MAIL_RECEIPT_SEND and
MAIL_RECEIPT_RESEND audit actions.
Wires the existing 'accusé de réception' banners to the new mail
module:
- declaration.submit / submitSecondDeclaration / cseOpinion.saveOpinions
  send the matching receipt template (with récapitulatif PDFs attached
  for declarations).
- New mail.resendReceipt tRPC mutation powers the Renvoyer buttons on
  all three banners via a shared ResendReceiptButton client component.
- mail.resendReceipt is audited as MAIL_RECEIPT_RESEND; initial sends
  piggyback on the existing submit audit rows plus a dedicated
  MAIL_RECEIPT_SEND log line emitted from sendReceipt.
@Viczei Viczei requested review from a team as code owners April 14, 2026 15:44
@revu-bot revu-bot Bot requested a review from revu-bot April 14, 2026 15:44
Copy link
Copy Markdown
Collaborator

@revu-bot revu-bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ PR Review Skipped

1 validation issue found. Review thresholds can be adjusted in .revu.yml.

See why it was skipped and detailed metrics

Issues Found

1. This PR changes 38 files, which exceeds the limit of 25 files.

Suggestion: Consider breaking this PR into smaller, more focused changes. Large PRs are harder to review effectively and may contain unrelated changes.

PR Metrics

  • Total files changed: 38
  • Reviewable files: 38
  • Diff size: 1276 lines
  • Documentation files: 0
  • Largest file change: 104 lines
  • Addition/Deletion ratio: 66.83

This validation helps ensure the bot focuses on PRs where automated review provides the most value.

@socket-security
Copy link
Copy Markdown

socket-security Bot commented Apr 14, 2026

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Addednext@​16.2.362100919770
Addedjsdom@​29.0.27510010096100
Addedexceljs@​4.4.09710010082100
Addednext-auth@​4.24.139810010086100

View full report

@Viczei Viczei marked this pull request as draft April 14, 2026 15:54
@Viczei Viczei temporarily deployed to build-review-auto April 14, 2026 16:01 — with GitHub Actions Inactive
Client components imported the mail barrel, which re-exported the
nodemailer transporter and pulled Node built-ins (stream, perf_hooks)
into the client bundle. Split into:
- ~/modules/mail (client-safe: button + schemas + types)
- ~/modules/mail/server (sendMail + sendReceipt, server-only)

Also dynamic-imports sendReceipt inside router handlers: the static
import went through buildPdfData, which lives in ~/modules/declarationPdf
and pulls ~/server/api/routers/declarationHelpers, creating a module
graph cycle that turbopack tripped over with a TDZ error on
createCaller.
@Viczei Viczei self-assigned this Apr 14, 2026
@Viczei Viczei temporarily deployed to build-review-auto April 16, 2026 09:12 — with GitHub Actions Inactive
Dev review apps route the ProConnect test account (test@fia1.fr) to a
shared yopmail inbox (fia1@yopmail.com) so the team can inspect
receipts without configuring individual SMTP destinations. The map is
an optional JSON env var, applied transparently in sendMail and
recorded in the audit log metadata.
Review apps get https://maildev-<namespace>.ovh.fabrique.social.gouv.fr
pointing at the maildev service port 1080 so the team can inspect
receipts directly in a browser without port-forwarding.
@Viczei Viczei temporarily deployed to build-review-auto April 16, 2026 10:02 — with GitHub Actions Inactive
readOnlyRootFilesystem=true prevented MailDev from creating its mail
spool directory, causing CrashLoopBackOff.
@Viczei Viczei temporarily deployed to build-review-auto April 16, 2026 11:57 — with GitHub Actions Inactive
Viczei added 2 commits April 16, 2026 13:58
…load

- Templates now return only { subject, html }. sendMail uses
  html-to-text to produce the plain-text alternative at send time,
  removing the duplication between the two representations.
- CSE opinion receipt is now triggered by a successful POST on
  /api/upload (flowType=cse_opinion) instead of cseOpinion.saveOpinions,
  so the acknowledgement matches the moment the document is actually
  deposited.
@Viczei Viczei marked this pull request as ready for review April 16, 2026 12:56
Copy link
Copy Markdown
Collaborator

@revu-bot revu-bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ PR Review Skipped

1 validation issue found. Review thresholds can be adjusted in .revu.yml.

See why it was skipped and detailed metrics

Issues Found

1. This PR changes 39 files, which exceeds the limit of 25 files.

Suggestion: Consider breaking this PR into smaller, more focused changes. Large PRs are harder to review effectively and may contain unrelated changes.

PR Metrics

  • Total files changed: 39
  • Reviewable files: 39
  • Diff size: 1518 lines
  • Documentation files: 0
  • Largest file change: 311 lines
  • Addition/Deletion ratio: 75.08

This validation helps ensure the bot focuses on PRs where automated review provides the most value.

@Viczei Viczei temporarily deployed to build-review-auto April 16, 2026 12:58 — with GitHub Actions Inactive
@socket-security
Copy link
Copy Markdown

socket-security Bot commented Apr 16, 2026

Warning

Review the following alerts detected in dependencies.

According to your organization's Security Policy, it is recommended to resolve "Warn" alerts. Learn more about Socket for GitHub.

Action Severity Alert  (click "▶" to expand/collapse)
Warn High
Obfuscated code: npm entities is 91.0% likely obfuscated

Confidence: 0.91

Location: Package overview

From: pnpm-lock.yamlnpm/entities@4.5.0

ℹ Read more on: This package | This alert | What is obfuscated code?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should not obfuscate their code. Consider not using packages with obfuscated code.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/entities@4.5.0. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

View full report

@Viczei Viczei requested a review from maxgfr April 16, 2026 15:06
@Viczei Viczei temporarily deployed to build-review-auto April 16, 2026 15:17 — with GitHub Actions Inactive
@Viczei Viczei enabled auto-merge (squash) April 16, 2026 15:25
@Viczei Viczei temporarily deployed to build-review-auto April 16, 2026 15:27 — with GitHub Actions Inactive
@Viczei Viczei disabled auto-merge April 16, 2026 16:14
@Viczei Viczei removed the request for review from maxgfr April 16, 2026 16:15
@Viczei Viczei enabled auto-merge (squash) April 16, 2026 16:15
Two changes targeted at the SonarCloud duplication threshold:

- `modules/admin/declarations/shared/DsfrTable.tsx` was a byte-identical
  copy of `modules/shared/DsfrTable.tsx`. Deleted the copy, pointed the
  three existing consumers (DetailSections, DeclarationTable, test file)
  at the shared module.
- `DeclarationTable` and `ReferentTable` both carried the same
  ~20-line sort / page-URL helper block. Extracted it into a new
  `useSortableTable` hook in `modules/shared`, with a companion unit
  test, so both tables consume the same code path.
@Viczei Viczei temporarily deployed to build-review-auto April 16, 2026 16:52 — with GitHub Actions Inactive
Both the admin and public referent search pages had near-identical
forms (same schema, same region/county cascade, same URL-state
handling). Consolidated them into `~/modules/referents/shared/
ReferentsSearchForm` parameterized by basePath, fieldPrefix, schema
and a few cosmetic flags. The two existing forms become thin wrappers.
@tokenbureau
Copy link
Copy Markdown

tokenbureau Bot commented Apr 16, 2026

@Viczei Viczei merged commit 672ac58 into alpha Apr 16, 2026
15 checks passed
@Viczei Viczei deleted the feat/issue-3177-maildev-setup branch April 16, 2026 17:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Mise en place de MailDev

3 participants