Merge pull request !2844 from rhodecode-enterprise-ce feature/RCCE-252_Implement-smtp-server-for-dev-env-to-test-email-notifications

feature: implements sending emails to a local store for local development
This commit is contained in:
Andrii Verbytskyi 2025-10-22 12:13:22 +00:00
commit c1115e792e
2 changed files with 22 additions and 4 deletions

View file

@ -12,6 +12,12 @@ debug = true
; These settings will be used by the RhodeCode mailing system
; ########################################################################
; redirect emails to a local file instead of sending them to the actual server
development_email = true
; folder where emails will be saved locally
local_email_store = ./local_emails
; prefix all emails subjects with given prefix, helps filtering out emails
#email_prefix = [RhodeCode]

View file

@ -28,6 +28,7 @@ from typing import Any
from celery import current_app
from pyramid_mailer.mailer import Mailer
from pyramid_mailer.mailer import DebugMailer
from pyramid_mailer.message import Message
from email.utils import formatdate
@ -77,7 +78,9 @@ def send_email(recipients, subject, body="", html_body="", email_config=None, ex
email_config = email_config or rhodecode.CONFIG
mail_server = email_config.get("smtp_server") or None
if mail_server is None:
dev_mod = str2bool(email_config.get("development_email"))
if mail_server is None and not dev_mod:
log.error(
"SMTP server information missing. Sending email failed. "
"Make sure that `smtp_server` variable is configured "
@ -104,7 +107,7 @@ def send_email(recipients, subject, body="", html_body="", email_config=None, ex
recipients += admins
# translate our LEGACY config into the one that pyramid_mailer supports
email_conf = dict(
transformed_email_confing = dict(
host=mail_server,
port=email_config.get("smtp_port", 25),
username=email_config.get("smtp_username", None),
@ -135,11 +138,11 @@ def send_email(recipients, subject, body="", html_body="", email_config=None, ex
extra_headers["References"] = " ".join("<{}>".format(t) for t in thread_ids)
try:
mailer = Mailer(**email_conf)
mailer = _get_mailer(transformed_email_confing, email_config)
message = Message(
subject=subject,
sender=email_conf["default_sender"],
sender=transformed_email_confing["default_sender"],
recipients=recipients,
body=body,
html=html_body,
@ -156,6 +159,15 @@ def send_email(recipients, subject, body="", html_body="", email_config=None, ex
return True
def _get_mailer(transformed_email_conf: dict[str, Any], original_email_conf: dict[str, Any]) -> Mailer | DebugMailer:
dev_mode = str2bool(original_email_conf.get("development_email"))
if dev_mode:
emails_path = original_email_conf.get("local_email_store") or "./local_emails"
return DebugMailer(emails_path)
return Mailer(**transformed_email_conf)
@async_task(ignore_result=True, base=RequestContextTask)
def create_repo(form_data, cur_user):
from rhodecode.model.repo import RepoModel