feat(email): add provider abstraction and HTML templates

Add pluggable email provider system supporting SMTP, Mailgun, and SendGrid
with factory pattern for runtime provider selection. Includes branded HTML
email templates for verification, password reset, MFA notifications, and
organization invites.

Also rebrands all email content from Gatehouse to Secuird, adds email
provider configuration options, and fixes duplicate log handlers in
development mode.
This commit is contained in:
2026-04-04 16:55:00 +10:30
parent d90a06437e
commit 41bbdb4bef
17 changed files with 1068 additions and 76 deletions
+7 -1
View File
@@ -191,6 +191,8 @@ def setup_logging(app):
root_logger.setLevel(log_level)
if app.config.get("LOG_TO_STDOUT"):
# Clear existing handlers on root logger to avoid duplicates
root_logger.handlers.clear()
stream_handler = logging.StreamHandler()
stream_handler.setFormatter(formatter)
stream_handler.setLevel(log_level)
@@ -207,7 +209,8 @@ def setup_logging(app):
child_logger.propagate = True
child_logger.setLevel(log_level)
# Configure Flask app logger
# Configure Flask app logger - clear handlers so it only propagates to root
app.logger.handlers.clear()
app.logger.setLevel(log_level)
# Configure SQLAlchemy logging level (also set at module level before DB init)
@@ -217,6 +220,9 @@ def setup_logging(app):
logging.getLogger('sqlalchemy.dialects').setLevel(sqlalchemy_log_level)
logging.getLogger('sqlalchemy.pool').setLevel(sqlalchemy_log_level)
# Suppress watchdog debug logging
logging.getLogger('watchdog.observers.inotify_buffer').setLevel(logging.INFO)
app.logger.info("Application startup")
# Test debug log after logging is configured