feat: add scheduler and mail outbox
SMTP adapter with TLS and a fake, outbox with retries, backoff, rate limit and restart safety, scheduler tick with job-run records started by gunicorn, and a send_test_mail command. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01N3t4WL7bd9bdHHNjEsxzqC
This commit is contained in:
@@ -140,3 +140,41 @@ def test_oidc_addresses_must_be_https_origins(valid_env, name, value):
|
||||
def test_a_plain_http_origin_is_allowed_only_in_debug(valid_env):
|
||||
env = {**valid_env, "PUBLIC_BASE_URL": "http://localhost:8000"}
|
||||
assert load_config({**env, "DEBUG": "true"}).oidc.public_base_url == "http://localhost:8000"
|
||||
|
||||
|
||||
def test_smtp_settings_default_to_starttls_on_587_and_hide_the_password(valid_env):
|
||||
smtp = load_config(valid_env).smtp
|
||||
assert (smtp.host, smtp.port, smtp.security) == ("mail.example.test", 587, "starttls")
|
||||
assert smtp.sender == "Portal <portal@example.test>"
|
||||
assert "mail-password" not in repr(smtp)
|
||||
|
||||
|
||||
def test_smtp_ssl_defaults_to_port_465_and_the_port_can_be_set(valid_env):
|
||||
assert load_config({**valid_env, "SMTP_SECURITY": "SSL"}).smtp.port == 465
|
||||
assert load_config({**valid_env, "SMTP_PORT": "2525"}).smtp.port == 2525
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("name", "value"),
|
||||
[
|
||||
("SMTP_HOST", "smtp://mail.example.test"),
|
||||
("SMTP_HOST", "mail.example.test:587"),
|
||||
("SMTP_SECURITY", "plain"),
|
||||
("SMTP_PORT", "abc"),
|
||||
("SMTP_PORT", "0"),
|
||||
("SMTP_PORT", "70000"),
|
||||
("MAIL_FROM", "not-an-address"),
|
||||
("MAIL_FROM", "a@b.test\r\nBcc: x@evil.test"),
|
||||
("MAIL_FROM", "@example.test"),
|
||||
],
|
||||
)
|
||||
def test_invalid_smtp_settings_are_refused(valid_env, name, value):
|
||||
with pytest.raises(ConfigError, match=name):
|
||||
load_config({**valid_env, name: value})
|
||||
|
||||
|
||||
@pytest.mark.parametrize("name", ["SMTP_HOST", "SMTP_USERNAME", "SMTP_PASSWORD", "MAIL_FROM"])
|
||||
def test_the_mail_settings_are_required(valid_env, name):
|
||||
del valid_env[name]
|
||||
with pytest.raises(ConfigError, match=name):
|
||||
load_config(valid_env)
|
||||
|
||||
Reference in New Issue
Block a user