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.

122 lines
4.8 KiB

  1. # -*- coding: utf-8 -*-
  2. # Copyright 2015 Innoviu srl <http://www.innoviu.it>
  3. # Copyright 2015 Agile Business Group <http://www.agilebg.com>
  4. # Copyright 2017 Eficent Business and IT Consulting Services, S.L.
  5. # <http://www.eficent.com>
  6. # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
  7. import logging
  8. import imaplib
  9. from datetime import datetime
  10. import time
  11. from openerp import api, fields, models
  12. _logger = logging.getLogger(__name__)
  13. class FetchmailServer(models.Model):
  14. _inherit = "fetchmail.server"
  15. last_internal_date = fields.Datetime(
  16. 'Last Download Date',
  17. help="Remote emails with a date greater than this will be "
  18. "downloaded. Only available with IMAP")
  19. @api.model
  20. def _fetch_from_date_imap(self, imap_server, count, failed):
  21. MailThread = self.env['mail.thread']
  22. messages = []
  23. date_uids = {}
  24. last_date = False
  25. last_internal_date = datetime.strptime(self.last_internal_date,
  26. "%Y-%m-%d %H:%M:%S")
  27. search_status, uids = imap_server.search(
  28. None,
  29. 'SINCE', '%s' % last_internal_date.strftime('%d-%b-%Y')
  30. )
  31. new_uids = uids[0].split()
  32. for new_uid in new_uids:
  33. fetch_status, date = imap_server.fetch(
  34. int(new_uid),
  35. 'INTERNALDATE'
  36. )
  37. internaldate = imaplib.Internaldate2tuple(date[0])
  38. internaldate_msg = datetime.fromtimestamp(
  39. time.mktime(internaldate)
  40. )
  41. if internaldate_msg > last_internal_date:
  42. messages.append(new_uid)
  43. date_uids[new_uid] = internaldate_msg
  44. for num in messages:
  45. # SEARCH command *always* returns at least the most
  46. # recent message, even if it has already been synced
  47. res_id = None
  48. result, data = imap_server.fetch(num, '(RFC822)')
  49. if data and data[0]:
  50. try:
  51. res_id = MailThread.message_process(
  52. self.object_id.model,
  53. data[0][1],
  54. save_original=self.original,
  55. strip_attachments=(not self.attach))
  56. except Exception:
  57. _logger.exception(
  58. 'Failed to process mail \
  59. from %s server %s.',
  60. self.type,
  61. self.name)
  62. failed += 1
  63. if res_id and self.action_id:
  64. self.action_id.run({
  65. 'active_id': res_id,
  66. 'active_ids': [res_id],
  67. 'active_model': self.env.context.get(
  68. "thread_model", self.object_id.model)
  69. })
  70. imap_server.store(num, '+FLAGS', '\\Seen')
  71. self._cr.commit()
  72. count += 1
  73. last_date = not failed and date_uids[num] or False
  74. return count, failed, last_date
  75. @api.multi
  76. def fetch_mail(self):
  77. context = self.env.context.copy()
  78. context['fetchmail_cron_running'] = True
  79. for server in self:
  80. if server.type == 'imap' and server.last_internal_date:
  81. _logger.info(
  82. 'start checking for new emails, starting from %s on %s '
  83. 'server %s',
  84. server.last_internal_date, server.type, server.name)
  85. context.update({'fetchmail_server_id': server.id,
  86. 'server_type': server.type})
  87. count, failed = 0, 0
  88. last_date = False
  89. imap_server = False
  90. try:
  91. imap_server = server.connect()
  92. imap_server.select()
  93. count, failed, last_date = server._fetch_from_date_imap(
  94. imap_server, count, failed)
  95. except Exception:
  96. _logger.exception(
  97. "General failure when trying to fetch mail by date \
  98. from %s server %s.",
  99. server.type,
  100. server.name
  101. )
  102. finally:
  103. if imap_server:
  104. imap_server.close()
  105. imap_server.logout()
  106. if last_date:
  107. _logger.info(
  108. "Fetched %d email(s) on %s server %s, starting from "
  109. "%s; %d succeeded, %d failed.", count,
  110. server.type, server.name, last_date,
  111. (count - failed), failed)
  112. vals = {'last_internal_date': last_date}
  113. server.write(vals)
  114. return super(FetchmailServer, self).fetch_mail()