From: Thibault Delavallée Date: Wed, 29 Aug 2012 15:00:02 +0000 (+0200) Subject: [REF] mail_mail: cool and clean refactoring of the models. X-Git-Tag: 7.0-server~2197^2~69 X-Git-Url: http://git.inspyration.org/?a=commitdiff_plain;h=9b6379462be8fd0fc2ec3e3565ccb5b778e6c6bf;p=odoo%2Fodoo.git [REF] mail_mail: cool and clean refactoring of the models. Removed body_html and content_subtype fields. We now entirely rely on the body field, that holds sanitized HTML. Added a user_signature field from email_template. mail_mail.send() is now responsible of adding the signature on emails. mail_notification.notify() sets the user_signature flag on emails send for notifciations. mail_mail.send() is responsible of adding a default subject on emails send if there is no subject on the mail.message, and res_id and model are set. purchase_requisition: removed an override of mail.message schedule_with_attach. bzr revid: tde@openerp.com-20120829150002-v8t581oesnw0rhvl --- diff --git a/addons/mail/mail_followers.py b/addons/mail/mail_followers.py index d0444a3..255b6d5 100644 --- a/addons/mail/mail_followers.py +++ b/addons/mail/mail_followers.py @@ -84,11 +84,20 @@ class mail_notification(osv.Model): def notify(self, cr, uid, partner_ids, msg_id, context=None): """ Send by email the notification depending on the user preferences """ context = context or {} + # mail_noemail (do not send email) or no partner_ids: do not send, return + if context.get('mail_noemail') or not partner_ids: + return True + mail_mail_obj = self.pool.get('mail.mail') msg_obj = self.pool.get('mail.message') msg = msg_obj.browse(cr, uid, msg_id, context=context) - towrite = self.notify_get_notif_email_dict(cr, uid, msg, context=context) + towrite = { + 'mail_message_id': msg.id, + 'email_to': [], + 'user_signature': True, + 'auto_delete': True, + } for partner in self.pool.get('res.partner').browse(cr, uid, partner_ids, context=context): # Do not send an email to the writer @@ -97,34 +106,14 @@ class mail_notification(osv.Model): # Partner does not want to receive any emails if partner.notification_email_send=='none' or not partner.email: continue - # Partners want to receive only emails and comments + # Partner want to receive only emails and comments if partner.notification_email_send=='comment' and msg.type not in ('email','comment'): continue - towrite['state'] = 'outgoing' if partner.email not in towrite['email_to']: towrite['email_to'].append(partner.email) + towrite['email_to'] = ', '.join(towrite['email_to']) - if towrite.get('state') and not context.get('mail_noemail'): - towrite['message_id'] = msg.id - towrite['email_to'] = ', '.join(towrite['email_to']) - - email_notif_id = mail_mail_obj.create(cr, uid, towrite, context=context) - mail_mail_obj.send(cr, uid, [email_notif_id], context=context) - + email_notif_id = mail_mail_obj.create(cr, uid, towrite, context=context) + mail_mail_obj.send(cr, uid, [email_notif_id], context=context) return True - - def notify_get_notif_email_dict(self, cr, uid, msg, context=None): - """ Return the content of the email send for notification. - :param message: browse record on source mail.message - """ - subject = msg.subject or '%s posted a comment on %s' % (msg.author_id.name, msg.record_name) - body = msg.body or '' - author_signature = msg.author_id.user_ids[0].signature - if author_signature: - body += '
%s
' % (author_signature) - return { - 'email_to': [], - 'subject': subject, - 'body': body, - } diff --git a/addons/mail/mail_mail.py b/addons/mail/mail_mail.py index ebfd19e..50b5b4c 100644 --- a/addons/mail/mail_mail.py +++ b/addons/mail/mail_mail.py @@ -26,6 +26,7 @@ import tools from osv import osv from osv import fields +from tools.translate import _ _logger = logging.getLogger(__name__) @@ -50,29 +51,27 @@ class mail_mail(osv.Model): ], 'Status', readonly=True), 'auto_delete': fields.boolean('Auto Delete', help="Permanently delete this email after sending it, to save space"), + 'user_signature': fields.boolean('Add Signature', + help="If checked, the user's signature will be appended to the text version of the message"), 'references': fields.text('References', help='Message references, such as identifiers of previous messages', readonly=1), 'email_from': fields.char('From', size=128, help='Message sender, taken from user preferences.'), 'email_to': fields.text('To', help='Message recipients'), 'email_cc': fields.char('Cc', size=256, help='Carbon copy message recipients'), 'reply_to':fields.char('Reply-To', size=256, help='Preferred response address for the message'), - - 'content_subtype': fields.char('Message content subtype', size=32, - oldname="subtype", readonly=1, - help="Type of message, usually 'html' or 'plain', used to select "\ - "plain-text or rich-text contents accordingly"), - 'body_html': fields.text('Rich-text Contents', help="Rich-text/HTML version of the message"), } - def _get_default_from(self, cr, uid, context={}): + def _get_default_from(self, cr, uid, context=None): cur = self.pool.get('res.users').browse(cr, uid, uid, context=context) if not cur.alias_domain: - raise osv.except_osv(_('Invalid Action!'), _('Unable to send email, set an alias domain in your server settings.')) + # TDE temp: impossible to install social module, because mail.group tries to send emails ... + # raise osv.except_osv(_('Invalid Action!'), _('Unable to send email, set an alias domain in your server settings.')) + pass return cur.alias_name + '@' + cur.alias_domain _defaults = { 'state': 'outgoing', - 'content_subtype': 'plain', - 'email_from': _get_default_from + 'email_from': lambda self, cr, uid, ctx=None: self._get_default_from(cr, uid, ctx), + 'user_signature': False, } def mark_outgoing(self, cr, uid, ids, context=None): @@ -144,50 +143,53 @@ class mail_mail(osv.Model): :return: True """ ir_mail_server = self.pool.get('ir.mail_server') - self.write(cr, uid, ids, {'state': 'outgoing'}, context=context) for message in self.browse(cr, uid, ids, context=context): try: + body = message.body + + # handle attachments attachments = [] for attach in message.attachment_ids: attachments.append((attach.datas_fname, base64.b64decode(attach.datas))) - body = message.body_html if message.content_subtype == 'html' else message.body - body_alternative = None - content_subtype_alternative = None - if message.content_subtype == 'html': - # we have a plain text alternative prepared, pass it to - # build_message instead of letting it build one - body_alternative = tools.html2plaintext(message.body) - content_subtype_alternative = 'plain' - - # handle destination_partners - partner_ids_email_to = '' - for partner in message.partner_ids: - partner_ids_email_to += '%s ' % (partner.email or '') - message_email_to = '%s %s' % (partner_ids_email_to, message.email_to or '') + # add signature if flag set + if message.user_signature: + signature = message.author_id and message.author_id.user_ids[0].signature or '' + insertion_point = body.find('') + body = body[:insertion_point] + signature + body[:insertion_point] + + # no subject, res_id, model: ' posted on ' + if not message.subject and message.model and message.res_id: + subject = '%s posted on %s' % (message.author_id.name, message.record_name) + else: + subject = message.subject + + # use only sanitized html and set its plaintexted version as alternative + body_alternative = tools.html2plaintext(body) + content_subtype_alternative = 'plain' # build an RFC2822 email.message.Message object and send it # without queuing msg = ir_mail_server.build_email( - email_from=message.email_from, - email_to=tools.email_split(message_email_to), - subject=message.subject, - body=body, - body_alternative=body_alternative, - email_cc=tools.email_split(message.email_cc), - reply_to=message.reply_to, - attachments=attachments, message_id=message.message_id, + subject = subject, + body = body, + body_alternative = body_alternative, + email_from = message.email_from, + email_to = tools.email_split(message.email_to), + email_cc = tools.email_split(message.email_cc), + reply_to = message.reply_to, + attachments = attachments, + message_id = message.message_id, references = message.references, - object_id=message.res_id and ('%s-%s' % (message.res_id,message.model)), - subtype=message.content_subtype, - subtype_alternative=content_subtype_alternative) + object_id = message.res_id and ('%s-%s' % (message.res_id,message.model)), + subtype = 'html', + subtype_alternative = content_subtype_alternative) res = ir_mail_server.send_email(cr, uid, msg, - mail_server_id=message.mail_server_id.id, - context=context) + mail_server_id=message.mail_server_id.id, context=context) if res: - message.write({'state':'sent', 'message_id': res, 'email_to': message_email_to}) + message.write({'state':'sent', 'message_id': res}) else: - message.write({'state':'exception', 'email_to': message_email_to}) + message.write({'state':'exception'}) message.refresh() if message.state == 'sent': self._postprocess_sent_message(cr, uid, message, context=context) @@ -198,4 +200,3 @@ class mail_mail(osv.Model): if auto_commit == True: cr.commit() return True - diff --git a/addons/mail/mail_mail_view.xml b/addons/mail/mail_mail_view.xml index 3abe0b1..9f8a341 100644 --- a/addons/mail/mail_mail_view.xml +++ b/addons/mail/mail_mail_view.xml @@ -29,10 +29,7 @@ - - - - + @@ -41,7 +38,6 @@ - diff --git a/addons/mail/mail_message.py b/addons/mail/mail_message.py index 2cd22aa..6c47e00 100644 --- a/addons/mail/mail_message.py +++ b/addons/mail/mail_message.py @@ -125,7 +125,7 @@ class mail_message(osv.Model): 'subject': fields.char('Subject'), 'date': fields.datetime('Date'), 'message_id': fields.char('Message-Id', help='Message unique identifier', select=1, readonly=1), - 'body': fields.html('Content'), + 'body': fields.html('Contents', help='Automatically sanitized HTML contents'), 'unread': fields.function(_get_unread, fnct_search=_search_unread, type='boolean', string='Unread', help='Functional field to search for unread messages linked to uid'), diff --git a/addons/mail/wizard/mail_compose_message.py b/addons/mail/wizard/mail_compose_message.py index e4b1d01..96ce253 100644 --- a/addons/mail/wizard/mail_compose_message.py +++ b/addons/mail/wizard/mail_compose_message.py @@ -241,7 +241,7 @@ class mail_compose_message(osv.TransientModel): active_model = context.get('default_model', False) active_model_pool = self.pool.get(active_model) subject = self.render_template(cr, uid, subject, active_model, active_id) - body = self.render_template(cr, uid, wizard.body_html, active_model, active_id) + body = self.render_template(cr, uid, wizard.body, active_model, active_id) # TODO TDE: find partner_ids # if email_to: find or create a partner diff --git a/addons/purchase_requisition/purchase_requisition.py b/addons/purchase_requisition/purchase_requisition.py index f8d7741..90a5244 100644 --- a/addons/purchase_requisition/purchase_requisition.py +++ b/addons/purchase_requisition/purchase_requisition.py @@ -194,27 +194,6 @@ class purchase_requisition(osv.osv): purchase_requisition() -class mail_message(osv.osv): - _inherit = 'mail.message' - - def schedule_with_attach(self, cr, uid, email_from, email_to, subject, body, model=False, email_cc=None, - email_bcc=None, reply_to=False, attachments=None, message_id=False, references=False, - res_id=False, content_subtype='plain', headers=None, mail_server_id=False, auto_delete=False, - context=None): - result = super(mail_message, self).schedule_with_attach(cr, uid, email_from, email_to, subject, body, model=model, email_cc=email_cc, - email_bcc=email_bcc, reply_to=reply_to, attachments=attachments, message_id=message_id, references=references, - res_id=res_id, content_subtype=content_subtype, headers=headers, mail_server_id=mail_server_id, auto_delete=auto_delete, - context=context) - # check model is purchase.order - if model and model == 'purchase.order' and res_id: - requisition_id = self.pool.get('purchase.order').browse(cr, uid, res_id, context=context).requisition_id - if requisition_id: - result = self.schedule_with_attach(cr, uid, email_from, email_to, subject, body, model='purchase.requisition', email_cc=email_cc, - email_bcc=email_bcc, reply_to=reply_to, attachments=attachments, message_id=message_id, references=references, - res_id=requisition_id.id, content_subtype=content_subtype, headers=headers, mail_server_id=mail_server_id, auto_delete=auto_delete, - context=context) - return result - class purchase_requisition_line(osv.osv): _name = "purchase.requisition.line"