Emanuel Cino
8 years ago
15 changed files with 659 additions and 0 deletions
-
61mail_sendgrid_mass_mailing/README.rst
-
13mail_sendgrid_mass_mailing/__init__.py
-
47mail_sendgrid_mass_mailing/__openerp__.py
-
14mail_sendgrid_mass_mailing/models/__init__.py
-
39mail_sendgrid_mass_mailing/models/email_tracking.py
-
66mail_sendgrid_mass_mailing/models/mail_mail.py
-
135mail_sendgrid_mass_mailing/models/mass_mailing.py
-
BINmail_sendgrid_mass_mailing/static/description/icon.png
-
10mail_sendgrid_mass_mailing/static/description/icon.svg
-
12mail_sendgrid_mass_mailing/tests/__init__.py
-
123mail_sendgrid_mass_mailing/tests/test_mass_mailing.py
-
31mail_sendgrid_mass_mailing/views/mass_mailing_view.xml
-
13mail_sendgrid_mass_mailing/wizards/__init__.py
-
40mail_sendgrid_mass_mailing/wizards/mail_compose_message.py
-
55mail_sendgrid_mass_mailing/wizards/test_mailing.py
@ -0,0 +1,61 @@ |
|||||
|
.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg |
||||
|
:alt: License: AGPL-3 |
||||
|
|
||||
|
========================= |
||||
|
SendGrid for mass mailing |
||||
|
========================= |
||||
|
|
||||
|
Links mass mailing and mail statistics objects with Sendgrid. |
||||
|
Note that the mass mailing campaign will be sent with Sendgrid transactional |
||||
|
e-emails (not to mix up with Sendgrid marketing campaigns) |
||||
|
|
||||
|
Installation |
||||
|
============ |
||||
|
This addon will be automatically installed when 'mail_sendgrid' and |
||||
|
'mass_mailing' are both installed. |
||||
|
|
||||
|
Usage |
||||
|
===== |
||||
|
|
||||
|
From mass mailing, you can use Sendgrid templates. |
||||
|
|
||||
|
- If you select a Sendgrid template, the campaign will be sent through |
||||
|
Sendgrid. Otherwise it will use what you set in your system preference |
||||
|
(see module sendgrid). |
||||
|
- You can force usage of a language for the template. |
||||
|
|
||||
|
Known issues / Roadmap |
||||
|
====================== |
||||
|
|
||||
|
* Use Sendgrid marketing campaigns API |
||||
|
|
||||
|
Bug Tracker |
||||
|
=========== |
||||
|
|
||||
|
Bugs are tracked on `GitHub Issues <https://github.com/OCA/social/issues>`_. |
||||
|
In case of trouble, please check there if your issue has already been reported. |
||||
|
If you spotted it first, help us smashing it by providing a detailed and welcomed feedback |
||||
|
`here <https://github.com/OCA/social/issues/new?body=module:%20mail_sendgrid_mass_mailing%0Aversion:%208.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_. |
||||
|
|
||||
|
Credits |
||||
|
======= |
||||
|
|
||||
|
Contributors |
||||
|
------------ |
||||
|
|
||||
|
* Emanuel Cino <ecino@compassion.ch> |
||||
|
|
||||
|
Maintainer |
||||
|
---------- |
||||
|
|
||||
|
.. image:: https://odoo-community.org/logo.png |
||||
|
:alt: Odoo Community Association |
||||
|
:target: https://odoo-community.org |
||||
|
|
||||
|
This module is maintained by the OCA. |
||||
|
|
||||
|
OCA, or the Odoo Community Association, is a nonprofit organization whose |
||||
|
mission is to support the collaborative development of Odoo features and |
||||
|
promote its widespread use. |
||||
|
|
||||
|
To contribute to this module, please visit http://odoo-community.org. |
@ -0,0 +1,13 @@ |
|||||
|
# -*- encoding: utf-8 -*- |
||||
|
############################################################################## |
||||
|
# |
||||
|
# Copyright (C) 2016 Compassion CH (http://www.compassion.ch) |
||||
|
# Releasing children from poverty in Jesus' name |
||||
|
# @author: Emanuel Cino |
||||
|
# |
||||
|
# The licence is in the file __openerp__.py |
||||
|
# |
||||
|
############################################################################## |
||||
|
|
||||
|
from . import models |
||||
|
from . import wizards |
@ -0,0 +1,47 @@ |
|||||
|
# -*- encoding: utf-8 -*- |
||||
|
############################################################################## |
||||
|
# |
||||
|
# ______ Releasing children from poverty _ |
||||
|
# / ____/___ ____ ___ ____ ____ ___________(_)___ ____ |
||||
|
# / / / __ \/ __ `__ \/ __ \/ __ `/ ___/ ___/ / __ \/ __ \ |
||||
|
# / /___/ /_/ / / / / / / /_/ / /_/ (__ |__ ) / /_/ / / / / |
||||
|
# \____/\____/_/ /_/ /_/ .___/\__,_/____/____/_/\____/_/ /_/ |
||||
|
# /_/ |
||||
|
# in Jesus' name |
||||
|
# |
||||
|
# Copyright (C) 2016 Compassion CH (http://www.compassion.ch) |
||||
|
# @author: Emanuel Cino <ecino@compassion.ch> |
||||
|
# |
||||
|
# This program is free software: you can redistribute it and/or modify |
||||
|
# it under the terms of the GNU Affero 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 Affero General Public License for more details. |
||||
|
# |
||||
|
# You should have received a copy of the GNU Affero General Public License |
||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>. |
||||
|
# |
||||
|
############################################################################## |
||||
|
|
||||
|
|
||||
|
{ |
||||
|
'name': 'Mass Mailing with SendGrid', |
||||
|
'version': '9.0.1.0.0', |
||||
|
'category': 'Social Network', |
||||
|
'author': 'Compassion CH', |
||||
|
'website': 'http://www.compassion.ch', |
||||
|
'depends': ['mail_sendgrid', 'mail_tracking_mass_mailing'], |
||||
|
'data': [ |
||||
|
'views/mass_mailing_view.xml' |
||||
|
], |
||||
|
'demo': [], |
||||
|
'installable': True, |
||||
|
'auto_install': True, |
||||
|
'external_dependencies': { |
||||
|
'python': ['sendgrid'], |
||||
|
}, |
||||
|
} |
@ -0,0 +1,14 @@ |
|||||
|
# -*- encoding: utf-8 -*- |
||||
|
############################################################################## |
||||
|
# |
||||
|
# Copyright (C) 2016 Compassion CH (http://www.compassion.ch) |
||||
|
# Releasing children from poverty in Jesus' name |
||||
|
# @author: Emanuel Cino |
||||
|
# |
||||
|
# The licence is in the file __openerp__.py |
||||
|
# |
||||
|
############################################################################## |
||||
|
|
||||
|
from . import mass_mailing |
||||
|
from . import mail_mail |
||||
|
from . import email_tracking |
@ -0,0 +1,39 @@ |
|||||
|
# -*- encoding: utf-8 -*- |
||||
|
############################################################################## |
||||
|
# |
||||
|
# Copyright (C) 2016 Compassion CH (http://www.compassion.ch) |
||||
|
# Releasing children from poverty in Jesus' name |
||||
|
# @author: Emanuel Cino <ecino@compassion.ch> |
||||
|
# |
||||
|
# The licence is in the file __openerp__.py |
||||
|
# |
||||
|
############################################################################## |
||||
|
from openerp import models, fields, api |
||||
|
|
||||
|
|
||||
|
class MailTrackingEvent(models.Model): |
||||
|
""" Push events to campaign_statistics |
||||
|
""" |
||||
|
_inherit = 'mail.tracking.event' |
||||
|
|
||||
|
@api.model |
||||
|
def process_delivered(self, tracking_email, metadata): |
||||
|
res = super(MailTrackingEvent, self).process_delivered( |
||||
|
tracking_email, metadata) |
||||
|
mail_mail_stats = self.sudo().env['mail.mail.statistics'].search([ |
||||
|
('mail_mail_id_int', '=', tracking_email.mail_id_int)]) |
||||
|
mail_mail_stats.write({ |
||||
|
'sent': fields.Datetime.now() |
||||
|
}) |
||||
|
return res |
||||
|
|
||||
|
@api.model |
||||
|
def process_reject(self, tracking_email, metadata): |
||||
|
res = super(MailTrackingEvent, self).process_reject( |
||||
|
tracking_email, metadata) |
||||
|
mail_mail_stats = self.sudo().env['mail.mail.statistics'].search([ |
||||
|
('mail_mail_id_int', '=', tracking_email.mail_id_int)]) |
||||
|
mail_mail_stats.write({ |
||||
|
'exception': fields.Datetime.now() |
||||
|
}) |
||||
|
return res |
@ -0,0 +1,66 @@ |
|||||
|
# -*- encoding: utf-8 -*- |
||||
|
############################################################################## |
||||
|
# |
||||
|
# Copyright (C) 2016 Compassion CH (http://www.compassion.ch) |
||||
|
# Releasing children from poverty in Jesus' name |
||||
|
# @author: Emanuel Cino <ecino@compassion.ch> |
||||
|
# |
||||
|
# The licence is in the file __openerp__.py |
||||
|
# |
||||
|
############################################################################## |
||||
|
from openerp import models |
||||
|
import logging |
||||
|
|
||||
|
_logger = logging.getLogger(__name__) |
||||
|
|
||||
|
try: |
||||
|
from sendgrid.helpers.mail.mail import TrackingSettings, \ |
||||
|
SubscriptionTracking |
||||
|
except ImportError: |
||||
|
_logger.error("ImportError raised while loading module.") |
||||
|
_logger.debug("ImportError details:", exc_info=True) |
||||
|
|
||||
|
|
||||
|
class MailMail(models.Model): |
||||
|
_inherit = "mail.mail" |
||||
|
|
||||
|
def _prepare_sendgrid_tracking(self): |
||||
|
track_vals = super(MailMail, self)._prepare_sendgrid_tracking() |
||||
|
track_vals.update({ |
||||
|
'mail_id_int': self.id, |
||||
|
'mass_mailing_id': self.mailing_id.id, |
||||
|
'mail_stats_id': self.statistics_ids[:1].id |
||||
|
if self.statistics_ids else False |
||||
|
}) |
||||
|
return track_vals |
||||
|
|
||||
|
def _track_sendgrid_emails(self): |
||||
|
""" Push tracking_email in mass_mail_statistic """ |
||||
|
tracking_emails = super(MailMail, self)._track_sendgrid_emails() |
||||
|
for tracking in tracking_emails.filtered('mail_stats_id'): |
||||
|
tracking.mail_stats_id.mail_tracking_id = tracking.id |
||||
|
return tracking_emails |
||||
|
|
||||
|
def _prepare_sendgrid_data(self): |
||||
|
""" |
||||
|
Add unsubscribe options in mass mailings |
||||
|
:return: Sendgrid Email |
||||
|
""" |
||||
|
s_mail = super(MailMail, self)._prepare_sendgrid_data() |
||||
|
tracking_settings = TrackingSettings() |
||||
|
if self.mailing_id.enable_unsubscribe: |
||||
|
sub_settings = SubscriptionTracking( |
||||
|
enable=True, |
||||
|
text=self.mailing_id.unsubscribe_text, |
||||
|
html=self.mailing_id.unsubscribe_text, |
||||
|
) |
||||
|
if self.mailing_id.unsubscribe_tag: |
||||
|
sub_settings.substitution_tag = \ |
||||
|
self.mailing_id.unsubscribe_tag |
||||
|
tracking_settings.subscription_tracking = sub_settings |
||||
|
else: |
||||
|
tracking_settings.subscription_tracking = SubscriptionTracking( |
||||
|
enable=False) |
||||
|
|
||||
|
s_mail.tracking_settings = tracking_settings |
||||
|
return s_mail |
@ -0,0 +1,135 @@ |
|||||
|
# -*- encoding: utf-8 -*- |
||||
|
############################################################################## |
||||
|
# |
||||
|
# Copyright (C) 2016 Compassion CH (http://www.compassion.ch) |
||||
|
# Releasing children from poverty in Jesus' name |
||||
|
# @author: Emanuel Cino |
||||
|
# |
||||
|
# The licence is in the file __openerp__.py |
||||
|
# |
||||
|
############################################################################## |
||||
|
|
||||
|
from openerp import api, models, fields, _ |
||||
|
from openerp.exceptions import Warning as UserError |
||||
|
from openerp.tools.safe_eval import safe_eval |
||||
|
|
||||
|
|
||||
|
class MassMailing(models.Model): |
||||
|
""" Add a direct link to an e-mail template in order to retrieve all |
||||
|
Sendgrid configuration into the e-mails. Add ability to force a |
||||
|
template language. |
||||
|
""" |
||||
|
_inherit = 'mail.mass_mailing' |
||||
|
|
||||
|
email_template_id = fields.Many2one( |
||||
|
'mail.template', 'Sengdrid Template', |
||||
|
) |
||||
|
lang = fields.Many2one( |
||||
|
comodel_name="res.lang", string="Force language") |
||||
|
body_sendgrid = fields.Html(compute='_compute_sendgrid_view') |
||||
|
# Trick to save html when taken from the e-mail template |
||||
|
html_copy = fields.Html( |
||||
|
compute='_compute_sendgrid_view', inverse='_inverse_html_copy') |
||||
|
enable_unsubscribe = fields.Boolean() |
||||
|
unsubscribe_text = fields.Char( |
||||
|
default='If you would like to unsubscribe and stop receiving these ' |
||||
|
'emails <% clickhere %>.') |
||||
|
unsubscribe_tag = fields.Char() |
||||
|
|
||||
|
@api.depends('body_html') |
||||
|
def _compute_sendgrid_view(self): |
||||
|
for wizard in self: |
||||
|
template = wizard.email_template_id.with_context( |
||||
|
lang=self.lang.code or self.env.context['lang']) |
||||
|
sendgrid_template = template.sendgrid_localized_template |
||||
|
if sendgrid_template and wizard.body_html: |
||||
|
res_id = self.env[wizard.mailing_model].search(safe_eval( |
||||
|
wizard.mailing_domain), limit=1).id |
||||
|
if res_id: |
||||
|
body = template.render_template( |
||||
|
wizard.body_html, template.model, [res_id], |
||||
|
post_process=True)[res_id] |
||||
|
wizard.body_sendgrid = \ |
||||
|
sendgrid_template.html_content.replace('<%body%>', |
||||
|
body) |
||||
|
else: |
||||
|
wizard.body_sendgrid = wizard.body_html |
||||
|
wizard.html_copy = wizard.body_html |
||||
|
|
||||
|
def _inverse_html_copy(self): |
||||
|
for wizard in self: |
||||
|
wizard.body_html = wizard.html_copy |
||||
|
|
||||
|
@api.onchange('email_template_id') |
||||
|
def onchange_email_template_id(self): |
||||
|
if self.email_template_id: |
||||
|
template = self.email_template_id.with_context( |
||||
|
lang=self.lang.code or self.env.context['lang']) |
||||
|
if template.email_from: |
||||
|
self.email_from = template.email_from |
||||
|
self.name = template.subject |
||||
|
self.body_html = template.body_html |
||||
|
|
||||
|
@api.onchange('lang') |
||||
|
def onchange_lang(self): |
||||
|
if self.lang and self.mailing_model == 'res.partner': |
||||
|
domain = safe_eval(self.mailing_domain) |
||||
|
lang_tuple = False |
||||
|
for tuple in domain: |
||||
|
if tuple[0] == 'lang': |
||||
|
lang_tuple = tuple |
||||
|
break |
||||
|
if lang_tuple: |
||||
|
domain.remove(lang_tuple) |
||||
|
domain.append(('lang', '=', self.lang.code)) |
||||
|
self.mailing_domain = str(domain) |
||||
|
self.onchange_email_template_id() |
||||
|
|
||||
|
@api.multi |
||||
|
def action_test_mailing(self): |
||||
|
wizard = self |
||||
|
if self.email_template_id: |
||||
|
wizard = self.with_context( |
||||
|
lang=self.lang.code or self.env.context['lang']) |
||||
|
return super(MassMailing, wizard).action_test_mailing() |
||||
|
|
||||
|
@api.multi |
||||
|
def send_mail(self): |
||||
|
self.ensure_one() |
||||
|
if self.email_template_id: |
||||
|
# use E-mail Template |
||||
|
res_ids = self.get_recipients(self) |
||||
|
if not res_ids: |
||||
|
raise UserError(_('Please select recipients.')) |
||||
|
template = self.email_template_id |
||||
|
composer_values = { |
||||
|
'template_id': template.id, |
||||
|
'composition_mode': 'mass_mail', |
||||
|
'model': template.model, |
||||
|
'author_id': self.env.user.partner_id.id, |
||||
|
'res_id': res_ids[0], |
||||
|
'attachment_ids': [(4, attachment.id) for attachment in |
||||
|
self.attachment_ids], |
||||
|
'email_from': self.email_from, |
||||
|
'body': self.body_html, |
||||
|
'subject': self.name, |
||||
|
'record_name': False, |
||||
|
'mass_mailing_id': self.id, |
||||
|
'mailing_list_ids': [(4, l.id) for l in |
||||
|
self.contact_list_ids], |
||||
|
'no_auto_thread': self.reply_to_mode != 'thread', |
||||
|
} |
||||
|
if self.reply_to_mode == 'email': |
||||
|
composer_values['reply_to'] = self.reply_to |
||||
|
composer = self.env['mail.compose.message'].with_context( |
||||
|
lang=self.lang.code or self.env.context.get('lang', 'en_US'), |
||||
|
active_ids=res_ids) |
||||
|
emails = composer.mass_mailing_sendgrid(res_ids, composer_values) |
||||
|
self.write({ |
||||
|
'state': 'done', |
||||
|
'sent_date': fields.Datetime.now(), |
||||
|
}) |
||||
|
return emails |
||||
|
else: |
||||
|
# Traditional sending |
||||
|
return super(MassMailing, self).send_mail() |
After Width: 128 | Height: 128 | Size: 3.1 KiB |
@ -0,0 +1,10 @@ |
|||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?> |
||||
|
<svg width="256px" height="256px" viewBox="0 0 256 256" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" preserveAspectRatio="xMidYMid"> |
||||
|
<g> |
||||
|
<polygon fill="#9DE1F3" points="85.3335 85.333 0.0005 85.333 0.0005 170.666 0.0005 256 85.3335 256 170.6665 256 170.6665 170.666 170.6665 85.333"></polygon> |
||||
|
<polygon fill="#27B4E1" points="85.3335 0.0004 85.3335 85.3334 85.3335 170.6664 170.6665 170.6664 255.9995 170.6664 255.9995 0.0004"></polygon> |
||||
|
<polygon fill="#1A82E2" points="0 256 85.333 256 85.333 170.667 0 170.667"></polygon> |
||||
|
<polygon fill="#1A82E2" points="170.667 85.333 256 85.333 256 0 170.667 0"></polygon> |
||||
|
<polygon fill="#239FD7" points="85.334 170.667 170.667 170.667 170.667 85.334 85.334 85.334"></polygon> |
||||
|
</g> |
||||
|
</svg> |
@ -0,0 +1,12 @@ |
|||||
|
# -*- encoding: utf-8 -*- |
||||
|
############################################################################## |
||||
|
# |
||||
|
# Copyright (C) 2017 Compassion CH (http://www.compassion.ch) |
||||
|
# Releasing children from poverty in Jesus' name |
||||
|
# @author: Emanuel Cino |
||||
|
# |
||||
|
# The licence is in the file __openerp__.py |
||||
|
# |
||||
|
############################################################################## |
||||
|
|
||||
|
from . import test_mass_mailing |
@ -0,0 +1,123 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
# © 2017 Emanuel Cino - <ecino@compassion.ch> |
||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
||||
|
import mock |
||||
|
from openerp.tests.common import TransactionCase |
||||
|
|
||||
|
mock_sendgrid_api_client = ('openerp.addons.mail_sendgrid.models.mail_mail' |
||||
|
'.SendGridAPIClient') |
||||
|
mock_config = ('openerp.addons.mail_sendgrid.models.mail_mail.' |
||||
|
'config') |
||||
|
|
||||
|
|
||||
|
class FakeClient(object): |
||||
|
""" Mock Sendgrid APIClient """ |
||||
|
status_code = 202 |
||||
|
body = 'ok' |
||||
|
|
||||
|
def __init__(self): |
||||
|
self.client = self |
||||
|
self.mail = self |
||||
|
self.send = self |
||||
|
|
||||
|
def post(self, **kwargs): |
||||
|
return self |
||||
|
|
||||
|
|
||||
|
class FakeRequest(object): |
||||
|
""" Simulate a Sendgrid JSON request """ |
||||
|
def __init__(self, data): |
||||
|
self.jsonrequest = [data] |
||||
|
|
||||
|
|
||||
|
class TestMailSendgrid(TransactionCase): |
||||
|
def setUp(self): |
||||
|
super(TestMailSendgrid, self).setUp() |
||||
|
self.sendgrid_template = self.env['sendgrid.template'].create({ |
||||
|
'name': 'Test Template', |
||||
|
'remote_id': 'a74795d7-f926-4bad-8e7a-ae95fabd70fc', |
||||
|
'html_content': u'<h1>Test Sendgrid</h1><%body%>{footer}' |
||||
|
}) |
||||
|
self.mail_template = self.env['mail.template'].create({ |
||||
|
'name': 'Test Template', |
||||
|
'model_id': self.env.ref('base.model_res_partner').id, |
||||
|
'subject': 'Test e-mail', |
||||
|
'body_html': u'Dear ${object.name}, hello!', |
||||
|
'sendgrid_template_ids': [ |
||||
|
(0, 0, {'lang': 'en_US', 'sendgrid_template_id': |
||||
|
self.sendgrid_template.id})] |
||||
|
}) |
||||
|
self.recipient = self.env.ref('base.partner_demo') |
||||
|
self.mass_mailing = self.env['mail.mass_mailing'].create({ |
||||
|
'email_from': 'admin@yourcompany.example.com', |
||||
|
'name': 'Test Mass Mailing Sendgrid', |
||||
|
'mailing_model': 'res.partner', |
||||
|
'mailing_domain': "[('id', '=', %d)]" % self.recipient.id, |
||||
|
'email_template_id': self.mail_template.id, |
||||
|
'body_html': u'Dear ${object.name}, hello!', |
||||
|
'reply_to_mode': 'thread', |
||||
|
}) |
||||
|
self.timestamp = u'1471021089' |
||||
|
self.event = { |
||||
|
'timestamp': self.timestamp, |
||||
|
'sg_event_id': u"f_JoKtrLQaOXUc4thXgROg", |
||||
|
'email': self.recipient.email, |
||||
|
'odoo_db': self.env.cr.dbname, |
||||
|
'odoo_id': u'<xxx.xxx.xxx-openerp-xxx-res.partner@test_db>' |
||||
|
} |
||||
|
self.metadata = { |
||||
|
'ip': '127.0.0.1', |
||||
|
'user_agent': False, |
||||
|
'os_family': False, |
||||
|
'ua_family': False, |
||||
|
} |
||||
|
self.request = FakeRequest(self.event) |
||||
|
|
||||
|
@mock.patch(mock_sendgrid_api_client) |
||||
|
@mock.patch(mock_config) |
||||
|
def test_send_campaign(self, m_config, mock_sendgrid): |
||||
|
""" |
||||
|
Test sending mass campaign with Sendgrid template |
||||
|
and statistics update |
||||
|
""" |
||||
|
self.env['ir.config_parameter'].set_param( |
||||
|
'mail_sendgrid.send_method', 'sendgrid') |
||||
|
mock_sendgrid.return_value = FakeClient() |
||||
|
m_config.get.return_value = 'we4iorujeriu' |
||||
|
emails = self.mass_mailing.send_mail() |
||||
|
self.assertEqual(len(emails), 1) |
||||
|
self.assertEqual(emails.state, 'outgoing') |
||||
|
self.assertEqual(emails.sendgrid_template_id.id, |
||||
|
self.sendgrid_template.id) |
||||
|
|
||||
|
emails.send() |
||||
|
self.assertTrue(mock_sendgrid.called) |
||||
|
self.assertEqual(emails.state, 'sent') |
||||
|
mail_tracking = emails.tracking_email_ids |
||||
|
self.assertEqual(len(mail_tracking), 1) |
||||
|
self.assertFalse(mail_tracking.state) |
||||
|
stats = self.mass_mailing.statistics_ids |
||||
|
self.assertEqual(len(stats), 1) |
||||
|
self.assertFalse(stats.sent) |
||||
|
|
||||
|
# Test delivered |
||||
|
self.event.update({ |
||||
|
'event': 'delivered', |
||||
|
'odoo_id': emails.message_id |
||||
|
}) |
||||
|
self.env['mail.tracking.email'].event_process( |
||||
|
self.request, self.event, self.metadata) |
||||
|
self.assertTrue(stats.sent) |
||||
|
|
||||
|
# Test click e-mail |
||||
|
self.event.update({ |
||||
|
'event': 'click', |
||||
|
}) |
||||
|
self.env['mail.tracking.email'].event_process( |
||||
|
self.request, self.event, self.metadata) |
||||
|
self.assertEqual(emails.click_count, 1) |
||||
|
events = stats.tracking_event_ids |
||||
|
self.assertEqual(len(events), 2) |
||||
|
self.assertEqual(events[0].event_type, 'delivered') |
||||
|
self.assertEqual(events[1].event_type, 'click') |
||||
|
self.assertEqual(stats.state, 'sent') |
@ -0,0 +1,31 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<openerp> |
||||
|
<data> |
||||
|
<!-- Form view --> |
||||
|
<record id="view_email_template_sendgrid_form" model="ir.ui.view"> |
||||
|
<field name="name">mass.mailing.sendgrid.form</field> |
||||
|
<field name="model">mail.mass_mailing</field> |
||||
|
<field name="inherit_id" ref="mass_mailing.view_mail_mass_mailing_form"/> |
||||
|
<field name="arch" type="xml"> |
||||
|
<xpath expr="//field[@name='mailing_model']/.." position="after"> |
||||
|
<field name="email_template_id" domain="[('model', '=', mailing_model), ('sendgrid_template_ids', '!=', False)]"/> |
||||
|
<field name="lang" attrs="{'invisible': [('email_template_id', '=', False)]}"/> |
||||
|
</xpath> |
||||
|
<xpath expr="//notebook/page[1]" position="after"> |
||||
|
<page string="Sendgrid Preview" attrs="{'invisible': [('email_template_id', '=', False)]}"> |
||||
|
<field name="html_copy" invisible="1"/> |
||||
|
<field name="body_sendgrid" widget="html"/> |
||||
|
</page> |
||||
|
</xpath> |
||||
|
<xpath expr="//notebook/page/group[1]"> |
||||
|
<group string="Sendgrid Unsubscribe"> |
||||
|
<field name="enable_unsubscribe"/> |
||||
|
<field name="unsubscribe_text" attrs="{'invisible': [('enable_unsubscribe', '=', False)]}"/> |
||||
|
<field name="unsubscribe_tag" attrs="{'invisible': [('enable_unsubscribe', '=', False)]}"/> |
||||
|
</group> |
||||
|
</xpath> |
||||
|
</field> |
||||
|
</record> |
||||
|
|
||||
|
</data> |
||||
|
</openerp> |
@ -0,0 +1,13 @@ |
|||||
|
# -*- encoding: utf-8 -*- |
||||
|
############################################################################## |
||||
|
# |
||||
|
# Copyright (C) 2016 Compassion CH (http://www.compassion.ch) |
||||
|
# Releasing children from poverty in Jesus' name |
||||
|
# @author: Emanuel Cino |
||||
|
# |
||||
|
# The licence is in the file __openerp__.py |
||||
|
# |
||||
|
############################################################################## |
||||
|
|
||||
|
from . import mail_compose_message |
||||
|
from . import test_mailing |
@ -0,0 +1,40 @@ |
|||||
|
# -*- encoding: utf-8 -*- |
||||
|
############################################################################## |
||||
|
# |
||||
|
# Copyright (C) 2016 Compassion CH (http://www.compassion.ch) |
||||
|
# Releasing children from poverty in Jesus' name |
||||
|
# @author: Emanuel Cino <ecino@compassion.ch> |
||||
|
# |
||||
|
# The licence is in the file __openerp__.py |
||||
|
# |
||||
|
############################################################################## |
||||
|
|
||||
|
from openerp import models, api |
||||
|
|
||||
|
|
||||
|
class EmailComposeMessage(models.TransientModel): |
||||
|
_inherit = 'mail.compose.message' |
||||
|
|
||||
|
@api.model |
||||
|
def mass_mailing_sendgrid(self, res_ids, composer_values): |
||||
|
""" Helper to generate a new e-mail given a template and objects. |
||||
|
|
||||
|
:param res_ids: ids of the resource objects |
||||
|
:param composer_values: values for the composer wizard |
||||
|
:return: browse records of created e-mails (one per resource object) |
||||
|
""" |
||||
|
if not isinstance(res_ids, list): |
||||
|
res_ids = [res_ids] |
||||
|
wizard = self.create(composer_values) |
||||
|
all_mail_values = wizard.get_mail_values(res_ids) |
||||
|
email_obj = self.env['mail.mail'] |
||||
|
emails = email_obj |
||||
|
for res_id in res_ids: |
||||
|
mail_values = all_mail_values[res_id] |
||||
|
obj = self.env[wizard.model].browse(res_id) |
||||
|
if wizard.model == 'res.partner': |
||||
|
mail_values['recipient_ids'] = [(6, 0, obj.ids)] |
||||
|
else: |
||||
|
mail_values['email_to'] = obj.email |
||||
|
emails += email_obj.create(mail_values) |
||||
|
return emails |
@ -0,0 +1,55 @@ |
|||||
|
# -*- encoding: utf-8 -*- |
||||
|
############################################################################## |
||||
|
# |
||||
|
# Copyright (C) 2016 Compassion CH (http://www.compassion.ch) |
||||
|
# Releasing children from poverty in Jesus' name |
||||
|
# @author: Emanuel Cino <ecino@compassion.ch> |
||||
|
# |
||||
|
# The licence is in the file __openerp__.py |
||||
|
# |
||||
|
############################################################################## |
||||
|
|
||||
|
from openerp import models, api, tools |
||||
|
|
||||
|
|
||||
|
class TestMassMailing(models.TransientModel): |
||||
|
_inherit = 'mail.mass_mailing.test' |
||||
|
|
||||
|
@api.multi |
||||
|
def send_mail_test(self): |
||||
|
""" Send with Sendgrid if needed. |
||||
|
""" |
||||
|
self.ensure_one() |
||||
|
mailing = self.mass_mailing_id |
||||
|
template = mailing.email_template_id.with_context( |
||||
|
lang=mailing.lang.code or self.env.context['lang']) |
||||
|
if template: |
||||
|
# Send with SendGrid (and use E-mail Template) |
||||
|
sendgrid_template = template.sendgrid_localized_template |
||||
|
res_id = self.env.user.partner_id.id |
||||
|
body = template.render_template( |
||||
|
mailing.body_html, template.model, [res_id], |
||||
|
post_process=True)[res_id] |
||||
|
test_emails = tools.email_split(self.email_to) |
||||
|
emails = self.env['mail.mail'] |
||||
|
for test_mail in test_emails: |
||||
|
email_vals = { |
||||
|
'email_from': mailing.email_from, |
||||
|
'reply_to': mailing.reply_to, |
||||
|
'email_to': test_mail, |
||||
|
'subject': mailing.name, |
||||
|
'body_html': body, |
||||
|
'sendgrid_template_id': sendgrid_template.id, |
||||
|
'substitution_ids': template.render_substitutions( |
||||
|
res_id)[res_id], |
||||
|
'notification': True, |
||||
|
'mailing_id': mailing.id, |
||||
|
'attachment_ids': [(4, attachment.id) for attachment in |
||||
|
mailing.attachment_ids], |
||||
|
} |
||||
|
emails += emails.create(email_vals) |
||||
|
emails.send_sendgrid() |
||||
|
else: |
||||
|
super(TestMassMailing, self).send_mail_test() |
||||
|
|
||||
|
return True |
Write
Preview
Loading…
Cancel
Save
Reference in new issue