feat(email): use HTML templates for all transactional emails

- Update org invite, password reset, email verification, and account activation emails to use HTML templates
- Update MFA deadline reminder and suspension notifications to use HTML templates
- Add html_body parameter to _send_email_async for rich email content
This commit is contained in:
2026-04-05 15:44:22 +00:00
parent f2386ed1da
commit 6325d60097
5 changed files with 127 additions and 50 deletions
+12 -6
View File
@@ -7,6 +7,7 @@ from gatehouse_app.utils.decorators import login_required, require_admin
from gatehouse_app.services.notification_service import NotificationService
from gatehouse_app.services.auth_service import AuthService
from gatehouse_app.services.organization_service import OrganizationService
from gatehouse_app.services.email_templates import build_org_invite_html
from gatehouse_app.utils.constants import OrganizationRole
@@ -37,15 +38,20 @@ def create_org_invite(org_id):
app_url = current_app.config.get("APP_URL", "http://localhost:8080")
invite_link = f"{app_url}/invite?token={invite.token}"
inviter_name = g.current_user.full_name or g.current_user.email
email_body = build_org_invite_html(
inviter_name=inviter_name,
org_name=org.name,
invite_link=invite_link,
role=role,
expiry_days=7,
)
NotificationService._send_email_async(
to_address=email,
subject=f"You're invited to join {org.name} on Secuird",
body=(
f"You've been invited to join {org.name} on Secuird.\n\n"
f"Click the link below to accept the invitation (valid for 7 days):\n"
f"{invite_link}\n\n"
f"Secuird Security Team"
),
body=f"You've been invited to join {org.name} on Secuird. Open this link in your browser: {invite_link}",
html_body=email_body,
)
logging.getLogger(__name__).info(f"[INVITE] Email queued for {email}")
email_sent = True # async — assume queued successfully
+13 -8
View File
@@ -1,5 +1,5 @@
"""Organization member management endpoints."""
from flask import g, request
from flask import g, request, current_app
from marshmallow import ValidationError
from gatehouse_app.api.v1 import api_v1_bp
from gatehouse_app.utils.response import api_response
@@ -7,6 +7,7 @@ from gatehouse_app.utils.decorators import login_required, require_admin, full_a
from gatehouse_app.schemas.organization_schema import InviteMemberSchema, UpdateMemberRoleSchema
from gatehouse_app.services.organization_service import OrganizationService
from gatehouse_app.services.user_service import UserService
from gatehouse_app.services.email_templates import build_mfa_setup_reminder_html
from gatehouse_app.utils.constants import OrganizationRole
@@ -161,16 +162,20 @@ def send_mfa_reminder(org_id, user_id):
if compliance and policy and compliance.deadline_at:
NotificationService.send_mfa_deadline_reminder(user, compliance, policy)
else:
app_url = current_app.config.get("APP_URL", "http://localhost:8080")
setup_link = f"{app_url}/settings/security"
html_body = f'''
<h2>Reminder: Set up multi-factor authentication</h2>
<p>Hi {user.full_name or user.email},</p>
<p>Your organization administrator has asked you to set up multi-factor authentication (MFA) on your Secuird account.</p>
<p>Please log in and configure MFA as soon as possible.</p>
<p><a href="{setup_link}">Set up MFA now</a></p>
'''
NotificationService._send_email_async(
to_address=user.email,
subject="Reminder: Set up multi-factor authentication",
body=(
f"Hi {user.full_name or user.email},\n\n"
"Your organization administrator has asked you to set up "
"multi-factor authentication (MFA) on your Secuird account.\n\n"
"Please log in and configure MFA as soon as possible.\n\n"
"Secuird Security Team"
),
body=f"Set up MFA on Secuird: {setup_link}",
html_body=html_body,
)
return api_response(data={}, message="Reminder sent successfully")