From 184df7e6568972ecb1773f17092b54f1a55bee70 Mon Sep 17 00:00:00 2001 From: pletinckxc Date: Wed, 28 Apr 2021 20:23:14 +0200 Subject: [PATCH] emails: Fix outgoing email handling inside the dev environment. Commit 9afde790c6a1855de1714378b1ee3e467a7b0fb1 introduced a bug concerning outgoing emails inside the development environment. These emails are not supposed to use a real connection with a mail server as the send_messages function is overwritten inside the EmailLogBackEnd class. The bug was happening inside the initialize_connection function that was introduced in the above-mentioned commit. This function is used to refresh the connection with an SMTP server that would have closed it. As the socket used to communicate with the server is not initialized inside the development environment this function was wrongly trying to send no-op commands. The fix just checks that the connection argument of the function is an EmailLogBackEnd object before trying the no-op command. Additionally as it is sometimes useful to be able to send outgoing emails inside the development environment the get_forward_address function is used to check if a real connection exists between Zulip and the server. If it is the case, as EmailLogBackEnd is a subclass of smtp.EmailBackend, the connection will be nicely refreshed. This commit was tested manually by checking that the console prints correctly that an email is sent to the user when it signs in inside the development environment. It was also tested when a mail provider is specified and the mails were correctly received. --- zerver/lib/send_email.py | 16 +++++++++++++++- zproject/email_backends.py | 1 + 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/zerver/lib/send_email.py b/zerver/lib/send_email.py index 30f4eb41a1..2fc4032a42 100644 --- a/zerver/lib/send_email.py +++ b/zerver/lib/send_email.py @@ -27,6 +27,7 @@ from confirmation.models import generate_key, one_click_unsubscribe_link from scripts.setup.inline_email_css import inline_template from zerver.lib.logging_util import log_to_file from zerver.models import EMAIL_TYPES, Realm, ScheduledEmail, UserProfile, get_user_profile_by_id +from zproject.email_backends import EmailLogBackEnd, get_forward_address MAX_CONNECTION_TRIES = 3 @@ -256,10 +257,22 @@ def send_email( def initialize_connection(connection: Optional[BaseEmailBackend] = None) -> BaseEmailBackend: if not connection: connection = get_connection() + if connection.open(): # If it's a new connection, no need to no-op to check connectivity return connection - # No-op to ensure that we don't return a connection that has been closed by the mail server + + if isinstance(connection, EmailLogBackEnd) and not get_forward_address(): + # With the development environment backend and without a + # configured forwarding address, we don't actually send emails. + # + # As a result, the connection cannot be closed by the server + # (as there is none), and `connection.noop` is not + # implemented, so we need to return the connection early. + return connection + + # No-op to ensure that we don't return a connection that has been + # closed by the mail server. if isinstance(connection, EmailBackend): try: status = connection.connection.noop()[0] @@ -269,6 +282,7 @@ def initialize_connection(connection: Optional[BaseEmailBackend] = None) -> Base # Close and connect again. connection.close() connection.open() + return connection diff --git a/zproject/email_backends.py b/zproject/email_backends.py index e67aa2aa4e..cfdb3a80d6 100644 --- a/zproject/email_backends.py +++ b/zproject/email_backends.py @@ -1,3 +1,4 @@ +# https://zulip.readthedocs.io/en/latest/subsystems/email.html#testing-in-a-real-email-client import configparser import logging from typing import List