Browse Source

Merge pull request #236 from Tecnativa/10.0-fix-resync-mail_tracking_mailgun

[FIX] mail_tracking_mailgun: manual sync gets events from other recipients
pull/242/head
Pedro M. Baeza 7 years ago
committed by GitHub
parent
commit
ce8da8ee09
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 4
      mail_tracking_mailgun/README.rst
  2. 2
      mail_tracking_mailgun/__manifest__.py
  3. 8
      mail_tracking_mailgun/models/mail_tracking_email.py
  4. 2
      mail_tracking_mailgun/models/mail_tracking_event.py
  5. 55
      mail_tracking_mailgun/models/res_partner.py
  6. 11
      mail_tracking_mailgun/tests/test_mailgun.py

4
mail_tracking_mailgun/README.rst

@ -40,6 +40,10 @@ parameters:
validity you must config this parameter with your account Public Validation validity you must config this parameter with your account Public Validation
Key. Key.
You can also config partner email autocheck with this system parameter:
- `mailgun.auto_check_partner_email`: Set it to True.
Usage Usage
===== =====

2
mail_tracking_mailgun/__manifest__.py

@ -7,7 +7,7 @@
{ {
"name": "Mail tracking for Mailgun", "name": "Mail tracking for Mailgun",
"summary": "Mail tracking and Mailgun webhooks integration", "summary": "Mail tracking and Mailgun webhooks integration",
"version": "10.0.1.1.2",
"version": "10.0.1.1.3",
"category": "Social Network", "category": "Social Network",
"website": "https://odoo-community.org/", "website": "https://odoo-community.org/",
"author": "Tecnativa, " "author": "Tecnativa, "

8
mail_tracking_mailgun/models/mail_tracking_email.py

@ -10,6 +10,7 @@ import requests
from datetime import datetime from datetime import datetime
from odoo import _, api, fields, models from odoo import _, api, fields, models
from odoo.exceptions import UserError, ValidationError from odoo.exceptions import UserError, ValidationError
from odoo.tools import email_split
import logging import logging
_logger = logging.getLogger(__name__) _logger = logging.getLogger(__name__)
@ -241,8 +242,13 @@ class MailTrackingEmail(models.Model):
if "items" not in content: if "items" not in content:
raise ValidationError(_("Event information not longer stored")) raise ValidationError(_("Event information not longer stored"))
for item in content["items"]: for item in content["items"]:
# mailgun event hasn't been synced and recipient is the same as
# in the evaluated tracking. We use email_split since tracking
# recipient could come in format: "example" <to@dest.com>
if not self.env['mail.tracking.event'].search( if not self.env['mail.tracking.event'].search(
[('mailgun_id', '=', item["id"])]):
[('mailgun_id', '=', item["id"])]) and (
item.get("recipient", "") ==
email_split(tracking.recipient)[0]):
mapped_event_type = self._mailgun_event_type_mapping.get( mapped_event_type = self._mailgun_event_type_mapping.get(
item["event"], item["event"]) item["event"], item["event"])
metadata = self._mailgun_metadata( metadata = self._mailgun_metadata(

2
mail_tracking_mailgun/models/mail_tracking_event.py

@ -2,7 +2,7 @@
# Copyright 2017 Tecnativa - David Vidal # Copyright 2017 Tecnativa - David Vidal
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from openerp import models, fields
from odoo import models, fields
class MailTrackingEvent(models.Model): class MailTrackingEvent(models.Model):

55
mail_tracking_mailgun/models/res_partner.py

@ -45,43 +45,50 @@ class ResPartner(models.Model):
if not validation_key: if not validation_key:
raise UserError(_('You need to configure mailgun.validation_key' raise UserError(_('You need to configure mailgun.validation_key'
' in order to be able to check mails validity')) ' in order to be able to check mails validity'))
for partner in self:
for partner in self.filtered('email'):
res = requests.get( res = requests.get(
"%s/address/validate" % api_url, "%s/address/validate" % api_url,
auth=("api", validation_key), params={ auth=("api", validation_key), params={
"address": partner.email, "address": partner.email,
"mailbox_verification": True, "mailbox_verification": True,
}) })
if not res or res.status_code != 200:
if not res or res.status_code != 200 and not self.env.context.get(
'mailgun_auto_check'):
raise UserError(_( raise UserError(_(
'Error %s trying to ' 'Error %s trying to '
'check mail' % res.status_code or 'of connection')) 'check mail' % res.status_code or 'of connection'))
content = json.loads(res.content, res.apparent_encoding) content = json.loads(res.content, res.apparent_encoding)
if 'mailbox_verification' not in content: if 'mailbox_verification' not in content:
raise UserError(
_("Mailgun Error. Mailbox verification value wasn't"
" returned"))
if not self.env.context.get('mailgun_auto_check'):
raise UserError(
_("Mailgun Error. Mailbox verification value wasn't"
" returned"))
# Not a valid address: API sets 'is_valid' as False # Not a valid address: API sets 'is_valid' as False
# and 'mailbox_verification' as None # and 'mailbox_verification' as None
if not content['is_valid']: if not content['is_valid']:
partner.email_bounced = True partner.email_bounced = True
raise UserError(
_('%s is not a valid email address. Please check it '
'in order to avoid sending issues') % (partner.email))
body = _('%s is not a valid email address. Please check it'
' in order to avoid sending issues') % partner.email
if not self.env.context.get('mailgun_auto_check'):
raise UserError(body)
partner.message_post(body=body)
# If the mailbox is not valid API returns 'mailbox_verification' # If the mailbox is not valid API returns 'mailbox_verification'
# as a string with value 'false' # as a string with value 'false'
if content['mailbox_verification'] == 'false': if content['mailbox_verification'] == 'false':
partner.email_bounced = True partner.email_bounced = True
raise UserError(
_('%s failed the mailbox verification. Please check it '
'in order to avoid sending issues') % (partner.email))
body = _('%s failed the mailbox verification. Please check it'
' in order to avoid sending issues') % partner.email
if not self.env.context.get('mailgun_auto_check'):
raise UserError(body)
partner.message_post(body=body)
# If Mailgun can't complete the validation request the API returns # If Mailgun can't complete the validation request the API returns
# 'mailbox_verification' as a string set to 'unknown' # 'mailbox_verification' as a string set to 'unknown'
if content['mailbox_verification'] == 'unknown': if content['mailbox_verification'] == 'unknown':
raise UserError(
_("%s couldn't be verified. Either the request couln't be "
"completed or the mailbox provider doesn't support "
"email verification") % (partner.email))
if not self.env.context.get('mailgun_auto_check'):
raise UserError(
_("%s couldn't be verified. Either the request couln't"
" be completed or the mailbox provider doesn't "
"support email verification") % (partner.email))
@api.multi @api.multi
def check_email_bounced(self): def check_email_bounced(self):
@ -133,3 +140,21 @@ class ResPartner(models.Model):
auth=("api", api_key)) auth=("api", api_key))
if res.status_code in (200, 404) and partner.email_bounced: if res.status_code in (200, 404) and partner.email_bounced:
partner.email_bounced = False partner.email_bounced = False
def _autocheck_partner_email(self):
for partner in self:
partner.with_context(
mailgun_auto_check=True).check_email_validity()
@api.model
def create(self, vals):
if 'email' in vals and self.env['ir.config_parameter'].get_param(
'mailgun.auto_check_partner_email'):
self._autocheck_partner_email()
return super(ResPartner, self).create(vals)
def write(self, vals):
if 'email' in vals and self.env['ir.config_parameter'].get_param(
'mailgun.auto_check_partner_email'):
self._autocheck_partner_email()
return super(ResPartner, self).write(vals)

11
mail_tracking_mailgun/tests/test_mailgun.py

@ -43,6 +43,8 @@ class TestMailgun(TransactionCase):
'mail.catchall.domain', self.domain) 'mail.catchall.domain', self.domain)
self.env['ir.config_parameter'].set_param( self.env['ir.config_parameter'].set_param(
'mailgun.validation_key', self.api_key) 'mailgun.validation_key', self.api_key)
self.env['ir.config_parameter'].set_param(
'mailgun.auto_check_partner_email', '')
self.event = { self.event = {
'Message-Id': u'<xxx.xxx.xxx-openerp-xxx-res.partner@test_db>', 'Message-Id': u'<xxx.xxx.xxx-openerp-xxx-res.partner@test_db>',
'X-Mailgun-Sid': u'WyIwNjgxZSIsICJ0b0BleGFtcGxlLmNvbSIsICI3MG' 'X-Mailgun-Sid': u'WyIwNjgxZSIsICJ0b0BleGFtcGxlLmNvbSIsICI3MG'
@ -79,7 +81,8 @@ class TestMailgun(TransactionCase):
"subject": "This is a test" "subject": "This is a test"
}, },
}, },
"event": "delivered"
"event": "delivered",
"recipient": "to@example.com",
}] }]
} }
@ -331,14 +334,16 @@ class TestMailgun(TransactionCase):
@mock.patch(_packagepath + '.models.res_partner.requests') @mock.patch(_packagepath + '.models.res_partner.requests')
def test_email_validity(self, mock_request): def test_email_validity(self, mock_request):
self.partner.email_bounced = False self.partner.email_bounced = False
self.partner.email = 'info@tecnativa.com'
mock_request.get.return_value.apparent_encoding = 'ascii' mock_request.get.return_value.apparent_encoding = 'ascii'
mock_request.get.return_value.status_code = 200 mock_request.get.return_value.status_code = 200
mock_request.get.return_value.content = json.dumps({ mock_request.get.return_value.content = json.dumps({
'is_valid': True, 'is_valid': True,
'mailbox_verification': 'true', 'mailbox_verification': 'true',
}, ensure_ascii=True) }, ensure_ascii=True)
self.partner.check_email_validity()
# Trigger email auto validation in partner
self.env['ir.config_parameter'].set_param(
'mailgun.auto_check_partner_email', 'True')
self.partner.email = 'info@tecnativa.com'
self.assertFalse(self.partner.email_bounced) self.assertFalse(self.partner.email_bounced)
self.partner.email = 'xoxoxoxo@tecnativa.com' self.partner.email = 'xoxoxoxo@tecnativa.com'
# Not a valid mailbox # Not a valid mailbox

Loading…
Cancel
Save