feat(automation): add the Email REAction vertical (Run 4) - #116
Merged
Conversation
Send an email through an SMTP relay when an automation rule fires, closing VIGIL-SVC-023. The Team-scoped `email` connection stores five encrypted credentials (host, port, username, password, sender). `email_notify` decrypts them, interpolates the subject and body templates, and delivers through the existing durable run engine, so a failure is recorded on the connection like any other reaction. Implementation notes: - `EmailSender` takes `SmtpConfig` and `EmailMessage` rather than nine positional arguments; five consecutive `&str` were trivially swappable at a call site. - `validate_smtp` opens an authenticated session and issues NOOP without sending anything, so the catalogue's `testable: true` is now backed by a real probe instead of returning `InvalidServiceConnection`. - `configure_service` gained its `email` arm. The catalogue advertised the connection and the client generated its form, but the endpoint rejected every save, leaving the whole service unreachable. - A failed delivery records the actual error code; a malformed recipient was previously reported to the Manager as an SMTP outage. - `InvalidEmailSender` distinguishes a bad sender address from a bad recipient, both at configuration time and at delivery time. - `0BSD` joins the license allowlist: lettre pulls quoted_printable for MIME encoding, which cargo-deny rejected. Covered by a `DummyEmailSender` double: template interpolation, the five decrypted credentials, connection-service mismatch, recipient rejection, Manager-only configuration, incomplete credential sets, and the probe that must not send mail.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes the Email REAction vertical,
VIGIL-SVC-023.A Team-scoped
emailconnection stores five encrypted credentials (host, port, username, password, sender). When a rule fires,email_notifydecrypts them, interpolates the subject and body templates and delivers through the existing durable run engine, recording success or failure on the connection like any other reaction.What this fixes beyond the feature itself
Three defects made the service unusable or the pipeline red:
configure_servicehad noemailarm. The catalogue advertised the connection and the client generated its form, but every save returnedInvalidServiceConnection, so the connection could never be created.testable: truewas not backed by anything. The single/testroute only accepted thehttpservice, so the Test button always errored on an Email connection. It now runs a real SMTP probe (validate_smtp: authenticated session + NOOP, no message sent).email_transport_error, so a malformed recipient was reported to the Manager as an SMTP outage. It now records the actual code.CI was also red before this branch:
cargo clippyraisednew_without_defaultandtoo_many_arguments(9/7) on the new code, andcargo denyrejectedquoted_printable(0BSD), pulled by lettre for MIME encoding.Design notes
EmailSendertakesSmtpConfigandEmailMessageinstead of nine positional arguments. Five consecutive&strwere trivially swappable at a call site, which is what the clippy lint was pointing at.validate_smtpmirrorsNotifier::validate_endpoint, so configuration and execution share one boundary.InvalidEmailSenderseparates a bad sender address from a bad recipient, at configuration time and at delivery time.Coverage
A
DummyEmailSenderdouble covers template interpolation, the five decrypted credentials reaching the right fields, connection-service mismatch, recipient rejection, Manager-only configuration, incomplete credential sets, malformed port and sender, and that the probe never sends mail.Local verification:
cargo fmt,clippy -D warnings,cargo audit,cargo deny, 435 Rust tests, 86.80% source coverage (gate 70%), and the full web lint/format/typecheck/test/build suite all pass.Not included
One live delivery to a real mailbox is still outstanding;
VIGIL-SVC-023staysPARTIALuntil that proof exists.