mirror of https://github.com/zulip/zulip.git
send_email: Improve configurability for outgoing email sender name.
Currently, the sender names for outgoing emails sent by Zulip are hardcoded. It should be configurable for self-hosted systems. This commit makes the 'Zulip' part a variable in the following email sender names: 'Zulip Account Security', 'Zulip Digest', and 'Zulip Notifications' by introducing a settings variable 'SERVICE_NAME' with the default value as f"{EXTERNAL_HOST} Zulip". Fixes: #23857
This commit is contained in:
parent
44d8dc66d2
commit
d8cf12eaaa
|
@ -9,6 +9,7 @@ from django.conf import settings
|
||||||
from django.db import transaction
|
from django.db import transaction
|
||||||
from django.db.models import Exists, OuterRef
|
from django.db.models import Exists, OuterRef
|
||||||
from django.utils.timezone import now as timezone_now
|
from django.utils.timezone import now as timezone_now
|
||||||
|
from django.utils.translation import gettext as _
|
||||||
from typing_extensions import TypeAlias
|
from typing_extensions import TypeAlias
|
||||||
|
|
||||||
from confirmation.models import one_click_unsubscribe_link
|
from confirmation.models import one_click_unsubscribe_link
|
||||||
|
@ -408,7 +409,7 @@ def bulk_handle_digest_email(user_ids: List[int], cutoff: float) -> None:
|
||||||
"zerver/emails/digest",
|
"zerver/emails/digest",
|
||||||
user.realm,
|
user.realm,
|
||||||
to_user_ids=[user.id],
|
to_user_ids=[user.id],
|
||||||
from_name="Zulip Digest",
|
from_name=_("{service_name} digest").format(service_name=settings.INSTALLATION_NAME),
|
||||||
from_address=FromAddress.no_reply_placeholder,
|
from_address=FromAddress.no_reply_placeholder,
|
||||||
context=context,
|
context=context,
|
||||||
)
|
)
|
||||||
|
|
|
@ -574,7 +574,9 @@ def do_send_missedmessage_events_reply_in_zulip(
|
||||||
)
|
)
|
||||||
|
|
||||||
with override_language(user_profile.default_language):
|
with override_language(user_profile.default_language):
|
||||||
from_name: str = _("Zulip notifications")
|
from_name: str = _("{service_name} notifications").format(
|
||||||
|
service_name=settings.INSTALLATION_NAME
|
||||||
|
)
|
||||||
from_address = FromAddress.NOREPLY
|
from_address = FromAddress.NOREPLY
|
||||||
|
|
||||||
email_dict = {
|
email_dict = {
|
||||||
|
|
|
@ -70,7 +70,9 @@ class FromAddress:
|
||||||
language = user_profile.default_language
|
language = user_profile.default_language
|
||||||
|
|
||||||
with override_language(language):
|
with override_language(language):
|
||||||
return _("Zulip Account Security")
|
return _("{service_name} account security").format(
|
||||||
|
service_name=settings.INSTALLATION_NAME
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def build_email(
|
def build_email(
|
||||||
|
|
|
@ -194,7 +194,7 @@ class EmailChangeTestCase(ZulipTestCase):
|
||||||
self.assertEqual(self.email_envelope_from(email_message), settings.NOREPLY_EMAIL_ADDRESS)
|
self.assertEqual(self.email_envelope_from(email_message), settings.NOREPLY_EMAIL_ADDRESS)
|
||||||
self.assertRegex(
|
self.assertRegex(
|
||||||
self.email_display_from(email_message),
|
self.email_display_from(email_message),
|
||||||
rf"^Zulip Account Security <{self.TOKENIZED_NOREPLY_REGEX}>\Z",
|
rf"^testserver account security <{self.TOKENIZED_NOREPLY_REGEX}>\Z",
|
||||||
)
|
)
|
||||||
|
|
||||||
self.assertEqual(email_message.extra_headers["List-Id"], "Zulip Dev <zulip.testserver>")
|
self.assertEqual(email_message.extra_headers["List-Id"], "Zulip Dev <zulip.testserver>")
|
||||||
|
@ -392,7 +392,7 @@ class EmailChangeTestCase(ZulipTestCase):
|
||||||
self.assertEqual(self.email_envelope_from(email_message), settings.NOREPLY_EMAIL_ADDRESS)
|
self.assertEqual(self.email_envelope_from(email_message), settings.NOREPLY_EMAIL_ADDRESS)
|
||||||
self.assertRegex(
|
self.assertRegex(
|
||||||
self.email_display_from(email_message),
|
self.email_display_from(email_message),
|
||||||
rf"^Zulip Account Security <{self.TOKENIZED_NOREPLY_REGEX}>\Z",
|
rf"^testserver account security <{self.TOKENIZED_NOREPLY_REGEX}>\Z",
|
||||||
)
|
)
|
||||||
self.assertEqual(email_message.extra_headers["List-Id"], "Zulip Dev <zulip.testserver>")
|
self.assertEqual(email_message.extra_headers["List-Id"], "Zulip Dev <zulip.testserver>")
|
||||||
|
|
||||||
|
|
|
@ -402,7 +402,7 @@ class TestPasswordRestEmail(ZulipTestCase):
|
||||||
self.assertEqual(self.email_envelope_from(outbox[0]), settings.NOREPLY_EMAIL_ADDRESS)
|
self.assertEqual(self.email_envelope_from(outbox[0]), settings.NOREPLY_EMAIL_ADDRESS)
|
||||||
self.assertRegex(
|
self.assertRegex(
|
||||||
self.email_display_from(outbox[0]),
|
self.email_display_from(outbox[0]),
|
||||||
rf"^Zulip Account Security <{self.TOKENIZED_NOREPLY_REGEX}>\Z",
|
rf"^testserver account security <{self.TOKENIZED_NOREPLY_REGEX}>\Z",
|
||||||
)
|
)
|
||||||
self.assertIn("reset your password", outbox[0].body)
|
self.assertIn("reset your password", outbox[0].body)
|
||||||
|
|
||||||
|
|
|
@ -131,7 +131,9 @@ class TestMessageNotificationEmails(ZulipTestCase):
|
||||||
reply_to_emails = ["noreply@testserver"]
|
reply_to_emails = ["noreply@testserver"]
|
||||||
msg = mail.outbox[0]
|
msg = mail.outbox[0]
|
||||||
assert isinstance(msg, EmailMultiAlternatives)
|
assert isinstance(msg, EmailMultiAlternatives)
|
||||||
from_email = str(Address(display_name="Zulip notifications", addr_spec=FromAddress.NOREPLY))
|
from_email = str(
|
||||||
|
Address(display_name="testserver notifications", addr_spec=FromAddress.NOREPLY)
|
||||||
|
)
|
||||||
self.assert_length(mail.outbox, 1)
|
self.assert_length(mail.outbox, 1)
|
||||||
self.assertEqual(self.email_envelope_from(msg), settings.NOREPLY_EMAIL_ADDRESS)
|
self.assertEqual(self.email_envelope_from(msg), settings.NOREPLY_EMAIL_ADDRESS)
|
||||||
self.assertEqual(self.email_display_from(msg), from_email)
|
self.assertEqual(self.email_display_from(msg), from_email)
|
||||||
|
|
|
@ -452,7 +452,7 @@ class RealmTest(ZulipTestCase):
|
||||||
self.assertEqual(self.email_envelope_from(outbox[0]), settings.NOREPLY_EMAIL_ADDRESS)
|
self.assertEqual(self.email_envelope_from(outbox[0]), settings.NOREPLY_EMAIL_ADDRESS)
|
||||||
self.assertRegex(
|
self.assertRegex(
|
||||||
self.email_display_from(outbox[0]),
|
self.email_display_from(outbox[0]),
|
||||||
rf"^Zulip Account Security <{self.TOKENIZED_NOREPLY_REGEX}>\Z",
|
rf"^testserver account security <{self.TOKENIZED_NOREPLY_REGEX}>\Z",
|
||||||
)
|
)
|
||||||
self.assertIn("Reactivate your Zulip organization", outbox[0].subject)
|
self.assertIn("Reactivate your Zulip organization", outbox[0].subject)
|
||||||
self.assertIn("Dear former administrators", outbox[0].body)
|
self.assertIn("Dear former administrators", outbox[0].body)
|
||||||
|
|
|
@ -16,7 +16,6 @@ from django.http import HttpResponse, HttpResponseBase
|
||||||
from django.template.response import TemplateResponse
|
from django.template.response import TemplateResponse
|
||||||
from django.test import Client, override_settings
|
from django.test import Client, override_settings
|
||||||
from django.utils import translation
|
from django.utils import translation
|
||||||
from django.utils.translation import gettext as _
|
|
||||||
|
|
||||||
from confirmation import settings as confirmation_settings
|
from confirmation import settings as confirmation_settings
|
||||||
from confirmation.models import Confirmation, one_click_unsubscribe_link
|
from confirmation.models import Confirmation, one_click_unsubscribe_link
|
||||||
|
@ -360,7 +359,7 @@ class PasswordResetTest(ZulipTestCase):
|
||||||
# The email might be sent in different languages for i18n testing
|
# The email might be sent in different languages for i18n testing
|
||||||
self.assertRegex(
|
self.assertRegex(
|
||||||
self.email_display_from(message),
|
self.email_display_from(message),
|
||||||
rf'^{_("Zulip Account Security")} <{self.TOKENIZED_NOREPLY_REGEX}>\Z',
|
rf"^testserver account security <{self.TOKENIZED_NOREPLY_REGEX}>\Z",
|
||||||
)
|
)
|
||||||
self.assertIn(f"{subdomain}.testserver", message.extra_headers["List-Id"])
|
self.assertIn(f"{subdomain}.testserver", message.extra_headers["List-Id"])
|
||||||
|
|
||||||
|
|
|
@ -485,6 +485,8 @@ WELCOME_EMAIL_SENDER: Optional[Dict[str, str]] = None
|
||||||
|
|
||||||
# Whether to send periodic digests of activity.
|
# Whether to send periodic digests of activity.
|
||||||
SEND_DIGEST_EMAILS = True
|
SEND_DIGEST_EMAILS = True
|
||||||
|
# The variable part of email sender names to be used for outgoing emails.
|
||||||
|
INSTALLATION_NAME = EXTERNAL_HOST
|
||||||
|
|
||||||
# Used to change the Zulip logo in portico pages.
|
# Used to change the Zulip logo in portico pages.
|
||||||
CUSTOM_LOGO_URL: Optional[str] = None
|
CUSTOM_LOGO_URL: Optional[str] = None
|
||||||
|
|
|
@ -101,6 +101,13 @@ EXTERNAL_HOST = "zulip.example.com"
|
||||||
## confirmation emails when ADD_TOKENS_TO_NOREPLY_ADDRESS=False.
|
## confirmation emails when ADD_TOKENS_TO_NOREPLY_ADDRESS=False.
|
||||||
# NOREPLY_EMAIL_ADDRESS = "noreply@example.com"
|
# NOREPLY_EMAIL_ADDRESS = "noreply@example.com"
|
||||||
|
|
||||||
|
## Emails sent by the Zulip server will use a sender name starting
|
||||||
|
## with INSTALLATION_NAME. The default is EXTERNAL_HOST. If INSTALLATION_NAME is
|
||||||
|
## "zulip.example.com", email senders names will include:
|
||||||
|
## * "zulip.example.com notifications" (message notification emails).
|
||||||
|
## * "zulip.example.com account security" (account security emails).
|
||||||
|
# INSTALLATION_NAME = "My Zulip Server"
|
||||||
|
|
||||||
## Many countries and bulk mailers require certain types of email to display
|
## Many countries and bulk mailers require certain types of email to display
|
||||||
## a physical mailing address to comply with anti-spam legislation.
|
## a physical mailing address to comply with anti-spam legislation.
|
||||||
## Non-commercial and non-public-facing installations are unlikely to need
|
## Non-commercial and non-public-facing installations are unlikely to need
|
||||||
|
|
Loading…
Reference in New Issue