feat: staging_mode that logs email instead of sending it#152
Conversation
When staging_mode = true, finalize logs a [STAGING] line containing recipients, sender, sender_attributes, expiry, download URL, and uuid instead of contacting SMTP. Returns Ok so the upload flow completes. Refs encryption4all/postguard#174.
There was a problem hiding this comment.
Self-review
This agent opened this PR, so GitHub blocks a formal APPROVE from this account. Posting a review-style comment instead — final approval needs to come from @rubenhensen.
The change is small, scoped, defaults safe (staging_mode = false), has direct test coverage, and CI is fully green (fmt/clippy/tests + Docker amd64/arm64). Ready for human review and, in this agent's read, ready to merge.
What looks good
- Single short-circuit at the top of
send_email; SMTP path is untouched, so production behavior is bit-identical when the flag is off. - New field is
Option<bool>inRawCryptifyConfigwith.unwrap_or(false)— existingconfig.tomlfiles keep working without changes. CryptifyConfig::for_testis gated on#[cfg(test)], so it can't leak into prod builds.- Test asserts the structural bits an operator would grep for (
[STAGING]prefix, recipient addresses, sender, attributes, uuid, download URL). - Log line uses
log::info!and returns the same summary string, so it surfaces in both container logs and the finalize response.
Minor (non-blocking) observations
- Recipient-level fidelity. The real flow sends one email per recipient (with a per-recipient
recipient=query param on the download URL) plus an optional sender confirmation. The staging log collapses that into a single line with all recipients and a download URL that carries onlyuuid=. Fine for "did the flow fire", but a small loop emitting one[STAGING]line per recipient (mirroring the SMTP loop) would be a more faithful reproduction if a future debug session needs per-recipient URLs. Not required now. notify_recipients=false/confirm=false. In real mode with both off, zero emails are sent. The staging summary still prints recipients/sender. Thenotify_recipients=…andconfirm=…fields in the summary disambiguate it — flagging just so it's intentional.mail_contentis omitted. Probably correct (size/PII), but worth a one-line comment so a future reader doesn't think it's an oversight.
None of those block merge. Once merged, set staging_mode = true in the staging config.toml and restart the cryptify container (per the bind-mount restart convention); finalize calls will then emit [STAGING] Email NOT sent ... lines as designed.
|
Rule compliance pass: updated the PR body to use |
There was a problem hiding this comment.
Re-review (cycle 0 of pipeline). GitHub blocks a formal APPROVE because this agent is the PR author — posting as a review comment, but the verdict is ready to merge pending @rubenhensen.
Reviewed the diff, ran cargo test locally (58 passing), and confirmed CI is green (fmt/clippy/test + Docker amd64/arm64).
What looks good:
- Short-circuit at the top of
send_emailis the right seam; SMTP path is untouched. staging_modedefaults tofalseviaOption<bool>::unwrap_or(false), so existing deployments are unaffected.CryptifyConfig::for_testis#[cfg(test)]-gated.- The test covers the structural fields an operator would grep (
[STAGING]prefix, both recipients, sender, attributes, uuid, parsed download URL). Url::parse(...).and_then(...).join(...)falls back to a labelled string instead of panicking on a malformedserver_url.
Non-blocking observations (already raised in the earlier self-review; recording here for the pipeline trace):
- Staging log collapses per-recipient sends into one line; faithful enough for a smoke check.
notify_recipients=false/confirm=falsewill still print the recipients/sender — the explicitnotify_recipients=/confirm=fields in the summary disambiguate.mail_contentis intentionally omitted (size/PII).
Ready to merge.
Adds a
staging_modeboolean toCryptifyConfig. When set,send_emailskips SMTP entirely and logs a single[STAGING] Email NOT sent ...line with the full intended recipients, sender, sender_attributes, expiry, download URL, and uuid. ReturnsOkso the upload finalize flow completes normally.Closes encryption4all/postguard#174
Changes
conf/config.dev.toml: documented (commented)staging_mode = trueoption.src/config.rs: newstaging_modefield, defaults tofalse. Test-only constructorCryptifyConfig::for_test.src/email.rs: short-circuit insend_emailplusstaging_log_emailhelper.staging_mode_skips_smtp_and_returns_summary(passes thestaging_mode_skips_smtp_and_returns_summaryhappy path; SMTP path is unchanged).How to enable in staging deploys
Add to the active config file (
conf/config.toml):Then tail the cryptify container logs after a finalize call:
Reviewer quickstart