[MERGE] [FIX] mail, email_template: various fixes
- [FIX] [IMP] mail_thread: allow to use message_post on models not having message_post method defined. mail_compose_message.send() wizard and mail_thread.message_process() now check that the active model has message_post defined. Otherwise using thread_model context key, it is possible to use mail_thread.message_post() while keeping model and res_id on the created mail_message. - [FIX] [TESTS] mail_message, mail_mail: fixed reply_to and email_from default / specified values + added tests (mostly backported from trunk) - [IMP] mail_message, mail_followers: _notify now have 2 new arguments force_send and user_signature. force_send allows to immediately send the notification emails. user_signature tells whether to add the author's signature in the notification emails sent. - [FIX] mail_message: notified people: when having no subtype, just avoid notifying the followers but take into account specified recipients (partner_ids). - [FIX] mail_mail: removed duplicate field email_from, as it is already defined on mail_message (mail_mail inherits from mail_message). - [IMP] mail_mail: no need to search on type = email in list view. - [FIX] email_template: allow to add a context action even without having create access on ir.values and ir.action by using SUPERUSER_ID. - [FIX] mail_compose_message: support user_signature of template. Note that in case of multiple wizards (having ids), user_signature=False on one template is used for all wizards. - [FIX] mass mailing: emails due to mass mailing are not queued instead of sent immediately. - [IMP] Chatter: better display of recipients when having a message_post due to mass mailing (not always displaying logged a note). bzr revid: tde@openerp.com-20130607101641-5h6z2707tu0f3i2n
This commit is contained in:
commit
a16e1a8ba1
|
@ -24,6 +24,7 @@ import base64
|
|||
import logging
|
||||
|
||||
import openerp
|
||||
from openerp import SUPERUSER_ID
|
||||
from openerp.osv import osv, fields
|
||||
from openerp.osv import fields
|
||||
from openerp import tools
|
||||
|
@ -199,7 +200,7 @@ class email_template(osv.osv):
|
|||
model_data_id = data_obj._get_id(cr, uid, 'mail', 'email_compose_message_wizard_form')
|
||||
res_id = data_obj.browse(cr, uid, model_data_id, context=context).res_id
|
||||
button_name = _('Send Mail (%s)') % template.name
|
||||
vals['ref_ir_act_window'] = action_obj.create(cr, uid, {
|
||||
vals['ref_ir_act_window'] = action_obj.create(cr, SUPERUSER_ID, {
|
||||
'name': button_name,
|
||||
'type': 'ir.actions.act_window',
|
||||
'res_model': 'mail.compose.message',
|
||||
|
@ -211,7 +212,7 @@ class email_template(osv.osv):
|
|||
'target': 'new',
|
||||
'auto_refresh':1
|
||||
}, context)
|
||||
vals['ref_ir_value'] = self.pool.get('ir.values').create(cr, uid, {
|
||||
vals['ref_ir_value'] = self.pool.get('ir.values').create(cr, SUPERUSER_ID, {
|
||||
'name': button_name,
|
||||
'model': src_obj,
|
||||
'key2': 'client_action_multi',
|
||||
|
|
|
@ -54,18 +54,22 @@ class mail_compose_message(osv.TransientModel):
|
|||
Indeed, basic mail.compose.message wizard duplicates attachments in mass
|
||||
mailing mode. But in 'single post' mode, attachments of an email template
|
||||
also have to be duplicated to avoid changing their ownership. """
|
||||
if context is None:
|
||||
context = {}
|
||||
wizard_context = dict(context)
|
||||
for wizard in self.browse(cr, uid, ids, context=context):
|
||||
if wizard.template_id and not wizard.template_id.user_signature:
|
||||
wizard_context['mail_notify_user_signature'] = False # template user_signature is added when generating body_html
|
||||
if not wizard.attachment_ids or wizard.composition_mode == 'mass_mail' or not wizard.template_id:
|
||||
continue
|
||||
template = self.pool.get('email.template').browse(cr, uid, wizard.template_id.id, context=context)
|
||||
new_attachment_ids = []
|
||||
for attachment in wizard.attachment_ids:
|
||||
if attachment in template.attachment_ids:
|
||||
if attachment in wizard.template_id.attachment_ids:
|
||||
new_attachment_ids.append(self.pool.get('ir.attachment').copy(cr, uid, attachment.id, {'res_model': 'mail.compose.message', 'res_id': wizard.id}, context=context))
|
||||
else:
|
||||
new_attachment_ids.append(attachment.id)
|
||||
self.write(cr, uid, wizard.id, {'attachment_ids': [(6, 0, new_attachment_ids)]}, context=context)
|
||||
return super(mail_compose_message, self).send_mail(cr, uid, ids, context=context)
|
||||
return super(mail_compose_message, self).send_mail(cr, uid, ids, context=wizard_context)
|
||||
|
||||
def onchange_template_id(self, cr, uid, ids, template_id, composition_mode, model, res_id, context=None):
|
||||
""" - mass_mailing: we cannot render, so return the template values
|
||||
|
|
|
@ -150,11 +150,17 @@ class mail_notification(osv.Model):
|
|||
|
||||
return footer
|
||||
|
||||
def _notify(self, cr, uid, msg_id, partners_to_notify=None, context=None):
|
||||
def _notify(self, cr, uid, msg_id, partners_to_notify=None, context=None,
|
||||
force_send=False, user_signature=True):
|
||||
""" Send by email the notification depending on the user preferences
|
||||
|
||||
:param list partners_to_notify: optional list of partner ids restricting
|
||||
the notifications to process
|
||||
:param bool force_send: if True, the generated mail.mail is
|
||||
immediately sent after being created, as if the scheduler
|
||||
was executed for this message only.
|
||||
:param bool user_signature: if True, the generated mail.mail body is
|
||||
the body of the related mail.message with the author's signature
|
||||
"""
|
||||
if context is None:
|
||||
context = {}
|
||||
|
@ -189,8 +195,9 @@ class mail_notification(osv.Model):
|
|||
# add signature
|
||||
body_html = msg.body
|
||||
user_id = msg.author_id and msg.author_id.user_ids and msg.author_id.user_ids[0] and msg.author_id.user_ids[0].id or None
|
||||
signature_company = self.get_signature_footer(cr, uid, user_id, res_model=msg.model, res_id=msg.res_id, context=context)
|
||||
body_html = tools.append_content_to_html(body_html, signature_company, plaintext=False, container_tag='div')
|
||||
if user_signature:
|
||||
signature_company = self.get_signature_footer(cr, uid, user_id, res_model=msg.model, res_id=msg.res_id, context=context)
|
||||
body_html = tools.append_content_to_html(body_html, signature_company, plaintext=False, container_tag='div')
|
||||
|
||||
references = False
|
||||
if msg.parent_id:
|
||||
|
@ -203,13 +210,9 @@ class mail_notification(osv.Model):
|
|||
'recipient_ids': [(4, id) for id in notify_partner_ids],
|
||||
'references': references,
|
||||
}
|
||||
if msg.email_from:
|
||||
mail_values['email_from'] = msg.email_from
|
||||
if msg.reply_to:
|
||||
mail_values['reply_to'] = msg.reply_to
|
||||
mail_mail = self.pool.get('mail.mail')
|
||||
email_notif_id = mail_mail.create(cr, uid, mail_values, context=context)
|
||||
try:
|
||||
return mail_mail.send(cr, uid, [email_notif_id], context=context)
|
||||
except Exception:
|
||||
return False
|
||||
|
||||
if force_send:
|
||||
mail_mail.send(cr, uid, [email_notif_id], context=context)
|
||||
return True
|
||||
|
|
|
@ -55,7 +55,6 @@ class mail_mail(osv.Model):
|
|||
'auto_delete': fields.boolean('Auto Delete',
|
||||
help="Permanently delete this email after sending it, to save space"),
|
||||
'references': fields.text('References', help='Message references, such as identifiers of previous messages', readonly=1),
|
||||
'email_from': fields.char('From', help='Message sender, taken from user preferences.'),
|
||||
'email_to': fields.text('To', help='Message recipients (emails)'),
|
||||
'recipient_ids': fields.many2many('res.partner', string='To (Partners)'),
|
||||
'email_cc': fields.char('Cc', help='Carbon copy message recipients'),
|
||||
|
@ -67,16 +66,13 @@ class mail_mail(osv.Model):
|
|||
}
|
||||
|
||||
def _get_default_from(self, cr, uid, context=None):
|
||||
this = self.pool.get('res.users').browse(cr, SUPERUSER_ID, uid, context=context)
|
||||
if this.alias_domain:
|
||||
return '%s <%s@%s>' % (this.name, this.alias_name, this.alias_domain)
|
||||
elif this.email:
|
||||
return '%s <%s>' % (this.name, this.email)
|
||||
raise osv.except_osv(_('Invalid Action!'), _("Unable to send email, please configure the sender's email address or alias."))
|
||||
""" Kept for compatibility
|
||||
TDE TODO: remove me in 8.0
|
||||
"""
|
||||
return self.pool['mail.message']._get_default_from(cr, uid, context=context)
|
||||
|
||||
_defaults = {
|
||||
'state': 'outgoing',
|
||||
'email_from': lambda self, cr, uid, ctx=None: self._get_default_from(cr, uid, ctx),
|
||||
}
|
||||
|
||||
def default_get(self, cr, uid, fields, context=None):
|
||||
|
@ -92,29 +88,35 @@ class mail_mail(osv.Model):
|
|||
"""
|
||||
if values.get('reply_to'):
|
||||
return values.get('reply_to')
|
||||
format_name = True # whether to use a 'Followers of Pigs <pigs@openerp.com' format
|
||||
email_reply_to = False
|
||||
|
||||
# model, res_id: comes from values OR related message
|
||||
model = values.get('model')
|
||||
res_id = values.get('res_id')
|
||||
if values.get('mail_message_id') and (not model or not res_id):
|
||||
# model, res_id, email_from: comes from values OR related message
|
||||
model, res_id, email_from = values.get('model'), values.get('res_id'), values.get('email_from')
|
||||
if values.get('mail_message_id'):
|
||||
message = self.pool.get('mail.message').browse(cr, uid, values.get('mail_message_id'), context=context)
|
||||
if message.reply_to:
|
||||
email_reply_to = message.reply_to
|
||||
format_name = False
|
||||
if not model:
|
||||
model = message.model
|
||||
if not res_id:
|
||||
res_id = message.res_id
|
||||
if not email_from:
|
||||
email_from = message.email_from
|
||||
|
||||
# if model and res_id: try to use ``message_get_reply_to`` that returns the document alias
|
||||
if model and res_id and hasattr(self.pool[model], 'message_get_reply_to'):
|
||||
if not email_reply_to and model and res_id and hasattr(self.pool[model], 'message_get_reply_to'):
|
||||
email_reply_to = self.pool[model].message_get_reply_to(cr, uid, [res_id], context=context)[0]
|
||||
# no alias reply_to -> reply_to will be the email_from, only the email part
|
||||
if not email_reply_to and values.get('email_from'):
|
||||
emails = tools.email_split(values.get('email_from'))
|
||||
if emails:
|
||||
email_reply_to = emails[0]
|
||||
# no alias reply_to -> reply_to will be the email_from
|
||||
if not email_reply_to and email_from:
|
||||
email_reply_to = email_from
|
||||
|
||||
# format 'Document name <email_address>'
|
||||
if email_reply_to and model and res_id:
|
||||
if email_reply_to and model and res_id and format_name:
|
||||
emails = tools.email_split(email_reply_to)
|
||||
if emails:
|
||||
email_reply_to = emails[0]
|
||||
document_name = self.pool[model].name_get(cr, SUPERUSER_ID, [res_id], context=context)[0]
|
||||
if document_name:
|
||||
# sanitize document name
|
||||
|
|
|
@ -110,7 +110,7 @@
|
|||
<field name="res_model">mail.mail</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="context">{'search_default_outgoing': 1, 'search_default_type_email': 1}</field>
|
||||
<field name="context">{'search_default_outgoing': 1}</field>
|
||||
<field name="search_view_id" ref="view_mail_search"/>
|
||||
</record>
|
||||
|
||||
|
|
|
@ -182,6 +182,14 @@ class mail_message(osv.Model):
|
|||
def _needaction_domain_get(self, cr, uid, context=None):
|
||||
return [('to_read', '=', True)]
|
||||
|
||||
def _get_default_from(self, cr, uid, context=None):
|
||||
this = self.pool.get('res.users').browse(cr, SUPERUSER_ID, uid, context=context)
|
||||
if this.alias_domain:
|
||||
return '%s <%s@%s>' % (this.name, this.alias_name, this.alias_domain)
|
||||
elif this.email:
|
||||
return '%s <%s>' % (this.name, this.email)
|
||||
raise osv.except_osv(_('Invalid Action!'), _("Unable to send email, please configure the sender's email address or alias."))
|
||||
|
||||
def _get_default_author(self, cr, uid, context=None):
|
||||
return self.pool.get('res.users').read(cr, uid, uid, ['partner_id'], context=context)['partner_id'][0]
|
||||
|
||||
|
@ -190,7 +198,7 @@ class mail_message(osv.Model):
|
|||
'date': lambda *a: fields.datetime.now(),
|
||||
'author_id': lambda self, cr, uid, ctx=None: self._get_default_author(cr, uid, ctx),
|
||||
'body': '',
|
||||
'email_from': lambda self, cr, uid, ctx=None: self.pool.get('mail.mail')._get_default_from(cr, uid, ctx),
|
||||
'email_from': lambda self, cr, uid, ctx=None: self._get_default_from(cr, uid, ctx),
|
||||
}
|
||||
|
||||
#------------------------------------------------------
|
||||
|
@ -315,8 +323,10 @@ class mail_message(osv.Model):
|
|||
for key, message in message_tree.iteritems():
|
||||
if message.author_id:
|
||||
partner_ids |= set([message.author_id.id])
|
||||
if message.notified_partner_ids:
|
||||
if message.subtype_id and message.notified_partner_ids: # take notified people of message with a subtype
|
||||
partner_ids |= set([partner.id for partner in message.notified_partner_ids])
|
||||
elif not message.subtype_id and message.partner_ids: # take specified people of message without a subtype (log)
|
||||
partner_ids |= set([partner.id for partner in message.partner_ids])
|
||||
if message.attachment_ids:
|
||||
attachment_ids |= set([attachment.id for attachment in message.attachment_ids])
|
||||
# Read partners as SUPERUSER -> display the names like classic m2o even if no access
|
||||
|
@ -336,9 +346,12 @@ class mail_message(osv.Model):
|
|||
else:
|
||||
author = (0, message.email_from)
|
||||
partner_ids = []
|
||||
for partner in message.notified_partner_ids:
|
||||
if partner.id in partner_tree:
|
||||
partner_ids.append(partner_tree[partner.id])
|
||||
if message.subtype_id:
|
||||
partner_ids = [partner_tree[partner.id] for partner in message.notified_partner_ids
|
||||
if partner.id in partner_tree]
|
||||
else:
|
||||
partner_ids = [partner_tree[partner.id] for partner in message.partner_ids
|
||||
if partner.id in partner_tree]
|
||||
attachment_ids = []
|
||||
for attachment in message.attachment_ids:
|
||||
if attachment.id in attachments_tree:
|
||||
|
@ -752,7 +765,9 @@ class mail_message(osv.Model):
|
|||
elif not values.get('message_id'):
|
||||
values['message_id'] = tools.generate_tracking_message_id('private')
|
||||
newid = super(mail_message, self).create(cr, uid, values, context)
|
||||
self._notify(cr, uid, newid, context=context)
|
||||
self._notify(cr, uid, newid, context=context,
|
||||
force_send=context.get('mail_notify_force_send', True),
|
||||
user_signature=context.get('mail_notify_user_signature', True))
|
||||
# TDE FIXME: handle default_starred. Why not setting an inv on starred ?
|
||||
# Because starred will call set_message_starred, that looks for notifications.
|
||||
# When creating a new mail_message, it will create a notification to a message
|
||||
|
@ -866,20 +881,16 @@ class mail_message(osv.Model):
|
|||
return ''
|
||||
return result
|
||||
|
||||
def _notify(self, cr, uid, newid, context=None):
|
||||
def _notify(self, cr, uid, newid, context=None, force_send=False, user_signature=True):
|
||||
""" Add the related record followers to the destination partner_ids if is not a private message.
|
||||
Call mail_notification.notify to manage the email sending
|
||||
"""
|
||||
notification_obj = self.pool.get('mail.notification')
|
||||
message = self.browse(cr, uid, newid, context=context)
|
||||
|
||||
partners_to_notify = set([])
|
||||
# message has no subtype_id: pure log message -> no partners, no one notified
|
||||
if not message.subtype_id:
|
||||
return True
|
||||
|
||||
# all followers of the mail.message document have to be added as partners and notified
|
||||
if message.model and message.res_id:
|
||||
# all followers of the mail.message document have to be added as partners and notified if a subtype is defined (otherwise: log message)
|
||||
if message.subtype_id and message.model and message.res_id:
|
||||
fol_obj = self.pool.get("mail.followers")
|
||||
# browse as SUPERUSER because rules could restrict the search results
|
||||
fol_ids = fol_obj.search(cr, SUPERUSER_ID, [
|
||||
|
@ -889,7 +900,7 @@ class mail_message(osv.Model):
|
|||
], context=context)
|
||||
partners_to_notify |= set(fo.partner_id for fo in fol_obj.browse(cr, SUPERUSER_ID, fol_ids, context=context))
|
||||
# remove me from notified partners, unless the message is written on my own wall
|
||||
if message.author_id and message.model == "res.partner" and message.res_id == message.author_id.id:
|
||||
if message.subtype_id and message.author_id and message.model == "res.partner" and message.res_id == message.author_id.id:
|
||||
partners_to_notify |= set([message.author_id])
|
||||
elif message.author_id:
|
||||
partners_to_notify -= set([message.author_id])
|
||||
|
@ -900,7 +911,8 @@ class mail_message(osv.Model):
|
|||
|
||||
# notify
|
||||
if partners_to_notify:
|
||||
notification_obj._notify(cr, uid, newid, partners_to_notify=[p.id for p in partners_to_notify], context=context)
|
||||
notification_obj._notify(cr, uid, newid, partners_to_notify=[p.id for p in partners_to_notify], context=context,
|
||||
force_send=force_send, user_signature=user_signature)
|
||||
message.refresh()
|
||||
|
||||
# An error appear when a user receive a notification without notifying
|
||||
|
|
|
@ -30,9 +30,9 @@
|
|||
<field name="subject"/>
|
||||
<field name="author_id"/>
|
||||
<field name="email_from"/>
|
||||
<field name="reply_to"/>
|
||||
<field name="date"/>
|
||||
<field name="type"/>
|
||||
<field name="subtype_id"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="model"/>
|
||||
|
@ -40,6 +40,7 @@
|
|||
<field name="parent_id"/>
|
||||
<field name="partner_ids" widget="many2many_tags"/>
|
||||
<field name="notified_partner_ids" widget="many2many_tags"/>
|
||||
<field name="subtype_id"/>
|
||||
</group>
|
||||
</group>
|
||||
<field name="body"/>
|
||||
|
|
|
@ -730,6 +730,9 @@ class mail_thread(osv.AbstractModel):
|
|||
else:
|
||||
assert thread_id == 0, "Posting a message without model should be with a null res_id, to create a private message."
|
||||
model_pool = self.pool.get('mail.thread')
|
||||
if not hasattr(hasattr, 'message_post'):
|
||||
context['thread_model'] = model
|
||||
model_pool = self.pool['mail.thread']
|
||||
new_msg_id = model_pool.message_post(cr, uid, [thread_id], context=context, subtype='mail.mt_comment', **msg)
|
||||
|
||||
if partner_ids:
|
||||
|
@ -1064,7 +1067,7 @@ class mail_thread(osv.AbstractModel):
|
|||
model = False
|
||||
if thread_id:
|
||||
model = context.get('thread_model', self._name) if self._name == 'mail.thread' else self._name
|
||||
if model != self._name:
|
||||
if model != self._name and hasattr(self.pool[model], 'message_post'):
|
||||
del context['thread_model']
|
||||
return self.pool[model].message_post(cr, uid, thread_id, body=body, subject=subject, type=type, subtype=subtype, parent_id=parent_id, attachments=attachments, context=context, content_subtype=content_subtype, **kwargs)
|
||||
|
||||
|
|
|
@ -271,16 +271,16 @@
|
|||
<span class='oe_subtle'>•</span>
|
||||
</t>
|
||||
</t>
|
||||
<t t-if="widget.type == 'comment' and ! widget.subtype">
|
||||
<t t-if="widget.type == 'comment' and ! widget.subtype and widget.partner_ids.length == 0">
|
||||
logged a note
|
||||
</t>
|
||||
<t t-if="(widget.type == 'comment' or widget.type == 'email') and widget.subtype">
|
||||
<t t-if="(widget.type == 'comment' or widget.type == 'email') and (widget.subtype or widget.partner_ids.length > 0)">
|
||||
to
|
||||
<t t-if="widget.partner_ids.length == 0">
|
||||
nobody
|
||||
</t>
|
||||
</t>
|
||||
<t t-if="widget.type == 'notification' or ( (widget.type == 'email' or widget.type == 'comment') and widget.subtype)"
|
||||
<t t-if="widget.type == 'notification' or ( (widget.type == 'email' or widget.type == 'comment') and (widget.subtype or widget.partner_ids.length > 0))"
|
||||
t-foreach="widget.partner_ids.slice(0, 3)" t-as="partner">
|
||||
<span t-attf-class="oe_partner_follower">
|
||||
<a t-if="widget.options.show_link" t-attf-href="#model=res.partner&id=#{partner[0]}"><t t-raw="partner[1]"/></a>
|
||||
|
|
|
@ -69,6 +69,7 @@ class TestMailBase(common.TransactionCase):
|
|||
self.group_employee_id = group_employee_ref and group_employee_ref[1] or False
|
||||
|
||||
# Test users to use through the various tests
|
||||
self.res_users.write(cr, uid, uid, {'name': 'Administrator'})
|
||||
self.user_raoul_id = self.res_users.create(cr, uid,
|
||||
{'name': 'Raoul Grosbedon', 'signature': 'SignRaoul', 'email': 'raoul@raoul.fr', 'login': 'raoul', 'groups_id': [(6, 0, [self.group_employee_id])]})
|
||||
self.user_bert_id = self.res_users.create(cr, uid,
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
##############################################################################
|
||||
|
||||
from openerp.addons.mail.tests.test_mail_base import TestMailBase
|
||||
from openerp.tools import mute_logger
|
||||
|
||||
MAIL_TEMPLATE = """Return-Path: <whatever-2a840@postmaster.twitter.com>
|
||||
To: {to}
|
||||
|
@ -123,6 +124,102 @@ class TestMailgateway(TestMailBase):
|
|||
self.assertEqual(partner_info['partner_id'], p_b_id,
|
||||
'mail_thread: message_find_partner_from_emails wrong partner found')
|
||||
|
||||
def test_05_mail_message_mail_mail(self):
|
||||
""" Tests designed for testing email values based on mail.message, aliases, ... """
|
||||
cr, uid, user_raoul_id = self.cr, self.uid, self.user_raoul_id
|
||||
|
||||
# Data: update + generic variables
|
||||
reply_to1 = '_reply_to1@example.com'
|
||||
reply_to2 = '_reply_to2@example.com'
|
||||
email_from1 = 'from@example.com'
|
||||
alias_domain = 'schlouby.fr'
|
||||
raoul_from = 'Raoul Grosbedon <raoul@raoul.fr>'
|
||||
raoul_from_alias = 'Raoul Grosbedon <raoul@schlouby.fr>'
|
||||
raoul_reply = '"Followers of Pigs" <raoul@raoul.fr>'
|
||||
raoul_reply_alias = '"Followers of Pigs" <group+pigs@schlouby.fr>'
|
||||
# Data: remove alias_domain to see emails with alias
|
||||
param_ids = self.registry('ir.config_parameter').search(cr, uid, [('key', '=', 'mail.catchall.domain')])
|
||||
self.registry('ir.config_parameter').unlink(cr, uid, param_ids)
|
||||
|
||||
# Do: free message; specified values > default values
|
||||
msg_id = self.mail_message.create(cr, user_raoul_id, {'reply_to': reply_to1, 'email_from': email_from1})
|
||||
msg = self.mail_message.browse(cr, user_raoul_id, msg_id)
|
||||
# Test: message content
|
||||
self.assertIn('reply_to', msg.message_id,
|
||||
'mail_message: message_id should be specific to a mail_message with a given reply_to')
|
||||
self.assertEqual(msg.reply_to, reply_to1,
|
||||
'mail_message: incorrect reply_to: should come from values')
|
||||
self.assertEqual(msg.email_from, email_from1,
|
||||
'mail_message: incorrect email_from: should come from values')
|
||||
# Do: create a mail_mail with the previous mail_message
|
||||
mail_id = self.mail_mail.create(cr, user_raoul_id, {'mail_message_id': msg_id, 'state': 'cancel'})
|
||||
mail = self.mail_mail.browse(cr, user_raoul_id, mail_id)
|
||||
# Test: mail_mail content
|
||||
self.assertEqual(mail.reply_to, reply_to1,
|
||||
'mail_mail: incorrect reply_to: should come from mail.message')
|
||||
self.assertEqual(mail.email_from, email_from1,
|
||||
'mail_mail: incorrect email_from: should come from mail.message')
|
||||
# Do: create a mail_mail with the previous mail_message + specified reply_to
|
||||
mail_id = self.mail_mail.create(cr, user_raoul_id, {'mail_message_id': msg_id, 'state': 'cancel', 'reply_to': reply_to2})
|
||||
mail = self.mail_mail.browse(cr, user_raoul_id, mail_id)
|
||||
# Test: mail_mail content
|
||||
self.assertEqual(mail.reply_to, reply_to2,
|
||||
'mail_mail: incorrect reply_to: should come from values')
|
||||
self.assertEqual(mail.email_from, email_from1,
|
||||
'mail_mail: incorrect email_from: should come from mail.message')
|
||||
|
||||
# Do: mail_message attached to a document
|
||||
msg_id = self.mail_message.create(cr, user_raoul_id, {'model': 'mail.group', 'res_id': self.group_pigs_id})
|
||||
msg = self.mail_message.browse(cr, user_raoul_id, msg_id)
|
||||
# Test: message content
|
||||
self.assertIn('mail.group', msg.message_id,
|
||||
'mail_message: message_id should contain model')
|
||||
self.assertIn('%s' % self.group_pigs_id, msg.message_id,
|
||||
'mail_message: message_id should contain res_id')
|
||||
self.assertFalse(msg.reply_to,
|
||||
'mail_message: incorrect reply_to: should not be generated if not specified')
|
||||
self.assertEqual(msg.email_from, raoul_from,
|
||||
'mail_message: incorrect email_from: should be Raoul')
|
||||
# Do: create a mail_mail based on the previous mail_message
|
||||
mail_id = self.mail_mail.create(cr, user_raoul_id, {'mail_message_id': msg_id, 'state': 'cancel'})
|
||||
mail = self.mail_mail.browse(cr, user_raoul_id, mail_id)
|
||||
# Test: mail_mail content
|
||||
self.assertEqual(mail.reply_to, raoul_reply,
|
||||
'mail_mail: incorrect reply_to: should be Raoul')
|
||||
|
||||
# Data: set catchall domain
|
||||
self.registry('ir.config_parameter').set_param(cr, uid, 'mail.catchall.domain', alias_domain)
|
||||
|
||||
# Update message
|
||||
self.mail_message.write(cr, user_raoul_id, [msg_id], {'email_from': False, 'reply_to': False})
|
||||
msg.refresh()
|
||||
# Do: create a mail_mail based on the previous mail_message
|
||||
mail_id = self.mail_mail.create(cr, user_raoul_id, {'mail_message_id': msg_id, 'state': 'cancel'})
|
||||
mail = self.mail_mail.browse(cr, user_raoul_id, mail_id)
|
||||
# Test: mail_mail content
|
||||
self.assertEqual(mail.reply_to, raoul_reply_alias,
|
||||
'mail_mail: incorrect reply_to: should be Pigs alias')
|
||||
|
||||
# Update message: test alias on email_from
|
||||
msg_id = self.mail_message.create(cr, user_raoul_id, {})
|
||||
msg = self.mail_message.browse(cr, user_raoul_id, msg_id)
|
||||
# Do: create a mail_mail based on the previous mail_message
|
||||
mail_id = self.mail_mail.create(cr, user_raoul_id, {'mail_message_id': msg_id, 'state': 'cancel'})
|
||||
mail = self.mail_mail.browse(cr, user_raoul_id, mail_id)
|
||||
# Test: mail_mail content
|
||||
self.assertEqual(mail.reply_to, raoul_from_alias,
|
||||
'mail_mail: incorrect reply_to: should be message email_from using Raoul alias')
|
||||
|
||||
# Update message
|
||||
self.mail_message.write(cr, user_raoul_id, [msg_id], {'res_id': False, 'email_from': 'someone@schlouby.fr', 'reply_to': False})
|
||||
msg.refresh()
|
||||
# Do: create a mail_mail based on the previous mail_message
|
||||
mail_id = self.mail_mail.create(cr, user_raoul_id, {'mail_message_id': msg_id, 'state': 'cancel'})
|
||||
mail = self.mail_mail.browse(cr, user_raoul_id, mail_id)
|
||||
# Test: mail_mail content
|
||||
self.assertEqual(mail.reply_to, msg.email_from,
|
||||
'mail_mail: incorrect reply_to: should be message email_from')
|
||||
|
||||
def test_10_message_process(self):
|
||||
""" Testing incoming emails processing. """
|
||||
cr, uid, user_raoul = self.cr, self.uid, self.user_raoul
|
||||
|
|
|
@ -126,7 +126,6 @@ class mail_compose_message(osv.TransientModel):
|
|||
|
||||
_defaults = {
|
||||
'composition_mode': 'comment',
|
||||
'email_from': lambda self, cr, uid, ctx={}: self.pool.get('mail.mail')._get_default_from(cr, uid, context=ctx),
|
||||
'body': lambda self, cr, uid, ctx={}: '',
|
||||
'subject': lambda self, cr, uid, ctx={}: False,
|
||||
'partner_ids': lambda self, cr, uid, ctx={}: [],
|
||||
|
@ -158,7 +157,7 @@ class mail_compose_message(osv.TransientModel):
|
|||
|
||||
return super(mail_compose_message, self).check_access_rule(cr, uid, ids, operation, context=context)
|
||||
|
||||
def _notify(self, cr, uid, newid, context=None):
|
||||
def _notify(self, cr, uid, newid, context=None, force_send=False, user_signature=True):
|
||||
""" Override specific notify method of mail.message, because we do
|
||||
not want that feature in the wizard. """
|
||||
return
|
||||
|
@ -235,6 +234,9 @@ class mail_compose_message(osv.TransientModel):
|
|||
for wizard in self.browse(cr, uid, ids, context=context):
|
||||
mass_mail_mode = wizard.composition_mode == 'mass_mail'
|
||||
active_model_pool = self.pool[wizard.model if wizard.model else 'mail.thread']
|
||||
if not hasattr(active_model_pool, 'message_post'):
|
||||
context['thread_model'] = wizard.model
|
||||
active_model_pool = self.pool['mail.thread']
|
||||
|
||||
# wizard works in batch mode: [res_id] or active_ids
|
||||
res_ids = active_ids if mass_mail_mode and wizard.model and active_ids else [wizard.res_id]
|
||||
|
@ -257,13 +259,15 @@ class mail_compose_message(osv.TransientModel):
|
|||
new_attach_id = ir_attachment_obj.copy(cr, uid, attach_id, {'res_model': self._name, 'res_id': wizard.id}, context=context)
|
||||
attachment_ids.append(new_attach_id)
|
||||
post_values['attachment_ids'] = attachment_ids
|
||||
post_values.update(email_dict)
|
||||
# email_from: mass mailing only can specify another email_from
|
||||
if email_dict.get('email_from'):
|
||||
post_values['email_from'] = email_dict.pop('email_from')
|
||||
# replies redirection: mass mailing only
|
||||
if not wizard.same_thread:
|
||||
post_values['reply_to'] = email_dict.pop('reply_to')
|
||||
else:
|
||||
email_dict.pop('reply_to')
|
||||
post_values.update(email_dict)
|
||||
# clean the context (hint: mass mailing sets some default values that
|
||||
# could be wrongly interpreted by mail_mail)
|
||||
context.pop('default_email_to', None)
|
||||
|
@ -280,11 +284,10 @@ class mail_compose_message(osv.TransientModel):
|
|||
elif mass_mail_mode: # mass mail: is a log pushed to recipients unless specified, author not added
|
||||
if not wizard.notify:
|
||||
subtype = False
|
||||
context = dict(context, mail_create_nosubscribe=True) # add context key to avoid subscribing the author
|
||||
msg_id = active_model_pool.message_post(cr, uid, [res_id], type='comment', subtype=subtype, context=context, **post_values)
|
||||
# mass_mailing, post without notify: notify specific partners
|
||||
if mass_mail_mode and not wizard.notify and post_values['partner_ids']:
|
||||
self.pool.get('mail.notification')._notify(cr, uid, msg_id, post_values['partner_ids'], context=context)
|
||||
context = dict(context,
|
||||
mail_notify_force_send=False, # do not send emails directly but use the queue instead
|
||||
mail_create_nosubscribe=True) # add context key to avoid subscribing the author
|
||||
active_model_pool.message_post(cr, uid, [res_id], type='comment', subtype=subtype, context=context, **post_values)
|
||||
|
||||
return {'type': 'ir.actions.act_window_close'}
|
||||
|
||||
|
|
Loading…
Reference in New Issue