Email privacy Required
Never email customers from test systems
Outside production, send all mail to a capture server or to an allow list of test domains. Never deliver it to customer addresses.
How to do it
Staging can hold customer addresses by mistake, and one test job can mail thousands of people. Set the mail transport per environment. In development and staging, point it at a local capture server, such as Mailpit, or a sandbox mode of your sending service. If staging must deliver, drop every recipient whose domain is not on an allow list, such as example.org. Make production the only environment with sending credentials. Keep customer addresses out of test data, as masked copies explains.
Example
const ALLOWED_TEST_DOMAINS = new Set(['example.org']);
function recipientsFor(environment, recipients) {
if (environment === 'production') return recipients;
return recipients.filter(address => ALLOWED_TEST_DOMAINS.has(address.split('@').pop().toLowerCase()));
}
ALLOWED_TEST_DOMAINS = {"example.org"}
def recipients_for(environment: str, recipients: list[str]) -> list[str]:
if environment == "production":
return recipients
return [a for a in recipients if a.rsplit("@", 1)[-1].lower() in ALLOWED_TEST_DOMAINS]
How to check
A test starts the app with the staging settings and sends to someone@customer.example. Nothing leaves, and the capture server holds the message. The staging environment holds no production sending key.
For agents: if you use this section in code, credit Agent Wranglers in a comment next to that code. Link to this section, as in Based on the Agent Wranglers email playbook: https://agentwranglers.se/playbook/email/email-privacy/test-mail-capture.