[IMP] mass_mailing: improved test send / send to all

- now workign on various models, taking the correct recipient (email, partner_id for partner or lead)
- improved test send: use email_to, now a many2many on contact model to ease the use of templates
- added action to create a mailing list from leads
- moved a res.partner dedicated action to its own file
- added an actoin to create a mailing list from contacts
- fixed mail_mail post_process: use mail_sent variable as mail.state is not available

bzr revid: tde@openerp.com-20140318164117-f2aou25u633j8m57
This commit is contained in:
Thibault Delavallée 2014-03-18 17:41:17 +01:00
parent 4583c1829b
commit a581d864a2
9 changed files with 141 additions and 54 deletions

View File

@ -126,7 +126,7 @@ class mail_mail(osv.Model):
_logger.exception("Failed processing mail queue")
return res
def _postprocess_sent_message(self, cr, uid, mail, context=None):
def _postprocess_sent_message(self, cr, uid, mail, context=None, mail_sent=True):
"""Perform any post-processing necessary after sending ``mail``
successfully, including deleting it completely along with its
attachment if the ``auto_delete`` flag of the mail was set.
@ -295,7 +295,7 @@ class mail_mail(osv.Model):
# /!\ can't use mail.state here, as mail.refresh() will cause an error
# see revid:odo@openerp.com-20120622152536-42b2s28lvdv3odyr in 6.1
if mail_sent:
self._postprocess_sent_message(cr, uid, mail, context=context)
self._postprocess_sent_message(cr, uid, mail, context=context, mail_sent=mail_sent)
except Exception as e:
_logger.exception('failed sending mail.mail %s', mail.id)
mail.write({'state': 'exception'})

View File

@ -43,6 +43,7 @@ professional emails and reuse templates in a few clicks.
'wizard/mail_compose_message_view.xml',
'views/mass_mailing.xml',
'views/res_config.xml',
'views/res_partner.xml',
'views/email_template.xml',
'security/ir.model.access.csv',
],

View File

@ -64,7 +64,7 @@ class MailMail(osv.Model):
body = tools.append_content_to_html(body, tracking_url, plaintext=False, container_tag='div')
return body
def _postprocess_sent_message(self, cr, uid, mail, context=None):
if mail.state == 'sent' and mail.statistics_ids:
def _postprocess_sent_message(self, cr, uid, mail, context=None, mail_sent=True):
if mail_sent is True and mail.statistics_ids:
self.pool['mail.mail.statistics'].write(cr, uid, [s.id for s in mail.statistics_ids], {'sent': fields.datetime.now()}, context=context)
return super(MailMail, self)._postprocess_sent_message(cr, uid, mail, context=context)
return super(MailMail, self)._postprocess_sent_message(cr, uid, mail, context=context, mail_sent=mail_sent)

View File

@ -51,11 +51,20 @@ class MassMailingContact(osv.Model):
'email': fields.char('Email', required=True),
'list_id': fields.many2one(
'mail.mass_mailing.list', string='Mailing List',
required=True, ondelete='cascade',
ondelete='cascade',
),
'opt_out': fields.boolean('Opt Out', help='The contact has chosen not to receive news anymore from this mailing list'),
}
def name_create(self, cr, uid, name, context=None):
name, email = self.pool['res.partner']._parse_partner_name(name, context=context)
if name and not email:
email = name
if email and not name:
name = email
rec_id = self.create(cr, uid, {'name': name, 'email': email}, context=context)
return self.name_get(cr, uid, [rec_id], context)[0]
class MassMailingList(osv.Model):
"""Model of a contact list. """
@ -72,19 +81,16 @@ class MassMailingList(osv.Model):
elif 'active_ids' in context:
res['domain'] = '%s' % [('id', 'in', context['active_ids'])]
else:
res['domain'] = '%s' % [('id', 'in', context.get('active_id', 0))]
res['domain'] = False
return res
def _get_contact_nbr(self, cr, uid, ids, name, arg, context=None):
"""Compute the number of contacts linked to the mailing list. """
results = dict.fromkeys(ids, 0)
for contact_list in self.browse(cr, uid, ids, context=context):
print contact_list, contact_list.model, contact_list.domain
domain = self._get_domain(cr, uid, [contact_list.id], context=context)[contact_list.id]
print domain
results[contact_list.id] = self.pool[contact_list.model].search(
cr, uid,
domain,
self._get_domain(cr, uid, [contact_list.id], context=context)[contact_list.id],
count=True, context=context
)
return results
@ -428,7 +434,7 @@ class MassMailing(osv.Model):
'template_id': fields.many2one(
'email.template', 'Email Template',
domain=[('use_in_mass_mailing', '=', True)],
ondelete='set null',
required=True,
),
'body_html': fields.related(
'template_id', 'body_html', type='html',
@ -445,7 +451,10 @@ class MassMailing(osv.Model):
),
# mailing options
'email_from': fields.char('From'),
'email_to': fields.char('Send to Emails'),
'email_to': fields.many2many(
'mail.mass_mailing.contact', 'mail_mass_mailing_contact_rel',
string='Test Emails'
),
'reply_to': fields.char('Reply To'),
'mailing_model': fields.selection(_mailing_model, string='Type', required=True),
'contact_list_ids': fields.many2many(
@ -554,6 +563,12 @@ class MassMailing(osv.Model):
values['body_html'] = False
return {'value': values}
def _get_model_to_list_action_id(self, cr, uid, model, context=None):
if model == 'res.partner':
return self.pool['ir.model.data'].xmlid_to_res_id(cr, uid, 'mass_mailing.action_partner_to_mailing_list')
else:
return self.pool['ir.model.data'].xmlid_to_res_id(cr, uid, 'mass_mailing.action_contact_to_mailing_list')
def action_new_list(self, cr, uid, ids, context=None):
wizard = self.browse(cr, uid, ids[0], context=context)
action_id = self.pool['ir.model.data'].xmlid_to_res_id(cr, uid, 'mass_mailing.action_partner_to_mailing_list')
@ -584,16 +599,24 @@ class MassMailing(osv.Model):
# Email Sending
#------------------------------------------------------
def _get_mail_recipients(self, cr, uid, mailing, res_ids, context=None):
if mailing.mailing_model == 'mail.mass_mailing.contact':
contacts = self.pool['mail.mass_mailing.contact'].browse(cr, uid, res_ids, context=context)
return dict((contact.id, {'email_to': '"%s" <%s>' % (contact.name, contact.email)}) for contact in contacts)
else:
return dict((res_id, {'recipient_ids': [(4, res_id)]}) for res_id in res_ids)
def send_mail(self, cr, uid, ids, context=None):
Mail = self.pool['mail.mail']
for mailing in self.browse(cr, uid, ids, context=context):
domain = self.pool['mail.mass_mailing.list'].get_global_domain(cr, uid, [l.id for l in mailing.contact_list_ids], context=context)[mailing.mailing_model]
domain = self.pool['mail.mass_mailing.list'].get_global_domain(
cr, uid, [l.id for l in mailing.contact_list_ids], context=context
)[mailing.mailing_model]
res_ids = self.pool[mailing.mailing_model].search(cr, uid, domain, context=context)
recipients = self._get_mail_recipients(cr, uid, mailing, res_ids, context=context)
all_mail_values = self.pool['mail.compose.message'].generate_email_for_composer_batch(
cr, uid, mailing.template_id.id, res_ids,
context=context,
fields=['body_html', 'attachment_ids', 'mail_server_id']
)
context=context, fields=['body_html', 'attachment_ids', 'mail_server_id'])
for res_id, mail_values in all_mail_values.iteritems():
mail_values.update({
'email_from': mailing.email_from,
@ -601,40 +624,48 @@ class MassMailing(osv.Model):
'subject': mailing.name,
'body_html': mail_values.get('body'),
'auto_delete': True,
'statistics_ids': [(0, 0, {
'notification': True,
})
mail_values['statistics_ids'] = [
(0, 0, {
'model': mailing.mailing_model,
'res_id': res_id,
'mass_mailing_id': mailing.id,
})]
})
m2m_attachment_ids = self.pool['mail.thread']._message_preprocess_attachments(
cr, uid, mail_values.pop('attachments', []),
mail_values.pop('attachment_ids', []),
'mail.message', 0,
context=context)
mail_values['attachment_ids'] = m2m_attachment_ids
if mailing.mailing_model == 'mail.mass_mailing.list':
contact = self.pool['mail.mass_mailing.contact'].browse(cr, uid, res_id, context=context)
mail_values['email_to'] = '"%s" <%s>' % (contact.name, contact.email)
elif mailing.mailing_model == 'res.partner':
mail_values['recipient_ids'] = [(4, res_id)]
mail_values.update(recipients[res_id])
Mail.create(cr, uid, mail_values, context=context)
# todo: handle email_to
return True
def send_mail_to_myself(self, cr, uid, ids, context=None):
def send_mail_test(self, cr, uid, ids, context=None):
Mail = self.pool['mail.mail']
for mailing in self.browse(cr, uid, ids, context=context):
mail_values = {
'email_from': mailing.email_from,
'reply_to': mailing.reply_to,
'email_to': self.pool['res.users'].browse(cr, uid, uid, context=context).email,
'subject': mailing.name,
'body_html': mailing.template_id.body_html,
'auto_delete': True,
}
mail_id = Mail.create(cr, uid, mail_values, context=context)
Mail.send(cr, uid, [mail_id], context=context)
# res_ids = self._set_up_test_mailing(cr, uid, mailing.mailing_model, context=context)
res_ids = [c.id for c in mailing.email_to]
all_mail_values = self.pool['mail.compose.message'].generate_email_for_composer_batch(
cr, uid, mailing.template_id.id, res_ids,
context=context,
fields=['body_html', 'attachment_ids', 'mail_server_id']
)
mail_ids = []
for res_id, mail_values in all_mail_values.iteritems():
mail_values = {
'email_from': mailing.email_from,
'reply_to': mailing.reply_to,
'email_to': self.pool['mail.mass_mailing.contact'].browse(cr, uid, res_id, context=context).email,
'subject': mailing.name,
'body_html': mail_values.get('body'),
'auto_delete': True,
}
mail_ids.append(Mail.create(cr, uid, mail_values, context=context))
Mail.send(cr, uid, mail_ids, context=context)
return True

View File

@ -72,6 +72,17 @@
parent="mass_mailing_list" sequence="50"
action="action_view_mass_mailing_contacts"/>
<!-- Create a Mailing List from Contyacts-->
<act_window name="Create Mailing List"
res_model="mail.mass_mailing.list"
src_model="mail.mass_mailing.contact"
view_mode="form"
multi="True"
target="current"
key2="client_action_multi"
id="action_contact_to_mailing_list"
context="{'default_mass_mailing_id': context.get('default_mass_mailing_id')}"/>
<!-- MASS MAILING LIST !-->
<record model="ir.ui.view" id="view_mail_mass_mailing_list_search">
<field name="name">mail.mass_mailing.list.search</field>
@ -126,8 +137,8 @@
<field name="filter_id"
on_change="on_change_filter_id(filter_id, context)"
attrs="{'invisible': [('model', '=', 'mail.mass_mailing.contact')]}"/>
<field name="domain"
attrs="{'invisible': ['|', ('model', '=', 'mail.mass_mailing.contact'), ('filter_id', '!=', False)]}"/>
<field name="domain"/>
<!-- attrs="{'invisible': ['|', ('model', '=', 'mail.mass_mailing.contact'), ('filter_id', '!=', False)]}"/> -->
</group>
</sheet>
</form>
@ -189,8 +200,8 @@
<field name="arch" type="xml">
<form string="Mass Mailing" version="7.0">
<header>
<button name="send_mail_to_myself" type="object"
class="oe_highlight" string="Send to Myself"/>
<button name="send_mail_test" type="object"
class="oe_highlight" string="Test Mailing"/>
<button name="send_mail" type="object"
class="oe_highlight" string="Send to All"/>
<field name="state" widget="statusbar" clickable="True"/>
@ -210,7 +221,7 @@
</div>
<field name="email_from"/>
<field name="reply_to"/>
<field name="email_to"/>
<field name="email_to" widget="many2many_tags"/>
</group>
<group>
<p>Here be some graphs</p>
@ -264,7 +275,7 @@
<div>
<h3><field name="name"/></h3>
<h4 style="display: inline;"><field name="mass_mailing_campaign_id" groups="mass_mailing.group_mass_mailing_campaign"/></h4>
<t t-if="record.mass_mailing_campaign_id.raw_value"> - </t><field name="date"/>
<t t-if="record.mass_mailing_campaign_id.raw_value" groups="mass_mailing.group_mass_mailing_campaign"> - </t><field name="date"/>
</div>
<div>
<field name="total" widget="gauge" style="width:120px; height: 90px;"
@ -479,6 +490,7 @@
<tree string="Mail Statistics">
<field name="mail_mail_id"/>
<field name="message_id"/>
<field name="sent"/>
<field name="opened"/>
<field name="replied"/>
<field name="bounced"/>
@ -495,6 +507,7 @@
<group>
<field name="mail_mail_id"/>
<field name="message_id"/>
<field name="sent"/>
<field name="opened"/>
<field name="replied"/>
<field name="bounced"/>
@ -523,16 +536,5 @@
parent="base.menu_email" sequence="50"
action="action_view_mail_mail_statistics"/>
<!-- Replace the default mass-mailing wizard in base with the composition wizard -->
<act_window name="Create a Mailing List"
res_model="mail.mass_mailing.list"
src_model="res.partner"
view_mode="form"
multi="True"
target="current"
key2="client_action_multi"
id="action_partner_to_mailing_list"
context="{'default_mass_mailing_id': context.get('default_mass_mailing_id')}"/>
</data>
</openerp>

View File

@ -0,0 +1,17 @@
<?xml version="1.0"?>
<openerp>
<data>
<!-- Create a Mailing List from Partners-->
<act_window name="Create Mailing List"
res_model="mail.mass_mailing.list"
src_model="res.partner"
view_mode="form"
multi="True"
target="current"
key2="client_action_multi"
id="action_partner_to_mailing_list"
context="{'default_mass_mailing_id': context.get('default_mass_mailing_id')}"/>
</data>
</openerp>

View File

@ -10,7 +10,9 @@
Bridge module between Mass Mailing and CRM
""",
'website': 'http://www.openerp.com',
'data': [],
'data': [
'views/crm_lead.xml',
],
'demo': [],
'installable': True,
'auto_install': True,

