You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

130 lines
4.5 KiB

# -*- coding: utf-8 -*-
# License AGPL-3: Antiun Ingenieria S.L. - Antonio Espinosa
# See README.rst file on addon root folder for more details
import json
from hashlib import sha1
import hmac
import logging
from psycopg2 import OperationalError
import openerp
from openerp import api, http, SUPERUSER_ID, tools
from openerp.http import request
_logger = logging.getLogger(__name__)
class MailController(http.Controller):
def _mandrill_validation(self, **kw):
"""
Validate Mandrill POST reques using
https://mandrill.zendesk.com/hc/en-us/articles/
205583257-Authenticating-webhook-requests
"""
headers = request.httprequest.headers
signature = headers.get('X-Mandrill-Signature', False)
key = tools.config.options.get('mandrill_webhook_key', False)
if not key:
_logger.info("No Mandrill validation key configured. "
"Please add 'mandrill_webhook_key' to [options] "
"section in odoo configuration file to enable "
"Mandrill authentication webhoook requests. "
"More info at: "
"https://mandrill.zendesk.com/hc/en-us/articles/"
"205583257-Authenticating-webhook-requests")
return True
if not signature:
return False
url = tools.config.options.get('mandrill_webhook_url', False)
if not url:
url = request.httprequest.url_root.rstrip('/') + '/mandrill/event'
data = url
kw_keys = kw.keys()
if kw_keys:
kw_keys.sort()
for kw_key in kw_keys:
data += kw_key + kw.get(kw_key)
hashed = hmac.new(key, data, sha1)
hash_text = hashed.digest().encode("base64").rstrip('\n')
if hash_text == signature:
return True
_logger.info("HASH[%s] != SIGNATURE[%s]" % (hash_text, signature))
return False
def _event_process(self, event):
message_id = event.get('_id')
event_type = event.get('event')
message = event.get('msg')
if not (message_id and event_type and message):
return False
info = "%s event for Message ID '%s'" % (event_type, message_id)
metadata = message.get('metadata')
db = None
if metadata:
db = metadata.get('odoo_db', None)
# Check database selected by mandrill event
if not db:
_logger.info('%s: No DB selected', info)
return False
try:
registry = openerp.registry(db)
except OperationalError:
_logger.info("%s: Selected BD '%s' not found", info, db)
return False
except:
_logger.info("%s: Selected BD '%s' connection error", info, db)
return False
# Database has been selected, process event
with registry.cursor() as cr:
env = api.Environment(cr, SUPERUSER_ID, {})
res = env['mail.mandrill.message'].process(
message_id, event_type, event)
if res:
_logger.info('%s: OK', info)
else:
_logger.info('%s: FAILED', info)
return res
@http.route('/mandrill/event', type='http', auth='none')
def event(self, **kw):
"""
End-point to receive Mandrill event
Configuration in Mandrill app > Settings > Webhooks
(https://mandrillapp.com/settings/webhooks)
Add a webhook, selecting this type of events:
- Message Is Sent
- Message Is Bounced
- Message Is Opened
- Message Is Marked As Spam
- Message Is Rejected
- Message Is Delayed
- Message Is Soft-Bounced
- Message Is Clicked
- Message Recipient Unsubscribes
and setting this Post to URL:
https://your_odoodomain.com/mandrill/event
"""
if not self._mandrill_validation(**kw):
_logger.info('Validation error, ignoring this request')
return 'NO_AUTH'
events = []
try:
events = json.loads(kw.get('mandrill_events', '[]'))
except:
pass
if not events:
return 'NO_EVENTS'
res = []
for event in events:
res.append(self._event_process(event))
msg = 'ALL_EVENTS_FAILED'
if all(res):
msg = 'OK'
elif any(res):
msg = 'SOME_EVENTS_FAILED'
return msg