diff --git a/mail_tracking_mailgun/README.rst b/mail_tracking_mailgun/README.rst index 7f377add..eb0ec7e4 100644 --- a/mail_tracking_mailgun/README.rst +++ b/mail_tracking_mailgun/README.rst @@ -40,6 +40,10 @@ parameters: validity you must config this parameter with your account Public Validation Key. +You can also config partner email autocheck with this system parameter: + +- `mailgun.auto_check_partner_email`: Set it to True. + Usage ===== diff --git a/mail_tracking_mailgun/__manifest__.py b/mail_tracking_mailgun/__manifest__.py index 0ebb5b20..419b1ea6 100644 --- a/mail_tracking_mailgun/__manifest__.py +++ b/mail_tracking_mailgun/__manifest__.py @@ -7,7 +7,7 @@ { "name": "Mail tracking for Mailgun", "summary": "Mail tracking and Mailgun webhooks integration", - "version": "10.0.1.1.2", + "version": "10.0.1.1.3", "category": "Social Network", "website": "https://odoo-community.org/", "author": "Tecnativa, " diff --git a/mail_tracking_mailgun/models/mail_tracking_email.py b/mail_tracking_mailgun/models/mail_tracking_email.py index b017d4e9..fa431dd2 100644 --- a/mail_tracking_mailgun/models/mail_tracking_email.py +++ b/mail_tracking_mailgun/models/mail_tracking_email.py @@ -10,6 +10,7 @@ import requests from datetime import datetime from odoo import _, api, fields, models from odoo.exceptions import UserError, ValidationError +from odoo.tools import email_split import logging _logger = logging.getLogger(__name__) @@ -241,8 +242,13 @@ class MailTrackingEmail(models.Model): if "items" not in content: raise ValidationError(_("Event information not longer stored")) 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" 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( item["event"], item["event"]) metadata = self._mailgun_metadata( diff --git a/mail_tracking_mailgun/models/mail_tracking_event.py b/mail_tracking_mailgun/models/mail_tracking_event.py index de3fe3ed..278210e9 100644 --- a/mail_tracking_mailgun/models/mail_tracking_event.py +++ b/mail_tracking_mailgun/models/mail_tracking_event.py @@ -2,7 +2,7 @@ # Copyright 2017 Tecnativa - David Vidal # 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): diff --git a/mail_tracking_mailgun/models/res_partner.py b/mail_tracking_mailgun/models/res_partner.py index 77f284e2..c5f531b3 100644 --- a/mail_tracking_mailgun/models/res_partner.py +++ b/mail_tracking_mailgun/models/res_partner.py @@ -45,43 +45,50 @@ class ResPartner(models.Model): if not validation_key: raise UserError(_('You need to configure mailgun.validation_key' ' in order to be able to check mails validity')) - for partner in self: + for partner in self.filtered('email'): res = requests.get( "%s/address/validate" % api_url, auth=("api", validation_key), params={ "address": partner.email, "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(_( 'Error %s trying to ' 'check mail' % res.status_code or 'of connection')) content = json.loads(res.content, res.apparent_encoding) 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 # and 'mailbox_verification' as None if not content['is_valid']: 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' # as a string with value 'false' if content['mailbox_verification'] == 'false': 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 # 'mailbox_verification' as a string set to '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 def check_email_bounced(self): @@ -133,3 +140,21 @@ class ResPartner(models.Model): auth=("api", api_key)) if res.status_code in (200, 404) and partner.email_bounced: 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) diff --git a/mail_tracking_mailgun/tests/test_mailgun.py b/mail_tracking_mailgun/tests/test_mailgun.py index d15888c9..45cecd65 100644 --- a/mail_tracking_mailgun/tests/test_mailgun.py +++ b/mail_tracking_mailgun/tests/test_mailgun.py @@ -43,6 +43,8 @@ class TestMailgun(TransactionCase): 'mail.catchall.domain', self.domain) self.env['ir.config_parameter'].set_param( 'mailgun.validation_key', self.api_key) + self.env['ir.config_parameter'].set_param( + 'mailgun.auto_check_partner_email', '') self.event = { 'Message-Id': u'', 'X-Mailgun-Sid': u'WyIwNjgxZSIsICJ0b0BleGFtcGxlLmNvbSIsICI3MG' @@ -79,7 +81,8 @@ class TestMailgun(TransactionCase): "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') def test_email_validity(self, mock_request): self.partner.email_bounced = False - self.partner.email = 'info@tecnativa.com' mock_request.get.return_value.apparent_encoding = 'ascii' mock_request.get.return_value.status_code = 200 mock_request.get.return_value.content = json.dumps({ 'is_valid': True, 'mailbox_verification': '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.partner.email = 'xoxoxoxo@tecnativa.com' # Not a valid mailbox