From bff806252789ffe29898a6c162f0f1abb63c48a1 Mon Sep 17 00:00:00 2001 From: Antonio Espinosa Date: Mon, 29 Aug 2016 19:11:07 +0200 Subject: [PATCH] Improvements from comments --- mail_tracking_mailgun/README.rst | 14 ++++++------ .../models/ir_mail_server.py | 5 +++-- .../models/mail_tracking_email.py | 22 ++++++++++--------- mail_tracking_mailgun/tests/test_mailgun.py | 13 +++++------ 4 files changed, 28 insertions(+), 26 deletions(-) diff --git a/mail_tracking_mailgun/README.rst b/mail_tracking_mailgun/README.rst index 83d345fe..880d07e2 100644 --- a/mail_tracking_mailgun/README.rst +++ b/mail_tracking_mailgun/README.rst @@ -8,10 +8,10 @@ Mail tracking for Mailgun This module integrates mail_tracking events with Mailgun webhooks. -Mailgun (https://www.mailgun.com/) is a service that provides an e-mail -sending infrastructure through an SMTP server or via API. You can also -query that API for seeing statistics of your sent e-mails, or provide -hooks that processes the status changes in real time, which is the +Mailgun (https://www.mailgun.com/) is a service that provides an e-mail +sending infrastructure through an SMTP server or via API. You can also +query that API for seeing statistics of your sent e-mails, or provide +hooks that processes the status changes in real time, which is the function used here. Configuration @@ -20,14 +20,14 @@ Configuration You must configure Mailgun webhooks in order to receive mail events: 1. Got a Mailgun account and validate your sending domain. -2. Go to Webhook tab and configure this URL for each event you want to track: +2. Go to Webhook tab and configure the below URL for each event: .. code:: html https:///mail/tracking/all/ -Replace '' by your Odoo install domain name -and '' by your database name. +Replace '' with your Odoo install domain name +and '' with your database name. In order to validate Mailgun webhooks you have to save Mailgun api_key in a system parameter named 'mailgun.apikey'. You can find Mailgun api_key in your diff --git a/mail_tracking_mailgun/models/ir_mail_server.py b/mail_tracking_mailgun/models/ir_mail_server.py index 45758df1..2ebb4ce6 100644 --- a/mail_tracking_mailgun/models/ir_mail_server.py +++ b/mail_tracking_mailgun/models/ir_mail_server.py @@ -3,7 +3,6 @@ # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). import json -import threading from openerp import models @@ -15,7 +14,9 @@ class IrMailServer(models.Model): tracking_email_id, headers) headers = headers or {} metadata = { - 'odoo_db': getattr(threading.currentThread(), 'dbname', None), + # NOTE: We can not use 'self.env.cr.dbname' because self is + # ir.mail_server object in old API (osv.osv) + 'odoo_db': self.pool.db_name, 'tracking_email_id': tracking_email_id, } headers['X-Mailgun-Variables'] = json.dumps(metadata) diff --git a/mail_tracking_mailgun/models/mail_tracking_email.py b/mail_tracking_mailgun/models/mail_tracking_email.py index f32366d2..adf8d565 100644 --- a/mail_tracking_mailgun/models/mail_tracking_email.py +++ b/mail_tracking_mailgun/models/mail_tracking_email.py @@ -4,7 +4,6 @@ import hashlib import hmac -import threading from datetime import datetime from openerp import models, api, fields @@ -19,16 +18,18 @@ class MailTrackingEmail(models.Model): country = False if country_code: country = self.env['res.country'].search([ - ('code', '=ilike', country_code), + ('code', '=', country_code.capitalize()), ]) if country: return country.id return False + @property def _mailgun_mandatory_fields(self): return ('event', 'timestamp', 'token', 'signature', 'tracking_email_id', 'odoo_db') + @property def _mailgun_event_type_mapping(self): return { # Mailgun event type: tracking event type @@ -41,13 +42,14 @@ class MailTrackingEmail(models.Model): 'dropped': 'reject', } + @property def _mailgun_supported_event_types(self): - return self._mailgun_event_type_mapping().keys() + return self._mailgun_event_type_mapping.keys() def _mailgun_event_type_verify(self, event): event = event or {} mailgun_event_type = event.get('event') - if mailgun_event_type not in self._mailgun_supported_event_types(): + if mailgun_event_type not in self._mailgun_supported_event_types: _logger.info("Mailgun: event type '%s' not supported", mailgun_event_type) return False @@ -76,8 +78,8 @@ class MailTrackingEmail(models.Model): signature = event.get('signature') event_digest = self._mailgun_signature(api_key, timestamp, token) if signature != event_digest: - _logger.info("Mailgun: Invalid signature '%s' != '%s'", - signature, event_digest) + _logger.error("Mailgun: Invalid signature '%s' != '%s'", + signature, event_digest) return False # OK, signature is valid return True @@ -85,7 +87,7 @@ class MailTrackingEmail(models.Model): def _db_verify(self, event): event = event or {} odoo_db = event.get('odoo_db') - current_db = getattr(threading.currentThread(), 'dbname', None) + current_db = self.env.cr.dbname if odoo_db != current_db: _logger.info("Mailgun: Database '%s' is not the current database", odoo_db) @@ -152,12 +154,12 @@ class MailTrackingEmail(models.Model): tracking = False tracking_email_id = event.get('tracking_email_id', False) if tracking_email_id and tracking_email_id.isdigit(): - tracking = self.search([('id', '=', tracking_email_id)]) + tracking = self.search([('id', '=', tracking_email_id)], limit=1) return tracking def _event_is_from_mailgun(self, event): event = event or {} - return all([k in event for k in self._mailgun_mandatory_fields()]) + return all([k in event for k in self._mailgun_mandatory_fields]) @api.model def event_process(self, request, post, metadata, event_type=None): @@ -174,7 +176,7 @@ class MailTrackingEmail(models.Model): res = 'OK' if res == 'OK': mailgun_event_type = post.get('event') - mapped_event_type = self._mailgun_event_type_mapping().get( + mapped_event_type = self._mailgun_event_type_mapping.get( mailgun_event_type) or event_type if not mapped_event_type: # pragma: no cover res = 'ERROR: Bad event' diff --git a/mail_tracking_mailgun/tests/test_mailgun.py b/mail_tracking_mailgun/tests/test_mailgun.py index fdb871ed..91396f78 100644 --- a/mail_tracking_mailgun/tests/test_mailgun.py +++ b/mail_tracking_mailgun/tests/test_mailgun.py @@ -2,7 +2,6 @@ # Copyright 2016 Antonio Espinosa - # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -import threading from openerp.tests.common import TransactionCase @@ -28,8 +27,8 @@ class TestMailgun(TransactionCase): self.api_key = u'key-12345678901234567890123456789012' self.token = u'f1349299097a51b9a7d886fcb5c2735b426ba200ada6e9e149' self.timestamp = u'1471021089' - self.signature = u'%s' % self.env['mail.tracking.email'].\ - _mailgun_signature(self.api_key, self.timestamp, self.token) + self.signature = ('4fb6d4dbbe10ce5d620265dcd7a3c0b8' + 'ca0dede1433103891bc1ae4086e9d5b2') self.env['ir.config_parameter'].set_param( 'mailgun.apikey', self.api_key) self.event = { @@ -42,7 +41,7 @@ class TestMailgun(TransactionCase): 'domain': u'example.com', 'message-headers': u'[]', 'recipient': self.recipient, - 'odoo_db': getattr(threading.currentThread(), 'dbname', None), + 'odoo_db': self.env.cr.dbname, 'tracking_email_id': u'%s' % self.tracking_email.id } self.metadata = { @@ -91,9 +90,9 @@ class TestMailgun(TransactionCase): self.assertEqual('ERROR: Invalid DB', response) def test_bad_ts(self): - timestamp = u'7a', # Now time will be used instead - signature = u'%s' % self.env['mail.tracking.email'].\ - _mailgun_signature(self.api_key, timestamp, self.token) + timestamp = u'7a' # Now time will be used instead + signature = ('06cc05680f6e8110e59b41152b2d1c0f' + '1045d755ef2880ff922344325c89a6d4') self.event.update({ 'event': u'delivered', 'timestamp': timestamp,