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.

126 lines
4.6 KiB

  1. # Copyright 2015-2019 Camptocamp SA
  2. # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
  3. import logging
  4. import datetime
  5. from dateutil.relativedelta import relativedelta
  6. from odoo import api, fields, models
  7. _logger = logging.getLogger(__name__)
  8. class FetchmailServer(models.Model):
  9. """Incoming POP/IMAP mail server account."""
  10. _inherit = 'fetchmail.server'
  11. cleanup_days = fields.Integer(
  12. string='Expiration days',
  13. help="Number of days before marking an e-mail as read",
  14. )
  15. cleanup_folder = fields.Char(
  16. string='Expiration folder',
  17. help="Folder where an e-mail marked as read will be moved.",
  18. )
  19. purge_days = fields.Integer(
  20. string='Deletion days',
  21. help="Number of days before removing an e-mail",
  22. )
  23. @property
  24. def _server_env_fields(self):
  25. base_fields = super()._server_env_fields
  26. mail_cleanup_fields = {
  27. 'cleanup_days': {
  28. 'getter': 'getint',
  29. },
  30. 'purge_days': {
  31. 'getter': 'getint',
  32. },
  33. 'cleanup_folder': {},
  34. }
  35. mail_cleanup_fields.update(base_fields)
  36. return mail_cleanup_fields
  37. def _cleanup_fetchmail_server(self, server, imap_server):
  38. count, failed = 0, 0
  39. expiration_date = datetime.date.today()
  40. expiration_date -= relativedelta(days=server.cleanup_days)
  41. search_text = expiration_date.strftime('(UNSEEN BEFORE %d-%b-%Y)')
  42. imap_server.select()
  43. result, data = imap_server.search(None, search_text)
  44. for num in data[0].split():
  45. try:
  46. # Mark message as read
  47. imap_server.store(num, '+FLAGS', '\\Seen')
  48. if server.cleanup_folder:
  49. # To move a message, you have to COPY
  50. # then DELETE the message
  51. result = imap_server.copy(num, server.cleanup_folder)
  52. if result[0] == 'OK':
  53. imap_server.store(num, '+FLAGS', '\\Deleted')
  54. except Exception:
  55. _logger.exception(
  56. 'Failed to cleanup mail from %s server %s.',
  57. server.type, server.name)
  58. failed += 1
  59. count += 1
  60. _logger.info(
  61. 'Marked %d email(s) as read on %s server %s;'
  62. ' %d succeeded, %d failed.', count, server.type,
  63. server.name, (count - failed), failed)
  64. def _purge_fetchmail_server(self, server, imap_server):
  65. # Purging e-mails older than the purge date, if available
  66. count, failed = 0, 0
  67. purge_date = datetime.date.today()
  68. purge_date -= relativedelta(days=server.purge_days)
  69. search_text = purge_date.strftime('(BEFORE %d-%b-%Y)')
  70. imap_server.select()
  71. result, data = imap_server.search(None, search_text)
  72. for num in data[0].split():
  73. try:
  74. # Delete message
  75. imap_server.store(num, '+FLAGS', '\\Deleted')
  76. except Exception:
  77. _logger.exception(
  78. 'Failed to remove mail from %s server %s.',
  79. server.type, server.name)
  80. failed += 1
  81. count += 1
  82. _logger.info(
  83. 'Removed %d email(s) on %s server %s;'
  84. ' %d succeeded, %d failed.', count, server.type,
  85. server.name, (count - failed), failed)
  86. @api.multi
  87. def fetch_mail(self):
  88. # Called before the fetch, in order to clean up right before
  89. # retrieving emails.
  90. for server in self:
  91. _logger.info('start cleaning up emails on %s server %s',
  92. server.type, server.name)
  93. imap_server = False
  94. if server.type == 'imap':
  95. try:
  96. imap_server = server.connect()
  97. if server.cleanup_days > 0:
  98. self._cleanup_fetchmail_server(server, imap_server)
  99. if server.purge_days > 0:
  100. self._purge_fetchmail_server(server, imap_server)
  101. # Do the final cleanup: delete all messages
  102. # flagged as deleted
  103. imap_server.expunge()
  104. except Exception:
  105. _logger.exception(
  106. 'General failure when trying to cleanup'
  107. ' mail from %s server %s.',
  108. server.type, server.name)
  109. finally:
  110. if imap_server:
  111. imap_server.close()
  112. imap_server.logout()
  113. return super().fetch_mail()