mirror of
				https://github.com/zulip/zulip.git
				synced 2025-11-04 05:53:43 +00:00 
			
		
		
		
	The envelope-from is used by the MTA if the destination address is not deliverable. Route all such mail to the noreply address.
		
			
				
	
	
		
			92 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			92 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
import configparser
 | 
						|
import logging
 | 
						|
from typing import List
 | 
						|
 | 
						|
from django.conf import settings
 | 
						|
from django.core.mail import EmailMultiAlternatives
 | 
						|
from django.core.mail.backends.smtp import EmailBackend
 | 
						|
from django.template import loader
 | 
						|
 | 
						|
 | 
						|
def get_forward_address() -> str:
 | 
						|
    config = configparser.ConfigParser()
 | 
						|
    config.read(settings.FORWARD_ADDRESS_CONFIG_FILE)
 | 
						|
    try:
 | 
						|
        return config.get("DEV_EMAIL", "forward_address")
 | 
						|
    except (configparser.NoSectionError, configparser.NoOptionError):
 | 
						|
        return ""
 | 
						|
 | 
						|
 | 
						|
def set_forward_address(forward_address: str) -> None:
 | 
						|
    config = configparser.ConfigParser()
 | 
						|
    config.read(settings.FORWARD_ADDRESS_CONFIG_FILE)
 | 
						|
 | 
						|
    if not config.has_section("DEV_EMAIL"):
 | 
						|
        config.add_section("DEV_EMAIL")
 | 
						|
    config.set("DEV_EMAIL", "forward_address", forward_address)
 | 
						|
 | 
						|
    with open(settings.FORWARD_ADDRESS_CONFIG_FILE, "w") as cfgfile:
 | 
						|
        config.write(cfgfile)
 | 
						|
 | 
						|
 | 
						|
class EmailLogBackEnd(EmailBackend):
 | 
						|
    @staticmethod
 | 
						|
    def log_email(email: EmailMultiAlternatives) -> None:
 | 
						|
        """Used in development to record sent emails in a nice HTML log"""
 | 
						|
        html_message = "Missing HTML message"
 | 
						|
        if len(email.alternatives) > 0:
 | 
						|
            html_message = email.alternatives[0][0]
 | 
						|
 | 
						|
        context = {
 | 
						|
            "subject": email.subject,
 | 
						|
            "envelope_from": email.from_email,
 | 
						|
            "from_email": email.extra_headers.get("From", email.from_email),
 | 
						|
            "reply_to": email.reply_to,
 | 
						|
            "recipients": email.to,
 | 
						|
            "body": email.body,
 | 
						|
            "html_message": html_message,
 | 
						|
        }
 | 
						|
 | 
						|
        new_email = loader.render_to_string("zerver/email.html", context)
 | 
						|
 | 
						|
        # Read in the pre-existing log, so that we can add the new entry
 | 
						|
        # at the top.
 | 
						|
        try:
 | 
						|
            with open(settings.EMAIL_CONTENT_LOG_PATH) as f:
 | 
						|
                previous_emails = f.read()
 | 
						|
        except FileNotFoundError:
 | 
						|
            previous_emails = ""
 | 
						|
 | 
						|
        with open(settings.EMAIL_CONTENT_LOG_PATH, "w+") as f:
 | 
						|
            f.write(new_email + previous_emails)
 | 
						|
 | 
						|
    @staticmethod
 | 
						|
    def prepare_email_messages_for_forwarding(email_messages: List[EmailMultiAlternatives]) -> None:
 | 
						|
        localhost_email_images_base_uri = settings.ROOT_DOMAIN_URI + "/static/images/emails"
 | 
						|
        czo_email_images_base_uri = "https://chat.zulip.org/static/images/emails"
 | 
						|
 | 
						|
        for email_message in email_messages:
 | 
						|
            html_alternative = list(email_message.alternatives[0])
 | 
						|
            # Here, we replace the email addresses used in development
 | 
						|
            # with chat.zulip.org, so that web email providers like Gmail
 | 
						|
            # will be able to fetch the illustrations used in the emails.
 | 
						|
            html_alternative[0] = html_alternative[0].replace(
 | 
						|
                localhost_email_images_base_uri, czo_email_images_base_uri
 | 
						|
            )
 | 
						|
            email_message.alternatives[0] = tuple(html_alternative)
 | 
						|
 | 
						|
            email_message.to = [get_forward_address()]
 | 
						|
 | 
						|
    def send_messages(self, email_messages: List[EmailMultiAlternatives]) -> int:
 | 
						|
        num_sent = len(email_messages)
 | 
						|
        if get_forward_address():
 | 
						|
            self.prepare_email_messages_for_forwarding(email_messages)
 | 
						|
            num_sent = super().send_messages(email_messages)
 | 
						|
 | 
						|
        if settings.DEVELOPMENT_LOG_EMAILS:
 | 
						|
            for email in email_messages:
 | 
						|
                self.log_email(email)
 | 
						|
                email_log_url = settings.ROOT_DOMAIN_URI + "/emails"
 | 
						|
                logging.info("Emails sent in development are available at %s", email_log_url)
 | 
						|
        return num_sent
 |