From c996efa2fe65e87ef62e4f0f4520ee83ed9ea5cd Mon Sep 17 00:00:00 2001 From: Olivier Dony Date: Fri, 22 Jul 2011 18:34:57 +0200 Subject: [IMP] mail: another pass of cleanup/refactoring of mail features - finish renaming bzr revid: odo@openerp.com-20110722163457-7g9ngdb2p0bixcst --- addons/mail/wizard/mail_compose_message.py | 248 +++++++++++++++++++++++++++++ 1 file changed, 248 insertions(+) create mode 100644 addons/mail/wizard/mail_compose_message.py (limited to 'addons/mail/wizard/mail_compose_message.py') diff --git a/addons/mail/wizard/mail_compose_message.py b/addons/mail/wizard/mail_compose_message.py new file mode 100644 index 00000000000..0cdd5a8b7ba --- /dev/null +++ b/addons/mail/wizard/mail_compose_message.py @@ -0,0 +1,248 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2010-Today OpenERP SA () +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see +# +############################################################################## + +import re + +import tools +from mail.mail_message import to_email +from osv import osv +from osv import fields +from tools.safe_eval import safe_eval as eval +from tools.safe_eval import literal_eval +from tools.translate import _ + +# main mako-like expression pattern +EXPRESSION_PATTERN = re.compile('(\$\{.+?\})') + +class mail_compose_message(osv.osv_memory): + """Generic E-mail composition wizard. This wizard is meant to be inherited + at model and view level to provide specific wizard features. + + The behavior of the wizard can be modified through the use of context + parameters, among which are: + + * mass_mail: turns multi-recipient mode, where the mail details can + contain template placeholders that will be merged with + actual data before being sent to each recipient, as + determined via ``context['active_model']`` and + ``context['active_ids']``. + * mail: if set to 'reply', the wizard will be in mail reply mode + * active_model: model name of the document to which the mail being + composed is related + * active_id: id of the document to which the mail being composed is + related, or id of the message to which user is replying, + in case mail == 'reply'. + * active_ids: ids of the documents to which the mail being composed is + related, in case ``context['mass_mail']`` is set. + """ + _name = 'mail.compose.message' + _inherit = 'mail.message.common' + _description = 'E-mail composition wizard' + + def default_get(self, cr, uid, fields, context=None): + """Overridden to provide specific defaults depending on the context + parameters. + + :param dict context: several context values will modify the behavior + of the wizard, cfr. the class description. + """ + if context is None: + context = {} + result = super(mail_compose_message, self).default_get(cr, uid, fields, context=context) + vals = {} + if context.get('mass_mail'): + return result + if context.get('active_model') and context.get('active_id') and not context.get('mail')=='reply': + vals = self.get_value(cr, uid, context.get('active_model'), context.get('active_id'), context) + elif context.get('mail')=='reply' and context.get('active_id'): + vals = self.get_message_data(cr, uid, int(context['active_id']), context) + else: + result['model'] = context.get('active_model', False) + if not vals: + return result + for field in fields: + result.update({field : vals.get(field, False)}) + return result + + _columns = { + 'attachment_ids': fields.many2many('ir.attachment','email_message_send_attachment_rel', 'wizard_id', 'attachment_id', 'Attachments'), + 'auto_delete': fields.boolean('Auto Delete', help="Permanently delete emails after sending"), + 'filter_id': fields.many2one('ir.filters', 'Filters'), + } + + def get_value(self, cr, uid, model, res_id, context=None): + """Returns a defaults-like dict with initial values for the composition + wizard when sending an email related to the document record identified + by ``model`` and ``res_id``. + + The default implementation returns an empty dictionary, and is meant + to be overridden by subclasses. + + :param str model: model name of the document record this mail is related to. + :param int res_id: id of the document record this mail is related to. + :param dict context: several context values will modify the behavior + of the wizard, cfr. the class description. + """ + return {} + + def get_message_data(self, cr, uid, message_id, context=None): + """Returns a defaults-like dict with initial values for the composition + wizard when replying to the given message (e.g. including the quote + of the initial message, and the correct recipient). + Should not be called unless ``context['mail'] == 'reply'``. + + :param int message_id: id of the mail.message to which the user + is replying. + :param dict context: several context values will modify the behavior + of the wizard, cfr. the class description. + When calling this method, the ``'mail'`` value + in the context should be ``'reply'``. + """ + if context is None: + context = {} + result = {} + mail_message = self.pool.get('mail.message') + if message_id: + message_data = mail_message.browse(cr, uid, message_id, context) + subject = tools.ustr(message_data.subject or '') + # we use the plain text version of the original mail, by default, + # as it is easier to quote than the HTML version. + # XXX TODO: make it possible to switch to HTML on the fly + description = message_data.body_text or '' + if context.get('mail') == 'reply': + header = _('-------- Original Message --------') + sender = _('From: %s') % tools.ustr(message_data.email_from or '') + email_to = _('To: %s') % tools.ustr(message_data.email_to or '') + sentdate = _('Date: %s') % message_data.date + desc = '\n > \t %s' % tools.ustr(description.replace('\n', "\n > \t") or '') + description = '\n'.join([header, sender, email_to, sentdate, desc]) + re_prefix = _("Re:") + if not (subject.startswith('Re:') or subject.startswith(re_prefix)): + subject = "%s %s" % (re_prefix, subject) + result.update({ + 'subtype' : 'plain', # default to the text version due to quoting + 'body_text' : description, + 'subject' : subject, + 'message_id' : message_data.message_id or False, + 'attachment_ids' : [], + 'res_id' : message_data.res_id or False, + 'email_from' : message_data.email_to or False, + 'email_to' : message_data.email_from or False, + 'email_cc' : message_data.email_cc or False, + 'email_bcc' : message_data.email_bcc or False, + 'reply_to' : message_data.reply_to or False, + 'model' : message_data.model or False, + 'user_id' : message_data.user_id and message_data.user_id.id or False, + 'references' : message_data.references and tools.ustr(message_data.references) or False, + 'headers' : message_data.headers or False, + }) + return result + + def send_mail(self, cr, uid, ids, context=None): + '''Process the wizard contents and proceed with sending the corresponding + email(s), rendering any template patterns on the fly if needed. + The resulting email(s) are scheduled for being sent the next time the + mail.message scheduler runs, or the next time + ``mail.message.process_email_queue`` is called. + + :param dict context: several context values will modify the behavior + of the wizard, cfr. the class description. + ''' + if context is None: + context = {} + mail_message = self.pool.get('mail.message') + for mail in self.browse(cr, uid, ids, context=context): + attachment = {} + for attach in mail.attachment_ids: + attachment[attach.datas_fname] = attach.datas + references = False + message_id = False + + # Reply Email + if context.get('mail') == 'reply' and mail.message_id: + references = mail.references and mail.references + "," + mail.message_id or mail.message_id + else: + message_id = mail.message_id + + if context.get('mass_mail'): + # Mass mailing: must render the template patterns + if context.get('active_ids') and context.get('active_model'): + active_ids = context['active_ids'] + active_model = context['active_model'] + else: + active_model = mail.model + active_model_pool = self.pool.get(active_model) + active_ids = active_model_pool.search(cr, uid, literal_eval(mail.filter_id.domain), context=literal_eval(mail.filter_id.context)) + + for active_id in active_ids: + subject = self.render_template(cr, uid, mail.subject, active_model, active_id) + + body = mail.body_html if mail.subtype == 'html' else mail.body_text + body = self.render_template(cr, uid, body, active_model, active_id) + email_from = self.render_template(cr, uid, mail.email_from, active_model, active_id) + email_to = self.render_template(cr, uid, mail.email_to, active_model, active_id) + email_cc = self.render_template(cr, uid, mail.email_cc, active_model, active_id) + email_bcc = self.render_template(cr, uid, mail.email_bcc, active_model, active_id) + reply_to = self.render_template(cr, uid, mail.reply_to, active_model, active_id) + + mail_message.schedule_with_attach(cr, uid, email_from, to_email(email_to), subject, body, + model=mail.model, email_cc=to_email(email_cc), email_bcc=to_email(email_bcc), reply_to=reply_to, + attachments=attachment, message_id=message_id, references=references, res_id=int(mail.res_id), + subtype=mail.subtype, headers=mail.headers, auto_delete=mail.auto_delete, context=context) + else: + # normal mode - no mass-mailing + mail_message.schedule_with_attach(cr, uid, mail.email_from, to_email(mail.email_to), mail.subject, mail.body, + model=mail.model, email_cc=to_email(mail.email_cc), email_bcc=to_email(mail.email_bcc), reply_to=mail.reply_to, + attachments=attachment, message_id=message_id, references=references, res_id=int(mail.res_id), + subtype=mail.subtype, headers=mail.headers, auto_delete=mail.auto_delete, context=context) + + return {'type': 'ir.actions.act_window_close'} + + def render_template(self, cr, uid, template, model, res_id, context=None): + """Render the given template text, replace mako-like expressions ``${expr}`` + with the result of passing these expressions ``through safe_eval()`` with + an evaluation context containing: + + * ``user``: browse_record of the current user + * ``object``: browse_record of the document record this mail is + related to + * ``context``: the context passed to the mail composition wizard + + :param str template: the template text to render + :param str model: model name of the document record this mail is related to. + :param int res_id: id of the document record this mail is related to. + """ + if context is None: + context = {} + def merge(match): + exp = str(match.group()[2:-1]).strip() + result = eval(exp, + { + 'user' : self.pool.get('res.users').browse(cr, uid, uid, context=context), + 'object' : self.pool.get(model).browse(cr, uid, res_id, context=context), + 'context': dict(context), # copy context to prevent side-effects of eval + }) + if result in (None, False): + return "" + return tools.ustr(result) + return template and EXPRESSION_PATTERN.sub(merge, template) + +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: -- cgit v1.2.3 From 8f9f45ea948d1ffecb79601e860d522fc6686c2d Mon Sep 17 00:00:00 2001 From: Olivier Dony Date: Mon, 22 Aug 2011 19:16:59 +0200 Subject: [IMP] all: next pass of review/renaming for new mail API bzr revid: odo@openerp.com-20110822171659-zxho36a6n628i10q --- addons/mail/wizard/mail_compose_message.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'addons/mail/wizard/mail_compose_message.py') diff --git a/addons/mail/wizard/mail_compose_message.py b/addons/mail/wizard/mail_compose_message.py index 0cdd5a8b7ba..b92db46857d 100644 --- a/addons/mail/wizard/mail_compose_message.py +++ b/addons/mail/wizard/mail_compose_message.py @@ -218,8 +218,8 @@ class mail_compose_message(osv.osv_memory): def render_template(self, cr, uid, template, model, res_id, context=None): """Render the given template text, replace mako-like expressions ``${expr}`` - with the result of passing these expressions ``through safe_eval()`` with - an evaluation context containing: + with the result of evaluating these expressions with an evaluation context + containing: * ``user``: browse_record of the current user * ``object``: browse_record of the document record this mail is -- cgit v1.2.3 From b0bed63351956455a23cdc960292e104af53f67a Mon Sep 17 00:00:00 2001 From: Olivier Dony Date: Tue, 23 Aug 2011 19:58:09 +0200 Subject: [IMP] mail.thread: renaming methods to avoid collisions with objects that use the mixin bzr revid: odo@openerp.com-20110823175809-hw81fkptg90702vh --- addons/mail/wizard/mail_compose_message.py | 67 +++++++++++++++++------------- 1 file changed, 37 insertions(+), 30 deletions(-) (limited to 'addons/mail/wizard/mail_compose_message.py') diff --git a/addons/mail/wizard/mail_compose_message.py b/addons/mail/wizard/mail_compose_message.py index b92db46857d..9179af2a009 100644 --- a/addons/mail/wizard/mail_compose_message.py +++ b/addons/mail/wizard/mail_compose_message.py @@ -126,42 +126,46 @@ class mail_compose_message(osv.osv_memory): # we use the plain text version of the original mail, by default, # as it is easier to quote than the HTML version. # XXX TODO: make it possible to switch to HTML on the fly - description = message_data.body_text or '' + body = message_data.body_text or '' if context.get('mail') == 'reply': header = _('-------- Original Message --------') sender = _('From: %s') % tools.ustr(message_data.email_from or '') email_to = _('To: %s') % tools.ustr(message_data.email_to or '') - sentdate = _('Date: %s') % message_data.date - desc = '\n > \t %s' % tools.ustr(description.replace('\n', "\n > \t") or '') - description = '\n'.join([header, sender, email_to, sentdate, desc]) + sentdate = _('Date: %s') % message_data.date if message_data.date else '' + quoted_body = '> \n> %s' % tools.ustr(body.replace('\n', "\n> ") or '') + body = '\n'.join(filter(None, ["\n", header, sender, email_to, sentdate, + quoted_body])) re_prefix = _("Re:") if not (subject.startswith('Re:') or subject.startswith(re_prefix)): subject = "%s %s" % (re_prefix, subject) + current_user = self.pool.get('res.users').browse(cr, uid, uid, context) result.update({ 'subtype' : 'plain', # default to the text version due to quoting - 'body_text' : description, + 'body_text' : body, 'subject' : subject, - 'message_id' : message_data.message_id or False, 'attachment_ids' : [], + 'model' : message_data.model or False, 'res_id' : message_data.res_id or False, - 'email_from' : message_data.email_to or False, - 'email_to' : message_data.email_from or False, + 'email_from' : current_user.user_email or message_data.email_to or False, + 'email_to' : message_data.reply_to or message_data.email_from or False, 'email_cc' : message_data.email_cc or False, - 'email_bcc' : message_data.email_bcc or False, - 'reply_to' : message_data.reply_to or False, - 'model' : message_data.model or False, - 'user_id' : message_data.user_id and message_data.user_id.id or False, + 'user_id' : uid, + + # pass msg-id and references of mail we're replying to, to construct the + # new ones later when sending + 'message_id' : message_data.message_id or False, 'references' : message_data.references and tools.ustr(message_data.references) or False, - 'headers' : message_data.headers or False, }) return result def send_mail(self, cr, uid, ids, context=None): '''Process the wizard contents and proceed with sending the corresponding email(s), rendering any template patterns on the fly if needed. - The resulting email(s) are scheduled for being sent the next time the - mail.message scheduler runs, or the next time + If the wizard is in mass-mail mode (context has a ``mass_mail`` key), + the resulting email(s) are scheduled for being sent the next time + the mail.message scheduler runs, or the next time ``mail.message.process_email_queue`` is called. + Otherwise the new message is sent immediately. :param dict context: several context values will modify the behavior of the wizard, cfr. the class description. @@ -173,14 +177,15 @@ class mail_compose_message(osv.osv_memory): attachment = {} for attach in mail.attachment_ids: attachment[attach.datas_fname] = attach.datas - references = False - message_id = False + references = None + headers = {} + + body = mail.body_html if mail.subtype == 'html' else mail.body_text # Reply Email - if context.get('mail') == 'reply' and mail.message_id: - references = mail.references and mail.references + "," + mail.message_id or mail.message_id - else: - message_id = mail.message_id + if context.get('mail') == 'reply' and mail.message_id: + references = (mail.references or '') + " " + mail.message_id + headers['In-Reply-To'] = mail.message_id if context.get('mass_mail'): # Mass mailing: must render the template patterns @@ -194,25 +199,27 @@ class mail_compose_message(osv.osv_memory): for active_id in active_ids: subject = self.render_template(cr, uid, mail.subject, active_model, active_id) - - body = mail.body_html if mail.subtype == 'html' else mail.body_text - body = self.render_template(cr, uid, body, active_model, active_id) + rendered_body = self.render_template(cr, uid, body, active_model, active_id) email_from = self.render_template(cr, uid, mail.email_from, active_model, active_id) email_to = self.render_template(cr, uid, mail.email_to, active_model, active_id) email_cc = self.render_template(cr, uid, mail.email_cc, active_model, active_id) email_bcc = self.render_template(cr, uid, mail.email_bcc, active_model, active_id) reply_to = self.render_template(cr, uid, mail.reply_to, active_model, active_id) - mail_message.schedule_with_attach(cr, uid, email_from, to_email(email_to), subject, body, + # in mass-mailing mode we only schedule the mail for sending, it will be + # processed as soon as the mail scheduler runs. + mail_message.schedule_with_attach(cr, uid, email_from, to_email(email_to), subject, rendered_body, model=mail.model, email_cc=to_email(email_cc), email_bcc=to_email(email_bcc), reply_to=reply_to, - attachments=attachment, message_id=message_id, references=references, res_id=int(mail.res_id), - subtype=mail.subtype, headers=mail.headers, auto_delete=mail.auto_delete, context=context) + attachments=attachment, references=references, res_id=int(mail.res_id), + subtype=mail.subtype, headers=headers, context=context) else: # normal mode - no mass-mailing - mail_message.schedule_with_attach(cr, uid, mail.email_from, to_email(mail.email_to), mail.subject, mail.body, + msg_id = mail_message.schedule_with_attach(cr, uid, mail.email_from, to_email(mail.email_to), mail.subject, body, model=mail.model, email_cc=to_email(mail.email_cc), email_bcc=to_email(mail.email_bcc), reply_to=mail.reply_to, - attachments=attachment, message_id=message_id, references=references, res_id=int(mail.res_id), - subtype=mail.subtype, headers=mail.headers, auto_delete=mail.auto_delete, context=context) + attachments=attachment, references=references, res_id=int(mail.res_id), + subtype=mail.subtype, headers=headers, context=context) + # in normal mode, we send the email immediately, as the user expects us to (delay should be sufficiently small) + mail_message.send(cr, uid, [msg_id], context) return {'type': 'ir.actions.act_window_close'} -- cgit v1.2.3 From e9d94b824eee6970bf3263d7d0fd3208a3b0f037 Mon Sep 17 00:00:00 2001 From: Olivier Dony Date: Tue, 6 Sep 2011 10:00:14 +0200 Subject: [IMP]: crm,mail: minor fixes after review bzr revid: odo@openerp.com-20110906080014-6texz097jepfrwsp --- addons/mail/wizard/mail_compose_message.py | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) (limited to 'addons/mail/wizard/mail_compose_message.py') diff --git a/addons/mail/wizard/mail_compose_message.py b/addons/mail/wizard/mail_compose_message.py index 9179af2a009..6d40ef13e80 100644 --- a/addons/mail/wizard/mail_compose_message.py +++ b/addons/mail/wizard/mail_compose_message.py @@ -39,7 +39,7 @@ class mail_compose_message(osv.osv_memory): The behavior of the wizard can be modified through the use of context parameters, among which are: - * mass_mail: turns multi-recipient mode, where the mail details can + * mass_mail: turns multi-recipient mode on, where the mail details can contain template placeholders that will be merged with actual data before being sent to each recipient, as determined via ``context['active_model']`` and @@ -68,18 +68,19 @@ class mail_compose_message(osv.osv_memory): context = {} result = super(mail_compose_message, self).default_get(cr, uid, fields, context=context) vals = {} - if context.get('mass_mail'): - return result - if context.get('active_model') and context.get('active_id') and not context.get('mail')=='reply': + if context.get('active_model') and context.get('active_id') and not context.get('mail') == 'reply': vals = self.get_value(cr, uid, context.get('active_model'), context.get('active_id'), context) - elif context.get('mail')=='reply' and context.get('active_id'): + elif context.get('mail') == 'reply' and context.get('active_id'): vals = self.get_message_data(cr, uid, int(context['active_id']), context) else: result['model'] = context.get('active_model', False) - if not vals: - return result - for field in fields: - result.update({field : vals.get(field, False)}) + if vals: + for field in fields: + result.update({field : vals.get(field, False)}) + # Try to provide default email_from if not specified yet + if not result.get('email_from'): + current_user = self.pool.get('res.users').browse(cr, uid, uid, context) + result['email_from'] = current_user.user_email or False return result _columns = { -- cgit v1.2.3 From 1db8e54425bd72477d67e77c62a160b405370f09 Mon Sep 17 00:00:00 2001 From: Olivier Dony Date: Tue, 6 Sep 2011 11:32:28 +0200 Subject: [IMP] all: unified context params for mail composition wizard A single common `mail.compose.message.mode` key is now used in the context, avoiding name collisions and being more consistent. bzr revid: odo@openerp.com-20110906093228-itbilwzpv4wl07j9 --- addons/mail/wizard/mail_compose_message.py | 40 ++++++++++++++++++------------ 1 file changed, 24 insertions(+), 16 deletions(-) (limited to 'addons/mail/wizard/mail_compose_message.py') diff --git a/addons/mail/wizard/mail_compose_message.py b/addons/mail/wizard/mail_compose_message.py index 6d40ef13e80..5deabd3cddf 100644 --- a/addons/mail/wizard/mail_compose_message.py +++ b/addons/mail/wizard/mail_compose_message.py @@ -39,19 +39,21 @@ class mail_compose_message(osv.osv_memory): The behavior of the wizard can be modified through the use of context parameters, among which are: - * mass_mail: turns multi-recipient mode on, where the mail details can - contain template placeholders that will be merged with - actual data before being sent to each recipient, as - determined via ``context['active_model']`` and + * mail.compose.message.mode: if set to 'reply', the wizard is in + reply mode and pre-populated with the original quote. + If set to 'mass_mail', the wizard is in mass mailing + where the mail details can contain template placeholders + that will be merged with actual data before being sent + to each recipient. Recipients will be derived from the + records determined via ``context['active_model']`` and ``context['active_ids']``. - * mail: if set to 'reply', the wizard will be in mail reply mode * active_model: model name of the document to which the mail being composed is related * active_id: id of the document to which the mail being composed is related, or id of the message to which user is replying, - in case mail == 'reply'. + in case ``mail.compose.message.mode == 'reply'`` * active_ids: ids of the documents to which the mail being composed is - related, in case ``context['mass_mail']`` is set. + related, in case ``mail.compose.message.mode == 'mass_mail'``. """ _name = 'mail.compose.message' _inherit = 'mail.message.common' @@ -68,11 +70,17 @@ class mail_compose_message(osv.osv_memory): context = {} result = super(mail_compose_message, self).default_get(cr, uid, fields, context=context) vals = {} - if context.get('active_model') and context.get('active_id') and not context.get('mail') == 'reply': + reply_mode = context.get('mail.compose.message.mode') == 'reply' + if (not reply_mode) and context.get('active_model') and context.get('active_id'): + # normal mode when sending an email related to any document, as specified by + # active_model and active_id in context vals = self.get_value(cr, uid, context.get('active_model'), context.get('active_id'), context) - elif context.get('mail') == 'reply' and context.get('active_id'): + elif reply_mode and context.get('active_id'): + # reply mode, consider active_id is the ID of a mail.message to which we're + # replying vals = self.get_message_data(cr, uid, int(context['active_id']), context) else: + # default mode result['model'] = context.get('active_model', False) if vals: for field in fields: @@ -108,7 +116,7 @@ class mail_compose_message(osv.osv_memory): """Returns a defaults-like dict with initial values for the composition wizard when replying to the given message (e.g. including the quote of the initial message, and the correct recipient). - Should not be called unless ``context['mail'] == 'reply'``. + Should not be called unless ``context['mail.compose.message.mode'] == 'reply'``. :param int message_id: id of the mail.message to which the user is replying. @@ -128,7 +136,7 @@ class mail_compose_message(osv.osv_memory): # as it is easier to quote than the HTML version. # XXX TODO: make it possible to switch to HTML on the fly body = message_data.body_text or '' - if context.get('mail') == 'reply': + if context.get('mail.compose.message.mode') == 'reply': header = _('-------- Original Message --------') sender = _('From: %s') % tools.ustr(message_data.email_from or '') email_to = _('To: %s') % tools.ustr(message_data.email_to or '') @@ -162,9 +170,9 @@ class mail_compose_message(osv.osv_memory): def send_mail(self, cr, uid, ids, context=None): '''Process the wizard contents and proceed with sending the corresponding email(s), rendering any template patterns on the fly if needed. - If the wizard is in mass-mail mode (context has a ``mass_mail`` key), - the resulting email(s) are scheduled for being sent the next time - the mail.message scheduler runs, or the next time + If the wizard is in mass-mail mode (context['mail.compose.message.mode'] is + set to ``'mass_mail'``), the resulting email(s) are scheduled for being + sent the next time the mail.message scheduler runs, or the next time ``mail.message.process_email_queue`` is called. Otherwise the new message is sent immediately. @@ -184,11 +192,11 @@ class mail_compose_message(osv.osv_memory): body = mail.body_html if mail.subtype == 'html' else mail.body_text # Reply Email - if context.get('mail') == 'reply' and mail.message_id: + if context.get('mail.compose.message.mode') == 'reply' and mail.message_id: references = (mail.references or '') + " " + mail.message_id headers['In-Reply-To'] = mail.message_id - if context.get('mass_mail'): + if context.get('mail.compose.message.mode') == 'mass_mail': # Mass mailing: must render the template patterns if context.get('active_ids') and context.get('active_model'): active_ids = context['active_ids'] -- cgit v1.2.3 From 2e91821bbfa22b564b3ebac046ae7f7ff8cd8e06 Mon Sep 17 00:00:00 2001 From: Olivier Dony Date: Wed, 7 Sep 2011 18:00:21 +0200 Subject: [IMP] mail.compose.message: simpler quoting layout for replies bzr revid: odo@openerp.com-20110907160021-qabhrrei2vw3ycdp --- addons/mail/wizard/mail_compose_message.py | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) (limited to 'addons/mail/wizard/mail_compose_message.py') diff --git a/addons/mail/wizard/mail_compose_message.py b/addons/mail/wizard/mail_compose_message.py index 5deabd3cddf..eb9ca6680fa 100644 --- a/addons/mail/wizard/mail_compose_message.py +++ b/addons/mail/wizard/mail_compose_message.py @@ -135,19 +135,17 @@ class mail_compose_message(osv.osv_memory): # we use the plain text version of the original mail, by default, # as it is easier to quote than the HTML version. # XXX TODO: make it possible to switch to HTML on the fly - body = message_data.body_text or '' + current_user = self.pool.get('res.users').browse(cr, uid, uid, context) + body = message_data.body_text or current_user.signature if context.get('mail.compose.message.mode') == 'reply': - header = _('-------- Original Message --------') - sender = _('From: %s') % tools.ustr(message_data.email_from or '') - email_to = _('To: %s') % tools.ustr(message_data.email_to or '') - sentdate = _('Date: %s') % message_data.date if message_data.date else '' - quoted_body = '> \n> %s' % tools.ustr(body.replace('\n', "\n> ") or '') - body = '\n'.join(filter(None, ["\n", header, sender, email_to, sentdate, - quoted_body])) + sent_date = _('On %(date)s, ') % {'date': message_data.date} if message_data.date else '' + sender = _('%(sender_name)s wrote:') % {'sender_name': tools.ustr(message_data.email_from or _('You'))} + quoted_body = '> %s' % tools.ustr(body.replace('\n', "\n> ") or '') + body = '\n'.join(["\n", (sent_date + sender), quoted_body]) + body += "\n" + current_user.signature re_prefix = _("Re:") if not (subject.startswith('Re:') or subject.startswith(re_prefix)): subject = "%s %s" % (re_prefix, subject) - current_user = self.pool.get('res.users').browse(cr, uid, uid, context) result.update({ 'subtype' : 'plain', # default to the text version due to quoting 'body_text' : body, -- cgit v1.2.3 From 186a66ba2d2a4249702307605a9a9436d629245a Mon Sep 17 00:00:00 2001 From: Olivier Dony Date: Fri, 9 Sep 2011 17:55:17 +0200 Subject: [IMP] mail: more robust model/record passing bzr revid: odo@openerp.com-20110909155517-0jhk34b0ka2azxgs --- addons/mail/wizard/mail_compose_message.py | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'addons/mail/wizard/mail_compose_message.py') diff --git a/addons/mail/wizard/mail_compose_message.py b/addons/mail/wizard/mail_compose_message.py index eb9ca6680fa..0bfaf06890a 100644 --- a/addons/mail/wizard/mail_compose_message.py +++ b/addons/mail/wizard/mail_compose_message.py @@ -85,6 +85,16 @@ class mail_compose_message(osv.osv_memory): if vals: for field in fields: result.update({field : vals.get(field, False)}) + + # link to model and record if not done yet + if not result.get('model') or not result.get('res_id'): + active_model = context.get('active_model') + res_id = context.get('active_id') + if active_model and active_model not in (self._name, 'mail.message'): + result['model'] = active_model + if res_id: + result['res_id'] = res_id + # Try to provide default email_from if not specified yet if not result.get('email_from'): current_user = self.pool.get('res.users').browse(cr, uid, uid, context) -- cgit v1.2.3