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:
@@ -9,6 +9,7 @@ from gatehouse_app.schemas.auth_schema import RegisterSchema, LoginSchema
|
||||
from gatehouse_app.services.auth_service import AuthService
|
||||
from gatehouse_app.services.mfa_policy_service import MfaPolicyService
|
||||
from gatehouse_app.services.notification_service import NotificationService
|
||||
from gatehouse_app.services.email_templates import build_email_verification_html
|
||||
from gatehouse_app.utils.decorators import login_required
|
||||
from gatehouse_app.utils.constants import AuditAction
|
||||
from gatehouse_app.exceptions.auth_exceptions import InvalidCredentialsError
|
||||
@@ -32,14 +33,17 @@ def register():
|
||||
verify_token = EmailVerificationToken.generate(user_id=user.id)
|
||||
app_url = current_app.config.get("APP_URL", "http://localhost:8080")
|
||||
verify_link = f"{app_url}/verify-email?token={verify_token.token}"
|
||||
subject = "Verify your Secuird email address"
|
||||
body = (
|
||||
f"Hi {user.full_name or user.email},\n\n"
|
||||
f"Welcome to Secuird! Please verify your email address by clicking the link below (valid for 24 hours):\n"
|
||||
f"{verify_link}\n\n"
|
||||
f"Secuird Security Team"
|
||||
email_body = build_email_verification_html(
|
||||
user_name=user.full_name or user.email,
|
||||
verify_link=verify_link,
|
||||
expiry_hours=24,
|
||||
)
|
||||
NotificationService._send_email_async(
|
||||
to_address=user.email,
|
||||
subject="Verify your Secuird email address",
|
||||
body=f"Verify your Secuird email: {verify_link}",
|
||||
html_body=email_body,
|
||||
)
|
||||
NotificationService._send_email_async(to_address=user.email, subject=subject, body=body)
|
||||
except Exception as exc:
|
||||
logging.getLogger(__name__).warning(f"Failed to send verification email on register: {exc}")
|
||||
|
||||
|
||||
@@ -6,6 +6,11 @@ from gatehouse_app.extensions import limiter
|
||||
from gatehouse_app.utils.response import api_response
|
||||
from gatehouse_app.services.auth_service import AuthService
|
||||
from gatehouse_app.services.notification_service import NotificationService
|
||||
from gatehouse_app.services.email_templates import (
|
||||
build_password_reset_html,
|
||||
build_email_verification_html,
|
||||
build_account_activation_html,
|
||||
)
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -27,17 +32,16 @@ def forgot_password():
|
||||
reset_token = PasswordResetToken.generate(user_id=user.id)
|
||||
app_url = current_app.config.get("APP_URL", "http://localhost:8080")
|
||||
reset_link = f"{app_url}/reset-password?token={reset_token.token}"
|
||||
email_body = build_password_reset_html(
|
||||
user_name=user.full_name or user.email,
|
||||
reset_link=reset_link,
|
||||
expiry_hours=2,
|
||||
)
|
||||
NotificationService._send_email_async(
|
||||
to_address=user.email,
|
||||
subject="Reset your Secuird password",
|
||||
body=(
|
||||
f"Hi {user.full_name or user.email},\n\n"
|
||||
f"You requested a password reset for your Secuird account.\n\n"
|
||||
f"Click the link below to reset your password (valid for 2 hours):\n"
|
||||
f"{reset_link}\n\n"
|
||||
f"If you did not request this, you can safely ignore this email.\n\n"
|
||||
f"Secuird Security Team"
|
||||
),
|
||||
body=f"Reset your Secuird password: {reset_link}",
|
||||
html_body=email_body,
|
||||
)
|
||||
_logger.info(f"Password reset token generated for user {user.id}")
|
||||
except Exception as exc:
|
||||
@@ -129,15 +133,16 @@ def resend_verification():
|
||||
verify_token = EmailVerificationToken.generate(user_id=user.id)
|
||||
app_url = current_app.config.get("APP_URL", "http://localhost:8080")
|
||||
verify_link = f"{app_url}/verify-email?token={verify_token.token}"
|
||||
email_body = build_email_verification_html(
|
||||
user_name=user.full_name or user.email,
|
||||
verify_link=verify_link,
|
||||
expiry_hours=24,
|
||||
)
|
||||
NotificationService._send_email_async(
|
||||
to_address=user.email,
|
||||
subject="Verify your Secuird email address",
|
||||
body=(
|
||||
f"Hi {user.full_name or user.email},\n\n"
|
||||
f"Please verify your email address by clicking the link below (valid for 24 hours):\n"
|
||||
f"{verify_link}\n\n"
|
||||
f"Secuird Security Team"
|
||||
),
|
||||
body=f"Verify your Secuird email: {verify_link}",
|
||||
html_body=email_body,
|
||||
)
|
||||
_logger.info(f"Verification email sent for user {user.id}")
|
||||
except Exception as exc:
|
||||
@@ -200,16 +205,15 @@ def resend_activation():
|
||||
|
||||
app_url = current_app.config.get("APP_URL", current_app.config.get("FRONTEND_URL", "http://localhost:8080"))
|
||||
activate_link = f"{app_url}/activate?code={code}"
|
||||
email_body = build_account_activation_html(
|
||||
user_name=user.full_name or user.email,
|
||||
activation_link=activate_link,
|
||||
)
|
||||
NotificationService._send_email_async(
|
||||
to_address=user.email,
|
||||
subject="Activate your Secuird account",
|
||||
body=(
|
||||
f"Hi {user.full_name or user.email},\n\n"
|
||||
f"Please activate your Secuird account by clicking the link below:\n"
|
||||
f"{activate_link}\n\n"
|
||||
f"If you did not create an account, you can safely ignore this email.\n\n"
|
||||
f"Secuird Security Team"
|
||||
),
|
||||
body=f"Activate your Secuird account: {activate_link}",
|
||||
html_body=email_body,
|
||||
)
|
||||
_logger.info(f"Activation email re-sent to {user.id}")
|
||||
except Exception as exc:
|
||||
|
||||
Reference in New Issue
Block a user