[IMP]URD Newsletter : better constraint on mailing lists
* Refactoring from tabs to spaces ; * Add constrains with create/write overwrite ; * Now allow to not raise on double email on creation (but no real insert) ; * Raise on write.
This commit is contained in:
parent
3663753a60
commit
f0edff138f
@ -21,7 +21,7 @@
|
|||||||
- Ajout section "Dernières publications" aux modèles Newsletter URD
|
- Ajout section "Dernières publications" aux modèles Newsletter URD
|
||||||
- Empêcher pour un publipostage de faire un second clic "Envoyer à tous" si l'envoi de mails est déjà planifié
|
- Empêcher pour un publipostage de faire un second clic "Envoyer à tous" si l'envoi de mails est déjà planifié
|
||||||
- Ajouter automatiquement un lien de désinscription s'il n'est pas ajouté manuellement
|
- Ajouter automatiquement un lien de désinscription s'il n'est pas ajouté manuellement
|
||||||
|
|
||||||
En projet:
|
En projet:
|
||||||
- Ecraser les propriétés d'un publipostage par les propriétés standard d'un modèle de courriel au moment de la sélection de ce dernier.
|
- Ecraser les propriétés d'un publipostage par les propriétés standard d'un modèle de courriel au moment de la sélection de ce dernier.
|
||||||
- Message de confirmation de désincription plus verbeux.
|
- Message de confirmation de désincription plus verbeux.
|
||||||
@ -34,7 +34,7 @@
|
|||||||
# Check https://github.com/odoo/odoo/blob/master/openerp/addons/base/module/module_data.xml
|
# Check https://github.com/odoo/odoo/blob/master/openerp/addons/base/module/module_data.xml
|
||||||
# for the full list
|
# for the full list
|
||||||
'category': 'Marketing',
|
'category': 'Marketing',
|
||||||
'version': '0.5',
|
'version': '8.0.0.5.1',
|
||||||
|
|
||||||
# any module necessary for this one to work correctly
|
# any module necessary for this one to work correctly
|
||||||
'depends': ['base','mass_mailing','marketing','website_mail'],
|
'depends': ['base','mass_mailing','marketing','website_mail'],
|
||||||
@ -49,4 +49,4 @@
|
|||||||
'newsletter-en-template.xml',
|
'newsletter-en-template.xml',
|
||||||
'snippets.xml',
|
'snippets.xml',
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,5 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
def migrate(cr, version):
|
||||||
|
cr.execute('''ALTER TABLE mail_mass_mailing_contact
|
||||||
|
DROP CONSTRAINT mail_mass_mailing_contact_email_list_unique''')
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
import urlparse
|
import urlparse
|
||||||
import werkzeug.urls
|
import werkzeug.urls
|
||||||
|
import logging
|
||||||
|
|
||||||
from openerp import models, fields, api
|
from openerp import models, fields, api
|
||||||
from openerp.osv import osv
|
from openerp.osv import osv
|
||||||
@ -9,175 +10,198 @@ from openerp.osv import osv
|
|||||||
from openerp import tools
|
from openerp import tools
|
||||||
from openerp.tools.translate import _
|
from openerp.tools.translate import _
|
||||||
|
|
||||||
import logging
|
|
||||||
_logger = logging.getLogger(__name__)
|
_logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
# Overrides mass mailing Contact for this module purpose
|
# Overrides mass mailing Contact for this module purpose
|
||||||
class contact(models.Model):
|
class contact(models.Model):
|
||||||
_name = "mail.mass_mailing.contact"
|
_name = "mail.mass_mailing.contact"
|
||||||
_inherit = "mail.mass_mailing.contact"
|
_inherit = "mail.mass_mailing.contact"
|
||||||
|
|
||||||
unsubscription_date = fields.Date(string="Unsubscription date")
|
|
||||||
unsubscribed_by_odoo_user = fields.Many2one("res.users", string="Unsubscribed by this Odoo user")
|
|
||||||
|
|
||||||
_sql_constraints = [
|
unsubscription_date = fields.Date(string="Unsubscription date")
|
||||||
('email_list_unique',
|
unsubscribed_by_odoo_user = fields.Many2one("res.users", string="Unsubscribed by this Odoo user")
|
||||||
'unique (email, list_id)',
|
|
||||||
_('Subscriber already registered for this mailing list.')
|
# _sql_constraints = [
|
||||||
)]
|
# ('email_list_unique',
|
||||||
|
# 'unique (email, list_id)',
|
||||||
@api.onchange("opt_out")
|
# _('Subscriber already registered for this mailing list.')
|
||||||
def on_change_opt_out(self):
|
# )]
|
||||||
if self.opt_out:
|
|
||||||
self.unsubscription_date = fields.Datetime.now()
|
@api.onchange("opt_out")
|
||||||
self.unsubscribed_by_odoo_user = self.env.user
|
def on_change_opt_out(self):
|
||||||
else:
|
if self.opt_out:
|
||||||
self.unsubscription_date = None
|
self.unsubscription_date = fields.Datetime.now()
|
||||||
self.unsubscribed_by_odoo_user = None
|
self.unsubscribed_by_odoo_user = self.env.user
|
||||||
|
else:
|
||||||
|
self.unsubscription_date = None
|
||||||
|
self.unsubscribed_by_odoo_user = None
|
||||||
|
|
||||||
|
@api.model
|
||||||
|
@api.returns('self', lambda rec: rec.id)
|
||||||
|
def create(self, vals):
|
||||||
|
if 'list_id' in vals and 'email' in vals:
|
||||||
|
domain = [('list_id', '=', vals['list_id']),
|
||||||
|
('email', 'ilike', vals['email'])]
|
||||||
|
res = self.env['mail.mass_mailing.contact'].search(domain)
|
||||||
|
if len(res.ids) > 0:
|
||||||
|
return res[0] # Workaround...
|
||||||
|
return super(contact, self).create(vals)
|
||||||
|
|
||||||
|
@api.multi
|
||||||
|
def write(self, values):
|
||||||
|
""" Ensures that there is no doubles in email for the same list """
|
||||||
|
for ctc in self:
|
||||||
|
domain = [('list_id', '=', ctc.list_id.id),
|
||||||
|
('email', 'ilike', ctc.email)]
|
||||||
|
res = self.env['mail.mass_mailing.contact'].search(domain)
|
||||||
|
if len(res.ids) > 1:
|
||||||
|
_logger.warning(res)
|
||||||
|
raise models.ValidationError(
|
||||||
|
_('Subscriber %s already registered for this mailing list.') % ctc.email
|
||||||
|
)
|
||||||
|
return super(contact, self).write(values)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class MailMail(osv.Model):
|
class MailMail(osv.Model):
|
||||||
"""Add the mass mailing campaign data to mail"""
|
"""Add the mass mailing campaign data to mail"""
|
||||||
_name = 'mail.mail'
|
_name = 'mail.mail'
|
||||||
_inherit = ['mail.mail']
|
_inherit = ['mail.mail']
|
||||||
|
|
||||||
def _get_unsubscribe_url(self, cr, uid, mail, email_to, msg=None, context=None):
|
def _get_unsubscribe_url(self, cr, uid, mail, email_to, msg=None, context=None):
|
||||||
if 'mass_mailing_test' in context:
|
if 'mass_mailing_test' in context:
|
||||||
base_url = self.pool.get('ir.config_parameter').get_param(cr, uid, 'web.base.url')
|
base_url = self.pool.get('ir.config_parameter').get_param(cr, uid, 'web.base.url')
|
||||||
else:
|
else:
|
||||||
base_url = ""
|
base_url = ""
|
||||||
url = urlparse.urljoin(
|
url = urlparse.urljoin(
|
||||||
base_url, 'mail/mailing/%(mailing_id)s/unsubscribe?%(params)s' % {
|
base_url, 'mail/mailing/%(mailing_id)s/unsubscribe?%(params)s' % {
|
||||||
'mailing_id': mail.mailing_id.id,
|
'mailing_id': mail.mailing_id.id,
|
||||||
'params': werkzeug.url_encode({'db': cr.dbname, 'res_id': mail.res_id, 'email': email_to})
|
'params': werkzeug.url_encode({'db': cr.dbname, 'res_id': mail.res_id, 'email': email_to})
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
return '%s' % url
|
return '%s' % url
|
||||||
|
|
||||||
def _get_html_version_url(self, cr, uid, mail, email_to, context=None):
|
def _get_html_version_url(self, cr, uid, mail, email_to, context=None):
|
||||||
if 'mass_mailing_test' in context:
|
if 'mass_mailing_test' in context:
|
||||||
base_url = self.pool.get('ir.config_parameter').get_param(cr, uid, 'web.base.url')
|
base_url = self.pool.get('ir.config_parameter').get_param(cr, uid, 'web.base.url')
|
||||||
else:
|
else:
|
||||||
base_url = ""
|
base_url = ""
|
||||||
url = urlparse.urljoin(base_url, 'newsletter/html_version_%s' % mail.mailing_id.id)
|
url = urlparse.urljoin(base_url, 'newsletter/html_version_%s' % mail.mailing_id.id)
|
||||||
return '%s' % url
|
return '%s' % url
|
||||||
|
|
||||||
def send_get_email_dict(self, cr, uid, mail, partner=None, context=None):
|
def send_get_email_dict(self, cr, uid, mail, partner=None, context=None):
|
||||||
email_to = self.send_get_mail_to(cr, uid, mail, partner=partner, context=context)
|
email_to = self.send_get_mail_to(cr, uid, mail, partner=partner, context=context)
|
||||||
body = self.send_get_mail_body(cr, uid, mail, partner=partner, context=context)
|
body = self.send_get_mail_body(cr, uid, mail, partner=partner, context=context)
|
||||||
|
|
||||||
if mail.mailing_id and body and email_to:
|
if mail.mailing_id and body and email_to:
|
||||||
emails = tools.email_split(email_to[0])
|
emails = tools.email_split(email_to[0])
|
||||||
has_email_to = emails and emails[0] or False
|
has_email_to = emails and emails[0] or False
|
||||||
unsubscribe_url = self._get_unsubscribe_url(cr, uid, mail, has_email_to, context=context)
|
unsubscribe_url = self._get_unsubscribe_url(cr, uid, mail, has_email_to, context=context)
|
||||||
if unsubscribe_url:
|
if unsubscribe_url:
|
||||||
if body.count('__UNSUBSCRIBE_URL__') > 0:
|
if body.count('__UNSUBSCRIBE_URL__') > 0:
|
||||||
body = body.replace('__UNSUBSCRIBE_URL__', unsubscribe_url)
|
body = body.replace('__UNSUBSCRIBE_URL__', unsubscribe_url)
|
||||||
else:
|
else:
|
||||||
unsubscribe_link = '<small><a href="%s">%s</a></small>' % (unsubscribe_url, _('Click to unsubscribe'))
|
unsubscribe_link = '<small><a href="%s">%s</a></small>' % (unsubscribe_url, _('Click to unsubscribe'))
|
||||||
body = tools.append_content_to_html(body,unsubscribe_link, plaintext=False, container_tag='p')
|
body = tools.append_content_to_html(body,unsubscribe_link, plaintext=False, container_tag='p')
|
||||||
html_version_url = self._get_html_version_url(cr, uid, mail, has_email_to, context=context)
|
html_version_url = self._get_html_version_url(cr, uid, mail, has_email_to, context=context)
|
||||||
body = body.replace('__HTML_VERSION_URL__', html_version_url)
|
body = body.replace('__HTML_VERSION_URL__', html_version_url)
|
||||||
|
|
||||||
body_alternative = tools.html2plaintext(body)
|
body_alternative = tools.html2plaintext(body)
|
||||||
|
|
||||||
res = {
|
res = {
|
||||||
'body': body,
|
'body': body,
|
||||||
'body_alternative': body_alternative,
|
'body_alternative': body_alternative,
|
||||||
'subject': self.send_get_mail_subject(cr, uid, mail, partner=partner, context=context),
|
'subject': self.send_get_mail_subject(cr, uid, mail, partner=partner, context=context),
|
||||||
'email_to': email_to,
|
'email_to': email_to,
|
||||||
}
|
}
|
||||||
|
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class TestMassMailing(osv.TransientModel):
|
class TestMassMailing(osv.TransientModel):
|
||||||
_name = 'mail.mass_mailing.test'
|
_name = 'mail.mass_mailing.test'
|
||||||
_description = 'Sample Mail Wizard'
|
_description = 'Sample Mail Wizard'
|
||||||
|
|
||||||
email_to = fields.Char('Recipients', required=True,help='Comma-separated list of email addresses.',default=lambda self: self.pool['mail.message']._get_default_from(self.env.cr, self.env.user.id, context=self.env.context))
|
email_to = fields.Char('Recipients', required=True,help='Comma-separated list of email addresses.',default=lambda self: self.pool['mail.message']._get_default_from(self.env.cr, self.env.user.id, context=self.env.context))
|
||||||
mass_mailing_id = fields.Many2one('mail.mass_mailing', 'Mailing', required=True, ondelete='cascade')
|
mass_mailing_id = fields.Many2one('mail.mass_mailing', 'Mailing', required=True, ondelete='cascade')
|
||||||
|
|
||||||
|
def send_mail_test(self, cr, uid, ids, context=None):
|
||||||
|
_logger.info('entering new send_mail_test')
|
||||||
|
#Add a 'mass_mailing_test' flag in the context to be able to build correct HTML_VERSION/UNSUBSCRIBE URLs in test mode
|
||||||
|
context['mass_mailing_test'] = True
|
||||||
|
|
||||||
|
Mail = self.pool['mail.mail']
|
||||||
|
|
||||||
|
_logger.info('before send_mail_test for loop')
|
||||||
|
for wizard in self.browse(cr, uid, ids, context=context):
|
||||||
|
mailing = wizard.mass_mailing_id
|
||||||
|
test_emails = tools.email_split(wizard.email_to)
|
||||||
|
mail_ids = []
|
||||||
|
for test_mail in test_emails:
|
||||||
|
mail_values = {
|
||||||
|
'email_from': mailing.email_from,
|
||||||
|
'reply_to': mailing.reply_to,
|
||||||
|
'email_to': test_mail,
|
||||||
|
'subject': mailing.name,
|
||||||
|
'body_html': '',
|
||||||
|
'notification': True,
|
||||||
|
'mailing_id': mailing.id,
|
||||||
|
'attachment_ids': [(4, attachment.id) for attachment in mailing.attachment_ids],
|
||||||
|
}
|
||||||
|
mail_mail_obj = Mail.browse(cr, uid, Mail.create(cr, uid, mail_values, context=context), context=context)
|
||||||
|
unsubscribe_url = Mail._get_unsubscribe_url(cr, uid, mail_mail_obj, test_mail, context=context)
|
||||||
|
html_version_url = Mail._get_html_version_url(cr, uid, mail_mail_obj, test_mail, context=context)
|
||||||
|
if unsubscribe_url:
|
||||||
|
if mailing.body_html.count('__UNSUBSCRIBE_URL__') > 0:
|
||||||
|
body = mailing.body_html.replace('__UNSUBSCRIBE_URL__', unsubscribe_url)
|
||||||
|
else:
|
||||||
|
unsubscribe_link = '<small><a href="%s">%s</a></small>' % (unsubscribe_url, _('Click to unsubscribe'))
|
||||||
|
body = tools.append_content_to_html(mailing.body_html,unsubscribe_link, plaintext=False, container_tag='p')
|
||||||
|
body = mailing.body_html.replace('__HTML_VERSION_URL__', html_version_url)
|
||||||
|
Mail.write(cr, uid, mail_mail_obj.id, {'body_html': mailing.body_html}, context=context)
|
||||||
|
mail_ids.append(mail_mail_obj.id)
|
||||||
|
_logger.info('just before new send_mail_test Mail.send')
|
||||||
|
Mail.send(cr, uid, mail_ids, context=context)
|
||||||
|
_logger.info('just after new send_mail_test Mail.send')
|
||||||
|
self.pool['mail.mass_mailing'].write(cr, uid, [mailing.id], {'state': 'test'}, context=context)
|
||||||
|
return True
|
||||||
|
|
||||||
def send_mail_test(self, cr, uid, ids, context=None):
|
|
||||||
_logger.info('entering new send_mail_test')
|
|
||||||
#Add a 'mass_mailing_test' flag in the context to be able to build correct HTML_VERSION/UNSUBSCRIBE URLs in test mode
|
|
||||||
context['mass_mailing_test'] = True
|
|
||||||
|
|
||||||
Mail = self.pool['mail.mail']
|
|
||||||
|
|
||||||
_logger.info('before send_mail_test for loop')
|
|
||||||
for wizard in self.browse(cr, uid, ids, context=context):
|
|
||||||
mailing = wizard.mass_mailing_id
|
|
||||||
test_emails = tools.email_split(wizard.email_to)
|
|
||||||
mail_ids = []
|
|
||||||
for test_mail in test_emails:
|
|
||||||
mail_values = {
|
|
||||||
'email_from': mailing.email_from,
|
|
||||||
'reply_to': mailing.reply_to,
|
|
||||||
'email_to': test_mail,
|
|
||||||
'subject': mailing.name,
|
|
||||||
'body_html': '',
|
|
||||||
'notification': True,
|
|
||||||
'mailing_id': mailing.id,
|
|
||||||
'attachment_ids': [(4, attachment.id) for attachment in mailing.attachment_ids],
|
|
||||||
}
|
|
||||||
mail_mail_obj = Mail.browse(cr, uid, Mail.create(cr, uid, mail_values, context=context), context=context)
|
|
||||||
unsubscribe_url = Mail._get_unsubscribe_url(cr, uid, mail_mail_obj, test_mail, context=context)
|
|
||||||
html_version_url = Mail._get_html_version_url(cr, uid, mail_mail_obj, test_mail, context=context)
|
|
||||||
if unsubscribe_url:
|
|
||||||
if mailing.body_html.count('__UNSUBSCRIBE_URL__') > 0:
|
|
||||||
body = mailing.body_html.replace('__UNSUBSCRIBE_URL__', unsubscribe_url)
|
|
||||||
else:
|
|
||||||
unsubscribe_link = '<small><a href="%s">%s</a></small>' % (unsubscribe_url, _('Click to unsubscribe'))
|
|
||||||
body = tools.append_content_to_html(mailing.body_html,unsubscribe_link, plaintext=False, container_tag='p')
|
|
||||||
body = mailing.body_html.replace('__HTML_VERSION_URL__', html_version_url)
|
|
||||||
Mail.write(cr, uid, mail_mail_obj.id, {'body_html': mailing.body_html}, context=context)
|
|
||||||
mail_ids.append(mail_mail_obj.id)
|
|
||||||
_logger.info('just before new send_mail_test Mail.send')
|
|
||||||
Mail.send(cr, uid, mail_ids, context=context)
|
|
||||||
_logger.info('just after new send_mail_test Mail.send')
|
|
||||||
self.pool['mail.mass_mailing'].write(cr, uid, [mailing.id], {'state': 'test'}, context=context)
|
|
||||||
return True
|
|
||||||
|
|
||||||
#class MassMailing(osv.Model):
|
#class MassMailing(osv.Model):
|
||||||
#_name = "mail.mass_mailing"
|
#_name = "mail.mass_mailing"
|
||||||
#_inherit = "mail.mass_mailing"
|
#_inherit = "mail.mass_mailing"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#def _get_mailing_model(self, cr, uid, context=None):
|
#def _get_mailing_model(self, cr, uid, context=None):
|
||||||
# res = super(MassMailing, self)._get_mailing_model(cr, uid, context)
|
# res = super(MassMailing, self)._get_mailing_model(cr, uid, context)
|
||||||
# res.append(('mail.tracking.email', _('Email Tracking')))
|
# res.append(('mail.tracking.email', _('Email Tracking')))
|
||||||
# print res
|
# print res
|
||||||
# return res
|
# return res
|
||||||
|
|
||||||
# indirections for inheritance
|
|
||||||
#_mailing_model = lambda self, *args, **kwargs: self._get_mailing_model_groupeurd(*args, **kwargs)
|
|
||||||
|
|
||||||
#_columns = {
|
# indirections for inheritance
|
||||||
# recipients
|
#_mailing_model = lambda self, *args, **kwargs: self._get_mailing_model_groupeurd(*args, **kwargs)
|
||||||
# 'mailing_model': fields.selection(_mailing_model, string='Recipients Model', required=True)
|
|
||||||
#}
|
|
||||||
|
|
||||||
#def action_edit_html(self, cr, uid, ids, context=None):
|
#_columns = {
|
||||||
# if not len(ids) == 1:
|
# recipients
|
||||||
# raise ValueError('One and only one ID allowed for this action')
|
# 'mailing_model': fields.selection(_mailing_model, string='Recipients Model', required=True)
|
||||||
# mail = self.browse(cr, uid, ids[0], context=context)
|
#}
|
||||||
|
|
||||||
# if mail.mailing_model == 'mail.mass_mailing.contact' :
|
#def action_edit_html(self, cr, uid, ids, context=None):
|
||||||
# template_model = 'mail.tracking.email'
|
# if not len(ids) == 1:
|
||||||
# else:
|
# raise ValueError('One and only one ID allowed for this action')
|
||||||
# template_model = mail.mailing_model
|
# mail = self.browse(cr, uid, ids[0], context=context)
|
||||||
|
|
||||||
|
# if mail.mailing_model == 'mail.mass_mailing.contact' :
|
||||||
#url = '/website_mail/email_designer?model=mail.mass_mailing&res_id=%d&template_model=%s&return_action=%d&enable_editor=1' % (ids[0], mail.mailing_model, context['params']['action'])
|
# template_model = 'mail.tracking.email'
|
||||||
# url = '/website_mail/email_designer?model=mail.mass_mailing&res_id=%d&template_model=%s&return_action=%d&enable_editor=1' % (ids[0], template_model, context['params']['action'])
|
# else:
|
||||||
# return {
|
# template_model = mail.mailing_model
|
||||||
# 'name': _('Open with Visual Editor'),
|
|
||||||
# 'type': 'ir.actions.act_url',
|
|
||||||
# 'url': url,
|
#url = '/website_mail/email_designer?model=mail.mass_mailing&res_id=%d&template_model=%s&return_action=%d&enable_editor=1' % (ids[0], mail.mailing_model, context['params']['action'])
|
||||||
# 'target': 'self',
|
# url = '/website_mail/email_designer?model=mail.mass_mailing&res_id=%d&template_model=%s&return_action=%d&enable_editor=1' % (ids[0], template_model, context['params']['action'])
|
||||||
# }
|
# return {
|
||||||
|
# 'name': _('Open with Visual Editor'),
|
||||||
|
# 'type': 'ir.actions.act_url',
|
||||||
|
# 'url': url,
|
||||||
|
# 'target': 'self',
|
||||||
|
# }
|
||||||
|
Loading…
Reference in New Issue
Block a user