diff --git a/groupeurd_newsletter/__openerp__.py b/groupeurd_newsletter/__openerp__.py index 945e569..61c24f7 100644 --- a/groupeurd_newsletter/__openerp__.py +++ b/groupeurd_newsletter/__openerp__.py @@ -21,7 +21,7 @@ - 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é - Ajouter automatiquement un lien de désinscription s'il n'est pas ajouté manuellement - + 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. - 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 # for the full list 'category': 'Marketing', - 'version': '0.5', + 'version': '8.0.0.5.1', # any module necessary for this one to work correctly 'depends': ['base','mass_mailing','marketing','website_mail'], @@ -49,4 +49,4 @@ 'newsletter-en-template.xml', 'snippets.xml', ], -} \ No newline at end of file +} diff --git a/groupeurd_newsletter/migrations/8.0.0.5.1/post-migrate.py b/groupeurd_newsletter/migrations/8.0.0.5.1/post-migrate.py new file mode 100644 index 0000000..a788ae9 --- /dev/null +++ b/groupeurd_newsletter/migrations/8.0.0.5.1/post-migrate.py @@ -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''') diff --git a/groupeurd_newsletter/models.py b/groupeurd_newsletter/models.py index 98dd6b4..77a93e1 100644 --- a/groupeurd_newsletter/models.py +++ b/groupeurd_newsletter/models.py @@ -2,6 +2,7 @@ import urlparse import werkzeug.urls +import logging from openerp import models, fields, api from openerp.osv import osv @@ -9,175 +10,198 @@ from openerp.osv import osv from openerp import tools from openerp.tools.translate import _ -import logging _logger = logging.getLogger(__name__) # Overrides mass mailing Contact for this module purpose class contact(models.Model): - _name = "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") + _name = "mail.mass_mailing.contact" + _inherit = "mail.mass_mailing.contact" - _sql_constraints = [ - ('email_list_unique', - 'unique (email, list_id)', - _('Subscriber already registered for this mailing list.') - )] - - @api.onchange("opt_out") - def on_change_opt_out(self): - if self.opt_out: - self.unsubscription_date = fields.Datetime.now() - self.unsubscribed_by_odoo_user = self.env.user - else: - self.unsubscription_date = None - self.unsubscribed_by_odoo_user = None - + unsubscription_date = fields.Date(string="Unsubscription date") + unsubscribed_by_odoo_user = fields.Many2one("res.users", string="Unsubscribed by this Odoo user") + + # _sql_constraints = [ + # ('email_list_unique', + # 'unique (email, list_id)', + # _('Subscriber already registered for this mailing list.') + # )] + + @api.onchange("opt_out") + def on_change_opt_out(self): + if self.opt_out: + self.unsubscription_date = fields.Datetime.now() + 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): - """Add the mass mailing campaign data to mail""" - _name = 'mail.mail' - _inherit = ['mail.mail'] + """Add the mass mailing campaign data to mail""" + _name = 'mail.mail' + _inherit = ['mail.mail'] - def _get_unsubscribe_url(self, cr, uid, mail, email_to, msg=None, context=None): - if 'mass_mailing_test' in context: - base_url = self.pool.get('ir.config_parameter').get_param(cr, uid, 'web.base.url') - else: - base_url = "" - url = urlparse.urljoin( - base_url, 'mail/mailing/%(mailing_id)s/unsubscribe?%(params)s' % { - 'mailing_id': mail.mailing_id.id, - 'params': werkzeug.url_encode({'db': cr.dbname, 'res_id': mail.res_id, 'email': email_to}) - } - ) - return '%s' % url + def _get_unsubscribe_url(self, cr, uid, mail, email_to, msg=None, context=None): + if 'mass_mailing_test' in context: + base_url = self.pool.get('ir.config_parameter').get_param(cr, uid, 'web.base.url') + else: + base_url = "" + url = urlparse.urljoin( + base_url, 'mail/mailing/%(mailing_id)s/unsubscribe?%(params)s' % { + 'mailing_id': mail.mailing_id.id, + 'params': werkzeug.url_encode({'db': cr.dbname, 'res_id': mail.res_id, 'email': email_to}) + } + ) + return '%s' % url - def _get_html_version_url(self, cr, uid, mail, email_to, context=None): - if 'mass_mailing_test' in context: - base_url = self.pool.get('ir.config_parameter').get_param(cr, uid, 'web.base.url') - else: - base_url = "" - url = urlparse.urljoin(base_url, 'newsletter/html_version_%s' % mail.mailing_id.id) - return '%s' % url + def _get_html_version_url(self, cr, uid, mail, email_to, context=None): + if 'mass_mailing_test' in context: + base_url = self.pool.get('ir.config_parameter').get_param(cr, uid, 'web.base.url') + else: + base_url = "" + url = urlparse.urljoin(base_url, 'newsletter/html_version_%s' % mail.mailing_id.id) + return '%s' % url - 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) - body = self.send_get_mail_body(cr, uid, mail, partner=partner, context=context) - - if mail.mailing_id and body and email_to: - emails = tools.email_split(email_to[0]) - has_email_to = emails and emails[0] or False - unsubscribe_url = self._get_unsubscribe_url(cr, uid, mail, has_email_to, context=context) - if unsubscribe_url: - if body.count('__UNSUBSCRIBE_URL__') > 0: - body = body.replace('__UNSUBSCRIBE_URL__', unsubscribe_url) - else: - unsubscribe_link = '%s' % (unsubscribe_url, _('Click to unsubscribe')) - 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) - body = body.replace('__HTML_VERSION_URL__', html_version_url) - - body_alternative = tools.html2plaintext(body) - - res = { - 'body': body, - 'body_alternative': body_alternative, - 'subject': self.send_get_mail_subject(cr, uid, mail, partner=partner, context=context), - 'email_to': email_to, - } - - return res + 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) + body = self.send_get_mail_body(cr, uid, mail, partner=partner, context=context) + + if mail.mailing_id and body and email_to: + emails = tools.email_split(email_to[0]) + has_email_to = emails and emails[0] or False + unsubscribe_url = self._get_unsubscribe_url(cr, uid, mail, has_email_to, context=context) + if unsubscribe_url: + if body.count('__UNSUBSCRIBE_URL__') > 0: + body = body.replace('__UNSUBSCRIBE_URL__', unsubscribe_url) + else: + unsubscribe_link = '%s' % (unsubscribe_url, _('Click to unsubscribe')) + 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) + body = body.replace('__HTML_VERSION_URL__', html_version_url) + + body_alternative = tools.html2plaintext(body) + + res = { + 'body': body, + 'body_alternative': body_alternative, + 'subject': self.send_get_mail_subject(cr, uid, mail, partner=partner, context=context), + 'email_to': email_to, + } + + return res class TestMassMailing(osv.TransientModel): - _name = 'mail.mass_mailing.test' - _description = 'Sample Mail Wizard' + _name = 'mail.mass_mailing.test' + _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)) - mass_mailing_id = fields.Many2one('mail.mass_mailing', 'Mailing', required=True, ondelete='cascade') + 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') + + 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 = '%s' % (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 = '%s' % (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): - #_name = "mail.mass_mailing" - #_inherit = "mail.mass_mailing" + #_name = "mail.mass_mailing" + #_inherit = "mail.mass_mailing" - #def _get_mailing_model(self, cr, uid, context=None): - # res = super(MassMailing, self)._get_mailing_model(cr, uid, context) - # res.append(('mail.tracking.email', _('Email Tracking'))) - # print res - # return res - - # indirections for inheritance - #_mailing_model = lambda self, *args, **kwargs: self._get_mailing_model_groupeurd(*args, **kwargs) + #def _get_mailing_model(self, cr, uid, context=None): + # res = super(MassMailing, self)._get_mailing_model(cr, uid, context) + # res.append(('mail.tracking.email', _('Email Tracking'))) + # print res + # return res - #_columns = { - # recipients - # 'mailing_model': fields.selection(_mailing_model, string='Recipients Model', required=True) - #} + # indirections for inheritance + #_mailing_model = lambda self, *args, **kwargs: self._get_mailing_model_groupeurd(*args, **kwargs) - #def action_edit_html(self, cr, uid, ids, context=None): - # if not len(ids) == 1: - # raise ValueError('One and only one ID allowed for this action') - # mail = self.browse(cr, uid, ids[0], context=context) - - # if mail.mailing_model == 'mail.mass_mailing.contact' : - # template_model = 'mail.tracking.email' - # else: - # template_model = mail.mailing_model - - - #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']) - # 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', - # } \ No newline at end of file + #_columns = { + # recipients + # 'mailing_model': fields.selection(_mailing_model, string='Recipients Model', required=True) + #} + + #def action_edit_html(self, cr, uid, ids, context=None): + # if not len(ids) == 1: + # raise ValueError('One and only one ID allowed for this action') + # mail = self.browse(cr, uid, ids[0], context=context) + + # if mail.mailing_model == 'mail.mass_mailing.contact' : + # template_model = 'mail.tracking.email' + # else: + # template_model = mail.mailing_model + + + #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']) + # 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', + # }