diff --git a/addons/mail/__manifest__.py b/addons/mail/__manifest__.py index ae56580d942..965198d0c45 100644 --- a/addons/mail/__manifest__.py +++ b/addons/mail/__manifest__.py @@ -27,7 +27,6 @@ 'views/mail_shortcode_views.xml', 'views/mail_activity_views.xml', 'views/res_config_settings_views.xml', - 'data/ir_config_parameter_data.xml', 'data/res_partner_data.xml', 'data/mail_message_subtype_data.xml', 'data/mail_templates.xml', diff --git a/addons/mail/data/ir_config_parameter_data.xml b/addons/mail/data/ir_config_parameter_data.xml deleted file mode 100644 index e4a2bfd088d..00000000000 --- a/addons/mail/data/ir_config_parameter_data.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - mail.catchall.alias - catchall - - - - - mail.bounce.alias - bounce - - - diff --git a/addons/mail/models/mail_mail.py b/addons/mail/models/mail_mail.py index bb39e6ff7b9..1eb110a4abf 100644 --- a/addons/mail/models/mail_mail.py +++ b/addons/mail/models/mail_mail.py @@ -217,22 +217,47 @@ class MailMail(models.Model): } return res - def _split_by_server(self): - """Returns an iterator of pairs `(mail_server_id, record_ids)` for current recordset. + def _split_by_mail_configuration(self): + """Group the based on their "email_from" and their "mail_server_id". - The same `mail_server_id` may repeat in order to limit batch size according to - the `mail.session.batch.size` system parameter. + The will have the "same sending configuration" if they have the same + mail server or the same mail from. For performance purpose, we can use an SMTP + session in batch and therefore we need to group them by the parameter that will + influence the mail server used. + + The same "sending configuration" may repeat in order to limit batch size + according to the `mail.session.batch.size` system parameter. + + Return iterators over + mail_server_id, email_from, Records.ids """ - groups = defaultdict(list) - # Turn prefetch OFF to avoid MemoryError on very large mail queues, we only care - # about the mail server ids in this case. - for mail in self.with_context(prefetch_fields=False): - groups[mail.mail_server_id.id].append(mail.id) + mail_values = self.read(['id', 'email_from', 'mail_server_id']) + + # First group the per mail_server_id and per email_from + group_per_email_from = defaultdict(list) + for values in mail_values: + mail_server_id = values['mail_server_id'][0] if values['mail_server_id'] else False + group_per_email_from[(mail_server_id, values['email_from'])].append(values['id']) + + # Then find the mail server for each email_from and group the + # per mail_server_id and smtp_from + mail_servers = self.env['ir.mail_server'].sudo().search([], order='sequence') + group_per_smtp_from = defaultdict(list) + for (mail_server_id, email_from), mail_ids in group_per_email_from.items(): + if not mail_server_id: + mail_server, smtp_from = self.env['ir.mail_server']._find_mail_server(email_from, mail_servers) + mail_server_id = mail_server.id if mail_server else False + else: + smtp_from = email_from + + group_per_smtp_from[(mail_server_id, smtp_from)].extend(mail_ids) + sys_params = self.env['ir.config_parameter'].sudo() batch_size = int(sys_params.get_param('mail.session.batch.size', 1000)) - for server_id, record_ids in groups.items(): - for mail_batch in tools.split_every(batch_size, record_ids): - yield server_id, mail_batch + + for (mail_server_id, smtp_from), record_ids in group_per_smtp_from.items(): + for batch_ids in tools.split_every(batch_size, record_ids): + yield mail_server_id, smtp_from, batch_ids def send(self, auto_commit=False, raise_exception=False): """ Sends the selected emails immediately, ignoring their current @@ -249,10 +274,10 @@ class MailMail(models.Model): email sending process has failed :return: True """ - for server_id, batch_ids in self._split_by_server(): + for mail_server_id, smtp_from, batch_ids in self._split_by_mail_configuration(): smtp_session = None try: - smtp_session = self.env['ir.mail_server'].connect(mail_server_id=server_id) + smtp_session = self.env['ir.mail_server'].connect(mail_server_id=mail_server_id, smtp_from=smtp_from) except Exception as exc: if raise_exception: # To be consistent and backward compatible with mail_mail.send() raised @@ -269,7 +294,7 @@ class MailMail(models.Model): smtp_session=smtp_session) _logger.info( 'Sent batch %s emails via mail server ID #%s', - len(batch_ids), server_id) + len(batch_ids), mail_server_id) finally: if smtp_session: smtp_session.quit() diff --git a/addons/mail/tests/common.py b/addons/mail/tests/common.py index 650f273e1ae..a62105585a6 100644 --- a/addons/mail/tests/common.py +++ b/addons/mail/tests/common.py @@ -100,9 +100,11 @@ class MockEmail(common.BaseCase): cls.alias_domain = 'test.com' cls.alias_catchall = 'catchall.test' cls.alias_bounce = 'bounce.test' + cls.default_from = 'notifications' cls.env['ir.config_parameter'].set_param('mail.bounce.alias', cls.alias_bounce) cls.env['ir.config_parameter'].set_param('mail.catchall.domain', cls.alias_domain) cls.env['ir.config_parameter'].set_param('mail.catchall.alias', cls.alias_catchall) + cls.env['ir.config_parameter'].set_param('mail.default.from', cls.default_from) cls.mailer_daemon_email = formataddr(('MAILER-DAEMON', '%s@%s' % (cls.alias_bounce, cls.alias_domain))) def format(self, template, to='groups@example.com, other@gmail.com', subject='Frogs', diff --git a/addons/mass_mailing/models/mailing.py b/addons/mass_mailing/models/mailing.py index 73ac0a0f9fb..ef27dbcf085 100644 --- a/addons/mass_mailing/models/mailing.py +++ b/addons/mass_mailing/models/mailing.py @@ -71,8 +71,8 @@ class MassMailing(models.Model): help='Catchy preview sentence that encourages recipients to open this email.\n' 'In most inboxes, this is displayed next to the subject.\n' 'Keep it empty if you prefer the first characters of your email content to appear instead.') - email_from = fields.Char(string='Send From', required=True, - default=lambda self: self.env.user.email_formatted) + email_from = fields.Char(string='Send From', required=True, store=True, readonly=False, compute='_compute_email_from', + default=lambda self: self.env.user.email_formatted) sent_date = fields.Datetime(string='Sent Date', copy=False) schedule_type = fields.Selection([('now', 'Send now'), ('scheduled', 'Send on')], string='Schedule', @@ -157,6 +157,28 @@ class MassMailing(models.Model): bounced_ratio = fields.Integer(compute="_compute_statistics", string='Bounced Ratio') clicks_ratio = fields.Integer(compute="_compute_clicks_ratio", string="Number of Clicks") next_departure = fields.Datetime(compute="_compute_next_departure", string='Scheduled date') + # UX + warning_message = fields.Char( + 'Warning Message', compute='_compute_warning_message', + help='Warning message displayed in the mailing form view') + + @api.depends('mail_server_id') + def _compute_email_from(self): + user_email = self.env.user.email_formatted + notification_email = self.env['ir.mail_server']._get_default_from_address() + + for mailing in self: + server = mailing.mail_server_id + if not server: + mailing.email_from = mailing.email_from or user_email + elif mailing.email_from and server._match_from_filter(mailing.email_from, server.from_filter): + mailing.email_from = mailing.email_from + elif server._match_from_filter(user_email, server.from_filter): + mailing.email_from = user_email + elif server._match_from_filter(notification_email, server.from_filter): + mailing.email_from = notification_email + else: + mailing.email_from = mailing.email_from or user_email def _compute_total(self): for mass_mailing in self: @@ -232,6 +254,18 @@ class MassMailing(models.Model): else: mass_mailing.next_departure = cron_time + @api.depends('email_from', 'mail_server_id') + def _compute_warning_message(self): + for mailing in self: + mail_server = mailing.mail_server_id + if mail_server and not mail_server._match_from_filter(mailing.email_from, mail_server.from_filter): + mailing.warning_message = _( + 'This email from can not be used with this mail server.\n' + 'Your emails might be marked as spam on the mail clients.' + ) + else: + mailing.warning_message = False + @api.depends('mailing_type') def _compute_medium_id(self): for mailing in self: diff --git a/addons/mass_mailing/views/mailing_mailing_views.xml b/addons/mass_mailing/views/mailing_mailing_views.xml index 5b9c3405fea..6178fb2d452 100644 --- a/addons/mass_mailing/views/mailing_mailing_views.xml +++ b/addons/mass_mailing/views/mailing_mailing_views.xml @@ -65,7 +65,8 @@ -