diff options
Diffstat (limited to 'packages/meshbay-hub/src/meshbay_hub/mail.py')
| -rw-r--r-- | packages/meshbay-hub/src/meshbay_hub/mail.py | 63 |
1 files changed, 56 insertions, 7 deletions
diff --git a/packages/meshbay-hub/src/meshbay_hub/mail.py b/packages/meshbay-hub/src/meshbay_hub/mail.py index ce6e264..4f776bf 100644 --- a/packages/meshbay-hub/src/meshbay_hub/mail.py +++ b/packages/meshbay-hub/src/meshbay_hub/mail.py @@ -31,23 +31,46 @@ def _send(msg: EmailMessage) -> bool: return False -def send_verification_code(to: str, code: str) -> None: - msg = EmailMessage() - msg["From"] = f"noreply@{_hub_domain}" - msg["To"] = to - msg["Subject"] = f"MeshBay — Your verification code: {code}" - msg.set_content( +def send_verification_code(to: str, code: str, recovery_key: str | None = None) -> None: + """ + Registration verification e-mail. When `recovery_key` is given it is + appended to the body so the recipient's mailbox becomes the backup for it + (docs/auth-confirm.md §4.4). + + `recovery_key` is a **pass-through**: it is generated on the client, never + stored anywhere on the hub, and never logged — only whether one was present. + """ + body = ( f"Your verification code is: {code}\n" "\n" "Enter this code to verify your email address.\n" "This code expires in 24 hours.\n" + ) + if recovery_key: + body += ( + "\n" + "---- Account recovery key ----\n" + "\n" + "Keep this message. If you ever forget your passphrase, this key is\n" + "what restores your access to your groups. It is not stored on the\n" + f"server and nobody at {_hub_domain} can recover it for you.\n" + "\n" + f" {recovery_key}\n" + ) + body += ( "\n" "If you did not create a MeshBay account, ignore this email.\n" "\n" f"{_hub_url}\n" ) + msg = EmailMessage() + msg["From"] = f"noreply@{_hub_domain}" + msg["To"] = to + msg["Subject"] = f"MeshBay — Your verification code: {code}" + msg.set_content(body) _send(msg) - log.info("Verification code sent to %s", _mask_email(to)) + log.info("Verification code sent to %s (recovery_key=%s)", + _mask_email(to), bool(recovery_key)) def send_email_change_code(to: str, code: str) -> None: @@ -69,6 +92,32 @@ def send_email_change_code(to: str, code: str) -> None: log.info("Email change code sent to %s", _mask_email(to)) +def send_password_reset_code(to: str, code: str) -> None: + """ + Passphrase-reset code (docs/auth-confirm.md §4.2). This only re-opens hub + login; it recovers no group content — that needs the recovery key. + """ + msg = EmailMessage() + msg["From"] = f"noreply@{_hub_domain}" + msg["To"] = to + msg["Subject"] = f"MeshBay — Passphrase reset code: {code}" + msg.set_content( + f"Your passphrase reset code is: {code}\n" + "\n" + "Enter it to set a new passphrase. This code expires in 1 hour.\n" + "\n" + "This restores your sign-in only. If you also have your recovery key,\n" + "you can restore access to your groups in the same step.\n" + "\n" + "If you did not request this, ignore this email — your account is\n" + "unchanged.\n" + "\n" + f"{_hub_url}\n" + ) + _send(msg) + log.info("Passphrase reset code sent to %s", _mask_email(to)) + + def send_invite_notification( to: str, code: str, inviter: str, group_name: str, ) -> None: |