#!/usr/bin/env python3 from __future__ import annotations from html import escape import socket from flask import current_app from flask_mail import Message from extensions import mail def _mail_send_suppressed() -> bool: state = current_app.extensions.get("mail") return bool(getattr(state, "suppress", False)) def _send_message(msg: Message) -> None: if not _mail_send_suppressed() and not current_app.config.get("MAIL_SERVER"): raise RuntimeError("Mail server is not configured.") previous_timeout = socket.getdefaulttimeout() socket.setdefaulttimeout(float(current_app.config.get("MAIL_TIMEOUT", 5))) try: mail.send(msg) finally: socket.setdefaulttimeout(previous_timeout) def _html_email(title: str, intro: str, cta_label: str | None = None, cta_url: str | None = None, code: str | None = None, note: str | None = None) -> str: app_url = current_app.config.get("APP_BASE_URL", "https://myboker.org").rstrip("/") cta_html = "" if cta_label and cta_url: cta_html = f""" {escape(cta_label)} If the button does not work, copy and paste this link:
{escape(cta_url)} """ code_html = "" if code: code_html = f"""
{escape(code)}
""" note_html = "" if note: note_html = f""" {escape(note)} """ return f"""
{code_html} {cta_html} {note_html}
myboker.org

{escape(title)}

{escape(intro)}
This email was sent by myboker.org. If you did not request this, you can safely ignore it.
""" def send_password_reset(to_email: str, reset_url: str) -> None: body = ( f"You requested a password reset for your myboker.org account.\n\n" f"Reset your password:\n\n" f"{reset_url}\n\n" f"This link expires in 1 hour. If you did not request this, you can ignore this email." ) msg = Message( subject="Reset your myboker.org password", recipients=[to_email], body=body, html=_html_email( "Reset your password", "We received a request to reset the password for your myboker.org account.", cta_label="Reset password", cta_url=reset_url, note="This link expires in 1 hour.", ), sender=current_app.config.get("MAIL_DEFAULT_SENDER"), ) _send_message(msg) def send_email_verification_code(to_email: str, code: str) -> None: body = ( "Verify your myboker.org account with this code:\n\n" f"{code}\n\n" "This code expires in 15 minutes. If you did not create an account, you can ignore this email." ) msg = Message( subject="Your myboker.org verification code", recipients=[to_email], body=body, html=_html_email( "Verify your email", "Enter this verification code to finish creating your myboker.org account.", code=code, note="This code expires in 15 minutes. Do not share it with anyone.", ), sender=current_app.config.get("MAIL_DEFAULT_SENDER"), ) _send_message(msg) def send_league_invite(to_email: str, league_name: str, invite_url: str, invited_by_email: str, role: str) -> None: role_label = role.strip().lower() if role else "member" body = ( f"{invited_by_email} has invited you to join {league_name} as a {role_label} on myboker.org.\n\n" f"Accept your invitation:\n\n" f"{invite_url}\n\n" f"This link expires in 7 days. You'll need a myboker.org account with this email address to accept." ) msg = Message( subject=f"You've been invited to join {league_name} on myboker.org", recipients=[to_email], body=body, html=_html_email( "You have a league invite", f"{invited_by_email} invited you to join {league_name} as a {role_label}.", cta_label="Accept invite", cta_url=invite_url, note="This invitation link expires in 7 days.", ), sender=current_app.config.get("MAIL_DEFAULT_SENDER"), ) _send_message(msg)