/addons/mass_mailing/models/mail_thread.py

https://gitlab.com/thanhchatvn/cloud-odoo · Python · 73 lines · 44 code · 11 blank · 18 comment · 13 complexity · 368157fc7596919d405172fb366eeb8f MD5 · raw file

  1. # -*- coding: utf-8 -*-
  2. # Part of Odoo. See LICENSE file for full copyright and licensing details.
  3. import logging
  4. import re
  5. from openerp.addons.mail.models.mail_message import decode
  6. from openerp.addons.mail.models.mail_thread import decode_header
  7. from openerp.osv import osv
  8. _logger = logging.getLogger(__name__)
  9. class MailThread(osv.AbstractModel):
  10. """ Update MailThread to add the feature of bounced emails and replied emails
  11. in message_process. """
  12. _name = 'mail.thread'
  13. _inherit = ['mail.thread']
  14. def message_route_check_bounce(self, cr, uid, message, context=None):
  15. """ Override to verify that the email_to is the bounce alias. If it is the
  16. case, log the bounce, set the parent and related document as bounced and
  17. return False to end the routing process. """
  18. bounce_alias = self.pool['ir.config_parameter'].get_param(cr, uid, "mail.bounce.alias", context=context)
  19. message_id = message.get('Message-Id')
  20. email_from = decode_header(message, 'From')
  21. email_to = decode_header(message, 'To')
  22. # 0. Verify whether this is a bounced email (wrong destination,...) -> use it to collect data, such as dead leads
  23. if bounce_alias and bounce_alias in email_to:
  24. # Bounce regex
  25. # Typical form of bounce is bounce_alias-128-crm.lead-34@domain
  26. # group(1) = the mail ID; group(2) = the model (if any); group(3) = the record ID
  27. bounce_re = re.compile("%s-(\d+)-?([\w.]+)?-?(\d+)?" % re.escape(bounce_alias), re.UNICODE)
  28. bounce_match = bounce_re.search(email_to)
  29. if bounce_match:
  30. bounced_model, bounced_thread_id = None, False
  31. bounced_mail_id = bounce_match.group(1)
  32. stat_ids = self.pool['mail.mail.statistics'].set_bounced(cr, uid, mail_mail_ids=[bounced_mail_id], context=context)
  33. for stat in self.pool['mail.mail.statistics'].browse(cr, uid, stat_ids, context=context):
  34. bounced_model = stat.model
  35. bounced_thread_id = stat.res_id
  36. _logger.info('Routing mail from %s to %s with Message-Id %s: bounced mail from mail %s, model: %s, thread_id: %s',
  37. email_from, email_to, message_id, bounced_mail_id, bounced_model, bounced_thread_id)
  38. if bounced_model and bounced_model in self.pool and hasattr(self.pool[bounced_model], 'message_receive_bounce') and bounced_thread_id:
  39. self.pool[bounced_model].message_receive_bounce(cr, uid, [bounced_thread_id], mail_id=bounced_mail_id, context=context)
  40. return False
  41. return True
  42. def message_route(self, cr, uid, message, message_dict, model=None, thread_id=None,
  43. custom_values=None, context=None):
  44. if not self.message_route_check_bounce(cr, uid, message, context=context):
  45. return []
  46. return super(MailThread, self).message_route(cr, uid, message, message_dict, model, thread_id, custom_values, context)
  47. def message_receive_bounce(self, cr, uid, ids, mail_id=None, context=None):
  48. """Called by ``message_process`` when a bounce email (such as Undelivered
  49. Mail Returned to Sender) is received for an existing thread. The default
  50. behavior is to check is an integer ``message_bounce`` column exists.
  51. If it is the case, its content is incremented. """
  52. if 'message_bounce' in self._fields:
  53. for obj in self.browse(cr, uid, ids, context=context):
  54. self.write(cr, uid, [obj.id], {'message_bounce': obj.message_bounce + 1}, context=context)
  55. def message_route_process(self, cr, uid, message, message_dict, routes, context=None):
  56. """ Override to update the parent mail statistics. The parent is found
  57. by using the References header of the incoming message and looking for
  58. matching message_id in mail.mail.statistics. """
  59. if message.get('References'):
  60. message_ids = [x.strip() for x in decode(message['References']).split()]
  61. self.pool['mail.mail.statistics'].set_replied(cr, uid, mail_message_ids=message_ids, context=context)
  62. return super(MailThread, self).message_route_process(cr, uid, message, message_dict, routes, context=context)