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.

152 lines
6.2 KiB

  1. # -*- coding: utf-8 -*-
  2. ##############################################################################
  3. #
  4. # Copyright (C) 2015 Innoviu srl (<http://www.innoviu.com>).
  5. # Copyright (C) 2015 Agile Business Group http://www.agilebg.com
  6. # @authors
  7. # Roberto Onnis <roberto.onnis@innoviu.com>
  8. # Alessio Gerace <alessio.gerace@agilebg.com>
  9. # Lorenzo Battistini <lorenzo.battistini@agilebg.com>
  10. #
  11. # This program is free software: you can redistribute it and/or modify
  12. # it under the terms of the GNU Affero General Public License as published
  13. # by the Free Software Foundation, either version 3 of the License, or
  14. # (at your option) any later version.
  15. #
  16. # This program is distributed in the hope that it will be useful,
  17. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  19. # GNU Affero General Public License for more details.
  20. #
  21. # You should have received a copy of the GNU Affero General Public License
  22. # along with this program. If not, see <http://www.gnu.org/licenses/>.
  23. ##############################################################################
  24. from openerp.osv import fields, orm
  25. import logging
  26. import imaplib
  27. from datetime import datetime
  28. import time
  29. _logger = logging.getLogger(__name__)
  30. class FetchmailServer(orm.Model):
  31. _inherit = "fetchmail.server"
  32. _columns = {
  33. 'last_internal_date': fields.datetime(
  34. 'Last Download Date',
  35. help="Remote emails with a date greater than this will be "
  36. "downloaded. Only available with IMAP"),
  37. }
  38. def _fetch_from_date_imap(self, cr, uid,
  39. server, imap_server,
  40. mail_thread, action_pool,
  41. count, failed,
  42. context=None):
  43. messages = []
  44. date_uids = {}
  45. last_date = False
  46. last_internal_date = datetime.strptime(
  47. server.last_internal_date, "%Y-%m-%d %H:%M:%S")
  48. search_status, uids = imap_server.search(
  49. None,
  50. 'SINCE', '%s' % last_internal_date.strftime('%d-%b-%Y')
  51. )
  52. new_uids = uids[0].split()
  53. for new_uid in new_uids:
  54. fetch_status, date = imap_server.fetch(
  55. int(new_uid),
  56. 'INTERNALDATE'
  57. )
  58. internaldate = imaplib.Internaldate2tuple(date[0])
  59. internaldate_msg = datetime.fromtimestamp(
  60. time.mktime(internaldate)
  61. )
  62. if internaldate_msg > last_internal_date:
  63. messages.append(new_uid)
  64. date_uids[new_uid] = internaldate_msg
  65. for num in messages:
  66. # SEARCH command *always* returns at least the most
  67. # recent message, even if it has already been synced
  68. res_id = None
  69. result, data = imap_server.fetch(num, '(RFC822)')
  70. if data and data[0]:
  71. try:
  72. res_id = mail_thread.message_process(
  73. cr, uid,
  74. server.object_id.model,
  75. data[0][1],
  76. save_original=server.original,
  77. strip_attachments=(not server.attach),
  78. context=context)
  79. except Exception:
  80. _logger.exception(
  81. 'Failed to process mail \
  82. from %s server %s.',
  83. server.type,
  84. server.name)
  85. failed += 1
  86. if res_id and server.action_id:
  87. action_pool.run(
  88. cr, uid, [server.action_id.id],
  89. {
  90. 'active_id': res_id,
  91. 'active_ids': [res_id],
  92. 'active_model': context.get(
  93. "thread_model",
  94. server.object_id.model)
  95. }, context=context)
  96. imap_server.store(num, '+FLAGS', '\\Seen')
  97. cr.commit()
  98. count += 1
  99. last_date = not failed and date_uids[num] or False
  100. return count, failed, last_date
  101. def fetch_mail(self, cr, uid, ids, context=None):
  102. if context is None:
  103. context = {}
  104. context['fetchmail_cron_running'] = True
  105. mail_thread = self.pool.get('mail.thread')
  106. action_pool = self.pool.get('ir.actions.server')
  107. for server in self.browse(cr, uid, ids, context=context):
  108. if server.type == 'imap' and server.last_internal_date:
  109. _logger.info(
  110. 'start checking for new emails by date on %s server %s',
  111. server.type, server.name)
  112. context.update({'fetchmail_server_id': server.id,
  113. 'server_type': server.type})
  114. count, failed = 0, 0
  115. last_date = False
  116. imap_server = False
  117. try:
  118. imap_server = server.connect()
  119. imap_server.select()
  120. count, failed, last_date = self._fetch_from_date_imap(
  121. cr, uid, server, imap_server, mail_thread,
  122. action_pool, count, failed, context=context
  123. )
  124. except Exception:
  125. _logger.exception(
  126. "General failure when trying to fetch mail \
  127. from %s server %s.",
  128. server.type,
  129. server.name
  130. )
  131. finally:
  132. if imap_server:
  133. imap_server.close()
  134. imap_server.logout()
  135. if last_date:
  136. _logger.info(
  137. "Fetched %d email(s) on %s server %s; \
  138. %d succeeded, %d failed.", count,
  139. server.type, server.name,
  140. (count - failed), failed)
  141. vals = {'last_internal_date': last_date}
  142. server.write(vals)
  143. return super(FetchmailServer, self).fetch_mail(
  144. cr, uid, ids, context=context)