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

# Copyright 2015-2019 Camptocamp SA
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
import logging
import datetime
from dateutil.relativedelta import relativedelta
from odoo import api, fields, models
_logger = logging.getLogger(__name__)
class FetchmailServer(models.Model):
"""Incoming POP/IMAP mail server account."""
_inherit = 'fetchmail.server'
cleanup_days = fields.Integer(
string='Expiration days',
help="Number of days before marking an e-mail as read",
)
cleanup_folder = fields.Char(
string='Expiration folder',
help="Folder where an e-mail marked as read will be moved.",
)
purge_days = fields.Integer(
string='Deletion days',
help="Number of days before removing an e-mail",
)
@property
def _server_env_fields(self):
base_fields = super()._server_env_fields
mail_cleanup_fields = {
'cleanup_days': {
'getter': 'getint',
},
'purge_days': {
'getter': 'getint',
},
'cleanup_folder': {},
}
mail_cleanup_fields.update(base_fields)
return mail_cleanup_fields
def _cleanup_fetchmail_server(self, server, imap_server):
count, failed = 0, 0
expiration_date = datetime.date.today()
expiration_date -= relativedelta(days=server.cleanup_days)
search_text = expiration_date.strftime('(UNSEEN BEFORE %d-%b-%Y)')
imap_server.select()
result, data = imap_server.search(None, search_text)
for num in data[0].split():
try:
# Mark message as read
imap_server.store(num, '+FLAGS', '\\Seen')
if server.cleanup_folder:
# To move a message, you have to COPY
# then DELETE the message
result = imap_server.copy(num, server.cleanup_folder)
if result[0] == 'OK':
imap_server.store(num, '+FLAGS', '\\Deleted')
except Exception:
_logger.exception(
'Failed to cleanup mail from %s server %s.',
server.type, server.name)
failed += 1
count += 1
_logger.info(
'Marked %d email(s) as read on %s server %s;'
' %d succeeded, %d failed.', count, server.type,
server.name, (count - failed), failed)
def _purge_fetchmail_server(self, server, imap_server):
# Purging e-mails older than the purge date, if available
count, failed = 0, 0
purge_date = datetime.date.today()
purge_date -= relativedelta(days=server.purge_days)
search_text = purge_date.strftime('(BEFORE %d-%b-%Y)')
imap_server.select()
result, data = imap_server.search(None, search_text)
for num in data[0].split():
try:
# Delete message
imap_server.store(num, '+FLAGS', '\\Deleted')
except Exception:
_logger.exception(
'Failed to remove mail from %s server %s.',
server.type, server.name)
failed += 1
count += 1
_logger.info(
'Removed %d email(s) on %s server %s;'
' %d succeeded, %d failed.', count, server.type,
server.name, (count - failed), failed)
@api.multi
def fetch_mail(self):
# Called before the fetch, in order to clean up right before
# retrieving emails.
for server in self:
_logger.info('start cleaning up emails on %s server %s',
server.type, server.name)
imap_server = False
if server.type == 'imap':
try:
imap_server = server.connect()
if server.cleanup_days > 0:
self._cleanup_fetchmail_server(server, imap_server)
if server.purge_days > 0:
self._purge_fetchmail_server(server, imap_server)
# Do the final cleanup: delete all messages
# flagged as deleted
imap_server.expunge()
except Exception:
_logger.exception(
'General failure when trying to cleanup'
' mail from %s server %s.',
server.type, server.name)
finally:
if imap_server:
imap_server.close()
imap_server.logout()
return super().fetch_mail()