diff --git a/addons/auth_signup/controllers/main.py b/addons/auth_signup/controllers/main.py index 986278e2ab3..3b6b92afd54 100644 --- a/addons/auth_signup/controllers/main.py +++ b/addons/auth_signup/controllers/main.py @@ -40,10 +40,7 @@ class AuthSignupHome(Home): user_sudo = request.env['res.users'].sudo().search([('login', '=', qcontext.get('login'))]) template = request.env.ref('auth_signup.mail_template_user_signup_account_created', raise_if_not_found=False) if user_sudo and template: - template.sudo().with_context( - lang=user_sudo.lang, - auth_login=werkzeug.url_encode({'auth_login': user_sudo.email}), - ).send_mail(user_sudo.id, force_send=True) + template.sudo().send_mail(user_sudo.id, force_send=True) return self.web_login(*args, **kw) except UserError as e: qcontext['error'] = e.name or e.value diff --git a/addons/auth_signup/data/auth_signup_data.xml b/addons/auth_signup/data/auth_signup_data.xml index 5fe062a6d44..e83930f0b88 100644 --- a/addons/auth_signup/data/auth_signup_data.xml +++ b/addons/auth_signup/data/auth_signup_data.xml @@ -289,7 +289,7 @@ Your login is ${object.email}
To gain access to your account, you can use the following link:
- Go to My Account diff --git a/addons/auth_signup/models/res_users.py b/addons/auth_signup/models/res_users.py index 11df8c34116..a1abd1c32b6 100644 --- a/addons/auth_signup/models/res_users.py +++ b/addons/auth_signup/models/res_users.py @@ -195,8 +195,9 @@ class ResUsers(models.Model): for user in self: if not user.email: raise UserError(_("Cannot send email: user %s has no email address.") % user.name) + # TDE FIXME: make this template technical (qweb) with self.env.cr.savepoint(): - template.with_context(lang=user.lang).send_mail(user.id, force_send=True, raise_exception=True) + template.send_mail(user.id, force_send=True, raise_exception=True) _logger.info("Password reset email sent for user <%s> to <%s>", user.login, user.email) def send_unregistered_user_reminder(self, after_days=5): diff --git a/addons/hr_expense/models/hr_expense.py b/addons/hr_expense/models/hr_expense.py index a535a8840c0..259cb7e0167 100644 --- a/addons/hr_expense/models/hr_expense.py +++ b/addons/hr_expense/models/hr_expense.py @@ -617,6 +617,8 @@ class HrExpense(models.Model): ) else: self.env['mail.mail'].create({ + 'email_from': self.env.user.email_formatted, + 'author_id': self.env.user.partner_id.id, 'body_html': body, 'subject': 'Re: %s' % msg_dict.get('subject', ''), 'email_to': msg_dict.get('email_from', False), diff --git a/addons/im_livechat/models/mail_channel.py b/addons/im_livechat/models/mail_channel.py index a46bc56d4d7..b5397e38bdf 100644 --- a/addons/im_livechat/models/mail_channel.py +++ b/addons/im_livechat/models/mail_channel.py @@ -173,7 +173,8 @@ class MailChannel(models.Model): mail_body = self.env['mail.thread']._replace_local_links(mail_body) mail = self.env['mail.mail'].create({ 'subject': _('Conversation with %s') % self.livechat_operator_id.name, - 'email_from': self.env.company.email, + 'email_from': company.catchall_formatted or company.email_formatted, + 'author_id': self.env.user.partner_id.id, 'email_to': email, 'body_html': mail_body, }) diff --git a/addons/mail/models/mail_channel.py b/addons/mail/models/mail_channel.py index a8440322c2b..ad1a1ef42b4 100644 --- a/addons/mail/models/mail_channel.py +++ b/addons/mail/models/mail_channel.py @@ -368,6 +368,8 @@ class Channel(models.Model): # The fields "email_from" and "reply_to" are filled in automatically by method create in model mail.message. if self.moderation_notify and self.moderation_notify_msg and message_type == 'email' and moderation_status == 'pending_moderation': self.env['mail.mail'].create({ + 'author_id': self.env.user.partner_id.id, + 'email_from': self.env.user.company_id.catchall_formatted or self.env.user.company_id.email_formatted, 'body_html': self.moderation_notify_msg, 'subject': 'Re: %s' % (kwargs.get('subject', '')), 'email_to': email, @@ -418,9 +420,10 @@ class Channel(models.Model): ]).mapped('email') for partner in partners.filtered(lambda p: p.email and not (p.email in banned_emails)): create_values = { + 'email_from': partner.company_id.catchall_formatted or partner.company_id.email_formatted, + 'author_id': self.env.user.partner_id.id, 'body_html': view.render({'channel': self, 'partner': partner}, engine='ir.qweb', minimal_qcontext=True), 'subject': _("Guidelines of channel %s") % self.name, - 'email_from': partner.company_id.catchall_formatted or partner.company_id.email, 'recipient_ids': [(4, partner.id)] } mail = self.env['mail.mail'].create(create_values) diff --git a/addons/mail/models/mail_message.py b/addons/mail/models/mail_message.py index 0bcc082fee5..5be02450f87 100644 --- a/addons/mail/models/mail_message.py +++ b/addons/mail/models/mail_message.py @@ -9,7 +9,7 @@ from collections import defaultdict from operator import itemgetter from odoo import _, api, fields, models, modules, tools -from odoo.exceptions import UserError, AccessError +from odoo.exceptions import AccessError from odoo.http import request from odoo.osv import expression from odoo.tools import groupby @@ -27,14 +27,17 @@ class Message(models.Model): _rec_name = 'record_name' @api.model - def _get_default_from(self): - if self.env.user.email: - return tools.formataddr((self.env.user.name, self.env.user.email)) - raise UserError(_("Unable to post message, please configure the sender's email address.")) - - @api.model - def _get_default_author(self): - return self.env.user.partner_id + def default_get(self, fields): + res = super(Message, self).default_get(fields) + missing_author = 'author_id' in fields and 'author_id' not in res + missing_email_from = 'email_from' in fields and 'email_from' not in res + if missing_author or missing_email_from: + author_id, email_from = self.env['mail.thread']._message_compute_author(res.get('author_id'), res.get('email_from'), raise_exception=False) + if missing_email_from: + res['email_from'] = email_from + if missing_author: + res['author_id'] = author_id + return res # content subject = fields.Char('Subject') @@ -69,12 +72,9 @@ class Message(models.Model): 'mail.activity.type', 'Mail Activity Type', index=True, ondelete='set null') # origin - email_from = fields.Char( - 'From', default=_get_default_from, - help="Email address of the sender. This field is set when no matching partner is found and replaces the author_id field in the chatter.") + email_from = fields.Char('From', help="Email address of the sender. This field is set when no matching partner is found and replaces the author_id field in the chatter.") author_id = fields.Many2one( - 'res.partner', 'Author', index=True, - ondelete='set null', default=_get_default_author, + 'res.partner', 'Author', index=True, ondelete='set null', help="Author of the message. If not set, email_from may hold an email address that did not match any partner.") author_avatar = fields.Binary("Author's avatar", related='author_id.image_128', readonly=False) # recipients: include inactive partners (they may have been archived after @@ -574,7 +574,8 @@ class Message(models.Model): tracking_values_list = [] for values in values_list: if 'email_from' not in values: # needed to compute reply_to - values['email_from'] = self._get_default_from() + author_id, email_from = self.env['mail.thread']._message_compute_author(values.get('author_id'), email_from=None, raise_exception=False) + values['email_from'] = email_from if not values.get('message_id'): values['message_id'] = self._get_message_id(values) if 'reply_to' not in values: @@ -833,16 +834,12 @@ class Message(models.Model): for msg in self: if not msg.email_from: continue - if self.env.user.partner_id.email: - email_from = tools.formataddr((self.env.user.partner_id.name, self.env.user.partner_id.email)) - else: - email_from = self.env.company.catchall_formatted - body_html = tools.append_content_to_html('
%s
' % tools.ustr(comment), msg.body, plaintext=False) vals = { 'subject': subject, 'body_html': body_html, - 'email_from': email_from, + 'author_id': self.env.user.partner_id.id, + 'email_from': self.env.user.email_formatted or self.env.company_id.catchall_formatted, 'email_to': msg.email_from, 'auto_delete': True, 'state': 'outgoing' @@ -924,7 +921,7 @@ class Message(models.Model): partner_ids=moderator.partner_id.ids, subject=_('Message are pending moderation'), # tocheck: target language body=template.render({'record': moderator.partner_id}, engine='ir.qweb', minimal_qcontext=True), - email_from=moderator.company_id.catchall_formatted or moderator.company_id.email, + email_from=moderator.company_id.catchall_formatted or moderator.company_id.email_formatted, ) # ------------------------------------------------------ diff --git a/addons/mail/models/mail_thread.py b/addons/mail/models/mail_thread.py index 0c53cbad6b1..d0abc8adab7 100644 --- a/addons/mail/models/mail_thread.py +++ b/addons/mail/models/mail_thread.py @@ -685,6 +685,7 @@ class MailThread(models.AbstractModel): def _routing_create_bounce_email(self, email_from, body_html, message, **mail_values): bounce_to = tools.decode_message_header(message, 'Return-Path') or email_from bounce_mail_values = { + 'author_id': False, 'body_html': body_html, 'subject': 'Re: %s' % message.get('subject'), 'email_to': bounce_to, @@ -693,6 +694,8 @@ class MailThread(models.AbstractModel): bounce_from = self.env['ir.mail_server']._get_default_bounce_address() if bounce_from: bounce_mail_values['email_from'] = tools.formataddr(('MAILER-DAEMON', bounce_from)) + else: + bounce_mail_values['email_from'] = tools.decode_message_header(message, 'To') bounce_mail_values.update(mail_values) self.env['mail.mail'].create(bounce_mail_values).send() diff --git a/addons/mail/wizard/invite.py b/addons/mail/wizard/invite.py index 44a68a92bb9..78bf03dd776 100644 --- a/addons/mail/wizard/invite.py +++ b/addons/mail/wizard/invite.py @@ -5,6 +5,7 @@ from lxml import etree from lxml.html import builder as html from odoo import _, api, fields, models +from odoo.exceptions import UserError class Invite(models.TransientModel): @@ -47,7 +48,9 @@ class Invite(models.TransientModel): send_mail = fields.Boolean('Send Email', default=True, help="If checked, the partners will receive an email warning they have been added in the document's followers.") def add_followers(self): - email_from = self.env['mail.message']._get_default_from() + if not self.env.user.email: + raise UserError(_("Unable to post message, please configure the sender's email address.")) + email_from = self.env.user.email_formatted for wizard in self: Model = self.env[wizard.res_model] document = Model.browse(wizard.res_id) diff --git a/addons/mail/wizard/mail_compose_message.py b/addons/mail/wizard/mail_compose_message.py index 193f7faf38b..d3b0e6f16bf 100644 --- a/addons/mail/wizard/mail_compose_message.py +++ b/addons/mail/wizard/mail_compose_message.py @@ -54,14 +54,14 @@ class MailComposer(models.TransientModel): result = super(MailComposer, self).default_get(fields) # author - if 'author_id' not in result: - result['author_id'] = self.env.user.partner_id.id - if 'email_from' not in result and self.env.user.email: - result['email_from'] = self.env.user.email_formatted - elif 'email_from' not in result: - author = self.env['res.partner'].browse(result['author_id']) - if author.email: - result['email_from'] = tools.formataddr((author.name, author.email)) + missing_author = 'author_id' in fields and 'author_id' not in result + missing_email_from = 'email_from' in fields and 'email_from' not in result + if missing_author or missing_email_from: + author_id, email_from = self.env['mail.thread']._message_compute_author(result.get('author_id'), result.get('email_from'), raise_exception=False) + if missing_email_from: + result['email_from'] = email_from + if missing_author: + result['author_id'] = author_id result['composition_mode'] = result.get('composition_mode', 'comment') result['model'] = result.get('model', self._context.get('active_model')) diff --git a/addons/mass_mailing/models/mailing.py b/addons/mass_mailing/models/mailing.py index cd098b3a347..999b3f824b0 100644 --- a/addons/mass_mailing/models/mailing.py +++ b/addons/mass_mailing/models/mailing.py @@ -69,7 +69,7 @@ class MassMailing(models.Model): active = fields.Boolean(default=True, tracking=True) subject = fields.Char('Subject', help='Subject of emails to send', required=True, translate=True) email_from = fields.Char(string='Send From', required=True, - default=lambda self: self.env['mail.message']._get_default_from()) + default=lambda self: self.env.user.email_formatted) sent_date = fields.Datetime(string='Sent Date', copy=False) schedule_date = fields.Datetime(string='Scheduled for', tracking=True) # don't translate 'body_arch', the translations are only on 'body_html' @@ -92,7 +92,7 @@ class MassMailing(models.Model): reply_to_mode = fields.Selection( [('thread', 'Recipient Followers'), ('email', 'Specified Email Address')], string='Reply-To Mode', required=True) reply_to = fields.Char(string='Reply To', help='Preferred Reply-To Address', - default=lambda self: self.env['mail.message']._get_default_from()) + default=lambda self: self.env.user.email_formatted) # recipients mailing_model_real = fields.Char(compute='_compute_model', string='Recipients Real Model', default='mailing.contact', required=True) mailing_model_id = fields.Many2one('ir.model', string='Recipients Model', domain=[('model', 'in', MASS_MAILING_BUSINESS_MODELS)], diff --git a/addons/mass_mailing/wizard/mailing_mailing_test.py b/addons/mass_mailing/wizard/mailing_mailing_test.py index 54424262563..5aa09a71999 100644 --- a/addons/mass_mailing/wizard/mailing_mailing_test.py +++ b/addons/mass_mailing/wizard/mailing_mailing_test.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. -from odoo import api, fields, models, tools +from odoo import fields, models, tools class TestMassMailing(models.TransientModel): @@ -9,7 +9,7 @@ class TestMassMailing(models.TransientModel): _description = 'Sample Mail Wizard' email_to = fields.Char(string='Recipients', required=True, - help='Comma-separated list of email addresses.', default=lambda self: self.env['mail.message']._get_default_from()) + help='Comma-separated list of email addresses.', default=lambda self: self.env.user.email_formatted) mass_mailing_id = fields.Many2one('mailing.mailing', string='Mailing', required=True, ondelete='cascade') def send_mail_test(self): diff --git a/addons/payment_paypal/models/payment.py b/addons/payment_paypal/models/payment.py index 64afaf6ad7c..40b38c70092 100644 --- a/addons/payment_paypal/models/payment.py +++ b/addons/payment_paypal/models/payment.py @@ -199,7 +199,8 @@ class TxPaypal(models.Model): 'body_html': mail_body, 'subject': _('Add your Paypal account to Odoo'), 'email_to': self.acquirer_id.paypal_email_account, - 'email_from': self.acquirer_id.create_uid.email + 'email_from': self.acquirer_id.create_uid.email_formatted, + 'author_id': self.acquirer_id.create_uid.partner_id.id, } self.env['mail.mail'].sudo().create(mail_values).send() diff --git a/addons/website_slides/models/slide_slide.py b/addons/website_slides/models/slide_slide.py index 0a61291bb2c..9e0730a1abb 100644 --- a/addons/website_slides/models/slide_slide.py +++ b/addons/website_slides/models/slide_slide.py @@ -502,10 +502,18 @@ class Slide(models.Model): mail_ids = [] base_url = self.env['ir.config_parameter'].sudo().get_param('web.base.url') for record in self: + template = self.channel_id.share_template_id.with_context( + user=self.env.user, + email=email, + base_url=base_url, + fullscreen=fullscreen + ) + email_values = {'email_to': email} if self.env.user.has_group('base.group_portal'): - mail_ids.append(self.channel_id.share_template_id.with_context(user=self.env.user, email=email, base_url=base_url, fullscreen=fullscreen).sudo().send_mail(record.id, notif_layout='mail.mail_notification_light', email_values={'email_from': self.env.company.catchall_formatted or self.env.company.email, 'email_to': email})) - else: - mail_ids.append(self.channel_id.share_template_id.with_context(user=self.env.user, email=email, base_url=base_url, fullscreen=fullscreen).send_mail(record.id, notif_layout='mail.mail_notification_light', email_values={'email_to': email})) + template = template.sudo() + email_values['email_from'] = self.env.company.catchall_formatted or self.env.company.email_formatted + + mail_ids.append(template.send_mail(record.id, notif_layout='mail.mail_notification_light', email_values=email_values)) return mail_ids def action_like(self):