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.

173 lines
7.0 KiB

  1. # -*- coding: utf-8 -*-
  2. # © 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com>
  3. # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
  4. import logging
  5. import urlparse
  6. import time
  7. from datetime import datetime
  8. from openerp import models, api, fields, tools
  9. import openerp.addons.decimal_precision as dp
  10. _logger = logging.getLogger(__name__)
  11. class MailTrackingEmail(models.Model):
  12. _name = "mail.tracking.email"
  13. _order = 'time desc'
  14. _rec_name = 'name'
  15. _description = 'MailTracking email'
  16. name = fields.Char(string="Subject", readonly=True, index=True)
  17. timestamp = fields.Float(
  18. string='UTC timestamp', readonly=True,
  19. digits=dp.get_precision('MailTracking Timestamp'))
  20. time = fields.Datetime(string="Time", readonly=True)
  21. date = fields.Date(
  22. string="Date", readonly=True, compute="_compute_date", store=True)
  23. mail_message_id = fields.Many2one(
  24. string="Message", comodel_name='mail.message', readonly=True)
  25. mail_id = fields.Many2one(
  26. string="Email", comodel_name='mail.mail', readonly=True)
  27. partner_id = fields.Many2one(
  28. string="Partner", comodel_name='res.partner', readonly=True)
  29. recipient = fields.Char(string='Recipient email', readonly=True)
  30. sender = fields.Char(string='Sender email', readonly=True)
  31. state = fields.Selection([
  32. ('error', 'Error'),
  33. ('deferred', 'Deferred'),
  34. ('sent', 'Sent'),
  35. ('delivered', 'Delivered'),
  36. ('opened', 'Open'),
  37. ('rejected', 'Rejected'),
  38. ('spam', 'Spam'),
  39. ('unsub', 'Unsubscribed'),
  40. ('bounced', 'Bounced'),
  41. ('soft-bounced', 'Soft bounced'),
  42. ], string='State', index=True, readonly=True, default=False,
  43. help=" * The 'Error' status indicates that there was an error "
  44. "when trying to sent the email, for example, "
  45. "'No valid recipient'\n"
  46. " * The 'Sent' status indicates that message was succesfully "
  47. "sent via outgoing email server (SMTP).\n"
  48. " * The 'Delivered' status indicates that message was "
  49. "succesfully delivered to recipient Mail Exchange (MX) server.\n"
  50. " * The 'Open' status indicates that message was opened or "
  51. "clicked by recipient.\n"
  52. " * The 'Rejected' status indicates that recipient email "
  53. "address is blacklisted by outgoing email server (SMTP). "
  54. "It is recomended to delete this email address.\n"
  55. " * The 'Spam' status indicates that outgoing email "
  56. "server (SMTP) consider this message as spam.\n"
  57. " * The 'Unsubscribed' status indicates that recipient has "
  58. "requested to be unsubscribed from this message.\n"
  59. " * The 'Bounced' status indicates that message was bounced "
  60. "by recipient Mail Exchange (MX) server.\n"
  61. " * The 'Soft bounced' status indicates that message was soft "
  62. "bounced by recipient Mail Exchange (MX) server.\n")
  63. error_smtp_server = fields.Char(string='Error SMTP server', readonly=True)
  64. error_type = fields.Char(string='Error type', readonly=True)
  65. error_description = fields.Char(
  66. string='Error description', readonly=True)
  67. bounce_type = fields.Char(string='Bounce type', readonly=True)
  68. bounce_description = fields.Char(
  69. string='Bounce description', readonly=True)
  70. tracking_event_ids = fields.One2many(
  71. string="Tracking events", comodel_name='mail.tracking.event',
  72. inverse_name='tracking_email_id', readonly=True)
  73. @api.multi
  74. @api.depends('time')
  75. def _compute_date(self):
  76. for email in self:
  77. email.date = fields.Date.to_string(
  78. fields.Date.from_string(email.time))
  79. def _get_mail_tracking_img(self):
  80. base_url = self.env['ir.config_parameter'].get_param('web.base.url')
  81. path_url = (
  82. 'mail/tracking/open/%(db)s/%(tracking_email_id)s/blank.gif' % {
  83. 'db': self.env.cr.dbname,
  84. 'tracking_email_id': self.id,
  85. })
  86. track_url = urlparse.urljoin(base_url, path_url)
  87. return (
  88. '<img src="%(url)s" alt="" '
  89. 'data-odoo-tracking-email="%(tracking_email_id)s"/>' % {
  90. 'url': track_url,
  91. 'tracking_email_id': self.id,
  92. })
  93. @api.multi
  94. def smtp_error(self, mail_server, smtp_server, exception):
  95. self.sudo().write({
  96. 'error_smtp_server': tools.ustr(smtp_server),
  97. 'error_type': exception.__class__.__name__,
  98. 'error_description': tools.ustr(exception),
  99. 'state': 'error',
  100. })
  101. return True
  102. @api.multi
  103. def tracking_img_add(self, email):
  104. self.ensure_one()
  105. tracking_url = self._get_mail_tracking_img()
  106. if tracking_url:
  107. body = tools.append_content_to_html(
  108. email.get('body', ''), tracking_url, plaintext=False,
  109. container_tag='div')
  110. email['body'] = body
  111. return email
  112. def _message_partners_check(self, message, message_id):
  113. mail_message = self.mail_message_id
  114. partners = mail_message.notified_partner_ids | mail_message.partner_ids
  115. if (self.partner_id and self.partner_id not in partners):
  116. # If mail_message haven't tracking partner, then
  117. # add it in order to see his trackking status in chatter
  118. if mail_message.subtype_id:
  119. mail_message.sudo().write({
  120. 'notified_partner_ids': [(4, self.partner_id.id)],
  121. })
  122. else:
  123. mail_message.sudo().write({
  124. 'partner_ids': [(4, self.partner_id.id)],
  125. })
  126. return True
  127. @api.multi
  128. def _tracking_sent_prepare(self, mail_server, smtp_server, message,
  129. message_id):
  130. self.ensure_one()
  131. ts = time.time()
  132. dt = datetime.utcfromtimestamp(ts)
  133. self._message_partners_check(message, message_id)
  134. self.sudo().write({'state': 'sent'})
  135. return {
  136. 'recipient': message['To'],
  137. 'timestamp': '%.6f' % ts,
  138. 'time': fields.Datetime.to_string(dt),
  139. 'tracking_email_id': self.id,
  140. 'event_type': 'sent',
  141. 'smtp_server': smtp_server,
  142. }
  143. def _event_prepare(self, event_type, metadata):
  144. self.ensure_one()
  145. m_event = self.env['mail.tracking.event']
  146. method = getattr(m_event, 'process_' + event_type, None)
  147. if method and hasattr(method, '__call__'):
  148. return method(self, metadata)
  149. else:
  150. _logger.info('Unknown event type: %s' % event_type)
  151. return False
  152. @api.multi
  153. def event_process(self, event_type, metadata):
  154. event_ids = self.env['mail.tracking.event']
  155. for tracking_email in self:
  156. vals = tracking_email._event_prepare(event_type, metadata)
  157. if vals:
  158. event_ids += event_ids.sudo().create(vals)
  159. return event_ids