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.

155 lines
6.3 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_internal_date': fields.datetime('Last Internal 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_internal_date = datetime.strptime(
  44. server.last_internal_date, "%Y-%m-%d %H:%M:%S")
  45. #~ timestamp1 = time.mktime(last_internal_date.timetuple())
  46. #~ intDate = imaplib.Time2Internaldate(timestamp1)
  47. search_status, uids = imap_server.search(
  48. None,
  49. 'SINCE', '%s' % last_internal_date.strftime('%d-%b-%Y')
  50. )
  51. new_uids = uids[0].split()
  52. for new_uid in new_uids:
  53. fetch_status, data = imap_server.fetch(
  54. int(new_uid),
  55. 'INTERNALDATE'
  56. )
  57. internaldate = imaplib.Internaldate2tuple(data[0])
  58. internaldate_msg = datetime.fromtimestamp(
  59. time.mktime(internaldate)
  60. )
  61. if internaldate_msg > last_internal_date:
  62. messages.append(new_uid)
  63. date_uids[new_uid] = internaldate_msg
  64. for num in messages:
  65. # SEARCH command *always* returns at least the most
  66. # recent message, even if it has already been synced
  67. res_id = None
  68. result, data = imap_server.fetch(num, '(RFC822)')
  69. imap_server.store(num, '-FLAGS', '\\Seen')
  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. """WARNING: meant for cron usage only -
  103. will commit() after each email!
  104. """
  105. if context is None:
  106. context = {}
  107. context['fetchmail_cron_running'] = True
  108. mail_thread = self.pool.get('mail.thread')
  109. action_pool = self.pool.get('ir.actions.server')
  110. for server in self.browse(cr, uid, ids, context=context):
  111. _logger.info(
  112. 'start checking for new emails by date on %s server %s',
  113. server.type, server.name)
  114. context.update({'fetchmail_server_id': server.id,
  115. 'server_type': server.type})
  116. count, failed = 0, 0
  117. last_date = False
  118. imap_server = False
  119. if server.type == 'imap' and server.last_internal_date:
  120. try:
  121. imap_server = server.connect()
  122. imap_server.select()
  123. count, failed, last_date = self._fetch_from_data_imap(
  124. cr, uid, server, imap_server, mail_thread,
  125. action_pool, count, failed, context=context
  126. )
  127. except Exception:
  128. _logger.exception(
  129. "General failure when trying to fetch mail \
  130. from %s server %s.",
  131. server.type,
  132. server.name
  133. )
  134. finally:
  135. if imap_server:
  136. imap_server.close()
  137. imap_server.logout()
  138. if last_date:
  139. _logger.info(
  140. "Fetched %d email(s) on %s server %s; \
  141. %d succeeded, %d failed.", count,
  142. server.type, server.name,
  143. (count - failed), failed)
  144. vals = {'last_internal_date': last_date}
  145. server.write(vals)
  146. return super(FetchmailServer, self).fetch_mail(
  147. cr, uid, ids, context=context)