def _get_email_from(self, email_from): """Logic which determines which email to use when sending the email. - If the system parameter `mail.force.smtp.from` is set we encapsulate all outgoing email from - If the previous system parameter is not set and if both `mail.dynamic.smtp.from` and `mail.catchall.domain` are set, we encapsulate the FROM only if the domain of the email is not the same as the domain of the catchall parameter - Otherwise we do not encapsulate the email and given email_from is used as is :param email_from: The initial FROM headers :return: The FROM to used in the headers and optionally the Return-Path """ force_smtp_from = self.env['ir.config_parameter'].sudo().get_param('mail.force.smtp.from') dynamic_smtp_from = self.env['ir.config_parameter'].sudo().get_param('mail.dynamic.smtp.from') catchall_domain = self.env['ir.config_parameter'].sudo().get_param('mail.catchall.domain') if force_smtp_from: rfc2822_force_smtp_from = extract_rfc2822_addresses(force_smtp_from) rfc2822_force_smtp_from = rfc2822_force_smtp_from[0] if rfc2822_force_smtp_from else None return encapsulate_email(email_from, force_smtp_from), rfc2822_force_smtp_from elif dynamic_smtp_from and catchall_domain and email_domain_extract(email_from) != catchall_domain: rfc2822_dynamic_smtp_from = extract_rfc2822_addresses(dynamic_smtp_from) rfc2822_dynamic_smtp_from = rfc2822_dynamic_smtp_from[0] if rfc2822_dynamic_smtp_from else None return encapsulate_email(email_from, dynamic_smtp_from), rfc2822_dynamic_smtp_from return email_from, None
def _prepare_email_message(self, message, smtp_session): """Prepare the SMTP information (from, to, message) before sending. :param message: the email.message.Message to send, information like the Return-Path, the From, etc... will be used to find the smtp_from and to smtp_to :param smtp_session: the opened SMTP session to use to authenticate the sender :return: smtp_from, smtp_to_list, message smtp_from: email to used during the authentication to the mail server smtp_to_list: list of email address which will receive the email message: the email.message.Message to send """ # Use the default bounce address **only if** no Return-Path was # provided by caller. Caller may be using Variable Envelope Return # Path (VERP) to detect no-longer valid email addresses. bounce_address = message[ 'Return-Path'] or self._get_default_bounce_address( ) or message['From'] smtp_from = message['From'] or bounce_address assert smtp_from, "The Return-Path or From header is required for any outbound email" email_to = message['To'] email_cc = message['Cc'] email_bcc = message['Bcc'] del message['Bcc'] # All recipient addresses must only contain ASCII characters smtp_to_list = [ address for base in [email_to, email_cc, email_bcc] for address in extract_rfc2822_addresses(base) if address ] assert smtp_to_list, self.NO_VALID_RECIPIENT x_forge_to = message['X-Forge-To'] if x_forge_to: # `To:` header forged, e.g. for posting on mail.channels, to avoid confusion del message['X-Forge-To'] del message['To'] # avoid multiple To: headers! message['To'] = x_forge_to # Try to not spoof the mail from headers from_filter = getattr(smtp_session, 'from_filter', False) smtp_from = getattr(smtp_session, 'smtp_from', False) or smtp_from notifications_email = email_normalize(self._get_default_from_address()) if notifications_email and smtp_from == notifications_email and message[ 'From'] != notifications_email: smtp_from = encapsulate_email(message['From'], notifications_email) if message['From'] != smtp_from: del message['From'] message['From'] = smtp_from # Check if it's still possible to put the bounce address as smtp_from if self._match_from_filter(bounce_address, from_filter): # Mail headers FROM will be spoofed to be able to receive bounce notifications # Because the mail server support the domain of the bounce address smtp_from = bounce_address # The email's "Envelope From" (Return-Path) must only contain ASCII characters. smtp_from_rfc2822 = extract_rfc2822_addresses(smtp_from) assert smtp_from_rfc2822, ( f"Malformed 'Return-Path' or 'From' address: {smtp_from} - " "It should contain one valid plain ASCII email") smtp_from = smtp_from_rfc2822[-1] return smtp_from, smtp_to_list, message