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.

153 lines
6.2 KiB

  1. # -*- coding: utf-8 -*-
  2. ##############################################################################
  3. #
  4. # Copyright (C) 2015 Innoviu srl (<http://www.innoviu.it>).
  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_download_date': fields.datetime('Last Download Date'),
  34. }
  35. def _fetch_from_data_imap(self, cr, uid,
  36. server, imap_server,
  37. mail_thread, action_pool,
  38. count, failed,
  39. context=None):
  40. messages = []
  41. date_uids = {}
  42. last_date = False
  43. last_download_date = datetime.strptime(
  44. server.last_download_date, "%Y-%m-%d %H:%M:%S")
  45. search_status, uids = imap_server.search(
  46. None,
  47. 'SINCE', '%s' % last_download_date.strftime('%d-%b-%Y')
  48. )
  49. new_uids = uids[0].split()
  50. for new_uid in new_uids:
  51. fetch_status, data = imap_server.fetch(
  52. int(new_uid),
  53. 'INTERNALDATE'
  54. )
  55. internaldate = imaplib.Internaldate2tuple(data[0])
  56. internaldate_msg = datetime.fromtimestamp(
  57. time.mktime(internaldate)
  58. )
  59. if internaldate_msg > last_download_date:
  60. messages.append(new_uid)
  61. date_uids[new_uid] = internaldate_msg
  62. for num in messages:
  63. # SEARCH command *always* returns at least the most
  64. # recent message, even if it has already been synced
  65. res_id = None
  66. result, data = imap_server.fetch(num, '(RFC822)')
  67. imap_server.store(num, '-FLAGS', '\\Seen')
  68. if data and data[0]:
  69. try:
  70. res_id = mail_thread.message_process(
  71. cr, uid,
  72. server.object_id.model,
  73. data[0][1],
  74. save_original=server.original,
  75. strip_attachments=(not server.attach),
  76. context=context)
  77. except Exception:
  78. _logger.exception(
  79. 'Failed to process mail \
  80. from %s server %s.',
  81. server.type,
  82. server.name)
  83. failed += 1
  84. if res_id and server.action_id:
  85. action_pool.run(
  86. cr, uid, [server.action_id.id],
  87. {
  88. 'active_id': res_id,
  89. 'active_ids': [res_id],
  90. 'active_model': context.get(
  91. "thread_model",
  92. server.object_id.model)
  93. }, context=context)
  94. imap_server.store(num, '+FLAGS', '\\Seen')
  95. cr.commit()
  96. count += 1
  97. last_date = not failed and date_uids[num] or False
  98. return count, failed, last_date
  99. def fetch_mail(self, cr, uid, ids, context=None):
  100. """WARNING: meant for cron usage only -
  101. will commit() after each email!
  102. """
  103. if context is None:
  104. context = {}
  105. context['fetchmail_cron_running'] = True
  106. mail_thread = self.pool.get('mail.thread')
  107. action_pool = self.pool.get('ir.actions.server')
  108. for server in self.browse(cr, uid, ids, context=context):
  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. if server.type == 'imap' and server.last_download_date:
  118. try:
  119. imap_server = server.connect()
  120. imap_server.select()
  121. count, failed, last_date = self._fetch_from_data_imap(
  122. cr, uid, server, imap_server, mail_thread,
  123. action_pool, count, failed, context=context
  124. )
  125. except Exception:
  126. _logger.exception(
  127. "General failure when trying to fetch mail \
  128. from %s server %s.",
  129. server.type,
  130. server.name
  131. )
  132. finally:
  133. if imap_server:
  134. imap_server.close()
  135. imap_server.logout()
  136. if last_date:
  137. _logger.info(
  138. "Fetched %d email(s) on %s server %s; \
  139. %d succeeded, %d failed.", count,
  140. server.type, server.name,
  141. (count - failed), failed)
  142. vals = {'last_download_date': last_date}
  143. server.write(vals)
  144. return super(FetchmailServer, self).fetch_mail(
  145. cr, uid, ids, context=context)