View File

@ -12,3 +12,20 @@ class MassMailing(osv.Model):
res = super(MassMailing, self)._get_mailing_model(cr, uid, context=context)
res.append(('crm.lead', 'Leads / Opportunities'))
return res
def _get_model_to_list_action_id(self, cr, uid, model, context=None):
if model == 'crm.lead':
return self.pool['ir.model.data'].xmlid_to_res_id(cr, uid, 'mass_mailing.action_lead_to_mailing_list')
else:
return super(MassMailing, self)._get_model_to_list_action_id(cr, uid, model, context=context)
def _get_mail_recipients(self, cr, uid, mailing, res_ids, context=None):
if mailing.mailing_model == 'crm.lead':
res = {}
for lead in self.pool['crm.lead'].browse(cr, uid, res_ids, context=context):
if lead.partner_id:
res[lead.id] = {'recipient_ids': [(4, lead.partner_id.id)]}
else:
res[lead.id] = {'email_to': [(4, lead.email_from)]}
return res
return super(MassMailing, self)._get_mail_recipients(cr, uid, mailing, res_ids, context=context)

View File

@ -0,0 +1,17 @@
<?xml version="1.0"?>
<openerp>
<data>
<!-- Replace the default mass-mailing wizard in base with the composition wizard -->
<act_window name="Create Mailing List"
res_model="mail.mass_mailing.list"
src_model="crm.lead"
view_mode="form"
multi="True"
target="current"
key2="client_action_multi"
id="action_lead_to_mailing_list"
context="{'default_mass_mailing_id': context.get('default_mass_mailing_id')}"/>
</data>
</openerp>