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.

130 lines
5.4 KiB

  1. # -*- coding: utf-8 -*-
  2. ##############################################################################
  3. #
  4. # Author: Matthieu Dietrich
  5. # Copyright 2015 Camptocamp SA
  6. #
  7. # This program is free software: you can redistribute it and/or modify
  8. # it under the terms of the GNU Affero General Public License as
  9. # published by the Free Software Foundation, either version 3 of the
  10. # License, or (at your option) any later version.
  11. #
  12. # This program is distributed in the hope that it will be useful,
  13. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. # GNU Affero General Public License for more details.
  16. #
  17. # You should have received a copy of the GNU Affero General Public License
  18. # along with this program. If not, see <http://www.gnu.org/licenses/>.
  19. #
  20. ##############################################################################
  21. import logging
  22. from openerp.osv import orm, fields
  23. from dateutil import relativedelta
  24. from datetime import datetime
  25. from server_environment import serv_config
  26. _logger = logging.getLogger(__name__)
  27. class FetchmailServer(orm.Model):
  28. """Incoming POP/IMAP mail server account"""
  29. _inherit = 'fetchmail.server'
  30. def _get_cleanup_conf(self, cursor, uid, ids, name, args, context=None):
  31. """
  32. Return configuration
  33. """
  34. res = {}
  35. for fetchmail in self.browse(cursor, uid, ids):
  36. global_section_name = 'incoming_mail'
  37. # default vals
  38. config_vals = {'cleanup_days': "30",
  39. 'cleanup_folder': False}
  40. if serv_config.has_section(global_section_name):
  41. config_vals.update(serv_config.items(global_section_name))
  42. custom_section_name = '.'.join((global_section_name,
  43. fetchmail.name))
  44. if serv_config.has_section(custom_section_name):
  45. config_vals.update(serv_config.items(custom_section_name))
  46. # convert string value to integer
  47. config_vals['cleanup_days'] = int(config_vals['cleanup_days'])
  48. res[fetchmail.id] = config_vals
  49. return res
  50. _columns = {
  51. 'cleanup_days': fields.function(
  52. _get_cleanup_conf,
  53. method=True,
  54. string='Expiration days',
  55. type="integer",
  56. multi='outgoing_mail_config',
  57. help="Number of days before discarding an e-mail"),
  58. 'cleanup_folder': fields.function(
  59. _get_cleanup_conf,
  60. method=True,
  61. string='Expiration folder',
  62. type="char",
  63. multi='outgoing_mail_config',
  64. help="Folder where the discarded e-mail will be moved.")
  65. }
  66. def _cleanup_fetchmail_server(self, server, imap_server):
  67. count, failed = 0, 0
  68. expiration_date = (datetime.now() + relativedelta.relativedelta(
  69. days=-(server.cleanup_days))).strftime('%d-%b-%Y')
  70. search_text = '(UNSEEN BEFORE %s)' % expiration_date
  71. imap_server.select()
  72. result, data = imap_server.search(None, search_text)
  73. for num in data[0].split():
  74. result, data = imap_server.fetch(num, '(RFC822)')
  75. try:
  76. # Mark message as read
  77. imap_server.store(num, '+FLAGS', '\\Seen')
  78. if server.cleanup_folder:
  79. # To move a message, you have to COPY
  80. # then DELETE the message
  81. result = imap_server.copy(num, server.cleanup_folder)
  82. if result[0] == 'OK':
  83. imap_server.store(num, '+FLAGS', '\\Deleted')
  84. imap_server.expunge()
  85. except Exception:
  86. _logger.exception('Failed to cleanup mail from %s server %s.',
  87. server.type, server.name)
  88. failed += 1
  89. count += 1
  90. _logger.info("Fetched %d email(s) on %s server %s; "
  91. "%d succeeded, %d failed.", count, server.type,
  92. server.name, (count - failed), failed)
  93. def fetch_mail(self, cr, uid, ids, context=None):
  94. """ Called before the fetch, in order to clean up
  95. right before retrieving emails. """
  96. if context is None:
  97. context = {}
  98. context['fetchmail_cron_running'] = True
  99. for server in self.browse(cr, uid, ids, context=context):
  100. _logger.info('start cleaning up emails on %s server %s',
  101. server.type, server.name)
  102. context.update({'fetchmail_server_id': server.id,
  103. 'server_type': server.type})
  104. imap_server = False
  105. if server.type == 'imap' and server.cleanup_days > 0:
  106. try:
  107. imap_server = server.connect()
  108. self._cleanup_fetchmail_server(server, imap_server)
  109. except Exception:
  110. _logger.exception("General failure when trying to cleanup "
  111. "mail from %s server %s.",
  112. server.type, server.name)
  113. finally:
  114. if imap_server:
  115. imap_server.close()
  116. imap_server.logout()
  117. return super(FetchmailServer, self).fetch_mail(cr, uid, ids,
  118. context=context)