diff --git a/addons/mail/models/mail_mail.py b/addons/mail/models/mail_mail.py index d846041c9f541..fd8d01eeab14a 100644 --- a/addons/mail/models/mail_mail.py +++ b/addons/mail/models/mail_mail.py @@ -342,6 +342,16 @@ def _send(self, auto_commit=False, raise_exception=False, smtp_session=None): # build an RFC2822 email.message.Message object and send it without queuing res = None for email in email_list: + # support headers specific to the specific outgoing email + if email.get('headers'): + email_headers = headers.copy() + try: + email_headers.update(email.get('headers')) + except Exception: + pass + else: + email_headers = headers + msg = IrMailServer.build_email( email_from=mail.email_from, email_to=email.get('email_to'), @@ -356,7 +366,7 @@ def _send(self, auto_commit=False, raise_exception=False, smtp_session=None): object_id=mail.res_id and ('%s-%s' % (mail.res_id, mail.model)), subtype='html', subtype_alternative='plain', - headers=headers) + headers=email_headers) processing_pid = email.pop("partner_id", None) try: res = IrMailServer.send_email( diff --git a/addons/mass_mailing/controllers/main.py b/addons/mass_mailing/controllers/main.py index 02ffe4609c387..f0d55872e55e0 100644 --- a/addons/mass_mailing/controllers/main.py +++ b/addons/mass_mailing/controllers/main.py @@ -27,7 +27,9 @@ def unsubscribe_placeholder_link(self, **post): """Dummy route so placeholder is not prefixed by language, MUST have multilang=False""" raise werkzeug.exceptions.NotFound() - @http.route(['/mail/mailing//unsubscribe'], type='http', website=True, auth='public') + # csrf is disabled here because it will be called by the MUA with unpredictable session at that time + @http.route(['/mail/mailing//unsubscribe'], type='http', website=True, auth='public', + csrf=False) def mailing(self, mailing_id, email=None, res_id=None, token="", **post): mailing = request.env['mailing.mailing'].sudo().browse(mailing_id) if mailing.exists(): diff --git a/addons/mass_mailing/models/mail_mail.py b/addons/mass_mailing/models/mail_mail.py index 845cd05fdfd45..dbd9ec67060b4 100644 --- a/addons/mass_mailing/models/mail_mail.py +++ b/addons/mass_mailing/models/mail_mail.py @@ -82,14 +82,27 @@ def _send_prepare_body(self): def _send_prepare_values(self, partner=None): # TDE: temporary addition (mail was parameter) due to semi-new-API res = super(MailMail, self)._send_prepare_values(partner) - base_url = self.env['ir.config_parameter'].sudo().get_param('web.base.url').rstrip('/') - if self.mailing_id and res.get('body') and res.get('email_to'): + if self.mailing_id and res.get('email_to'): + base_url = self.mailing_id.get_base_url() emails = tools.email_split(res.get('email_to')[0]) email_to = emails and emails[0] or False + unsubscribe_url = self._get_unsubscribe_url(email_to) - link_to_replace = base_url + '/unsubscribe_from_list' - if link_to_replace in res['body']: - res['body'] = res['body'].replace(link_to_replace, unsubscribe_url if unsubscribe_url else '#') + + # replace links in body + if f'{base_url}/unsubscribe_from_list' in res['body']: + res['body'] = res['body'].replace( + f'{base_url}/unsubscribe_from_list', + unsubscribe_url, + ) + + # add headers + res.setdefault("headers", {}).update({ + 'List-Unsubscribe': f'<{unsubscribe_url}>', + 'List-Unsubscribe-Post': 'List-Unsubscribe=One-Click', + 'Precedence': 'list', + 'X-Auto-Response-Suppress': 'OOF', # avoid out-of-office replies from MS Exchange + }) return res def _postprocess_sent_message(self, success_pids, failure_reason=False, failure_type=None):