[IMP] fetchmail: process pop messages in subsets

Most pop servers don't perform deletions until QUIT. If for some reason
the process is killed while fetching a large quantity of messages, the
quit method isn't invoked, while the commit method has been. We may thus
end up with duplicated messages the next time we try to fetch. It therefore
helps to fetch the messages in small subsets and call the quit method between
those subsets.
This commit is contained in:
Julien Legros 2015-02-09 13:21:06 +01:00
parent dd9d8b0c84
commit 318f254761
1 changed files with 26 additions and 21 deletions

View File

@ -40,6 +40,7 @@ from openerp import tools
from openerp.tools.translate import _ from openerp.tools.translate import _
_logger = logging.getLogger(__name__) _logger = logging.getLogger(__name__)
MAX_POP_MESSAGES = 50
class fetchmail_server(osv.osv): class fetchmail_server(osv.osv):
"""Incoming POP/IMAP mail server account""" """Incoming POP/IMAP mail server account"""
@ -223,27 +224,31 @@ openerp_mailgate: "|/path/to/openerp-mailgate.py --host=localhost -u %(uid)d -p
imap_server.logout() imap_server.logout()
elif server.type == 'pop': elif server.type == 'pop':
try: try:
pop_server = server.connect() while True:
(numMsgs, totalSize) = pop_server.stat() pop_server = server.connect()
pop_server.list() (numMsgs, totalSize) = pop_server.stat()
for num in range(1, numMsgs + 1): pop_server.list()
(header, msges, octets) = pop_server.retr(num) for num in range(1, min(MAX_POP_MESSAGES, numMsgs) + 1):
msg = '\n'.join(msges) (header, msges, octets) = pop_server.retr(num)
res_id = None msg = '\n'.join(msges)
try: res_id = None
res_id = mail_thread.message_process(cr, uid, server.object_id.model, try:
msg, res_id = mail_thread.message_process(cr, uid, server.object_id.model,
save_original=server.original, msg,
strip_attachments=(not server.attach), save_original=server.original,
context=context) strip_attachments=(not server.attach),
pop_server.dele(num) context=context)
except Exception: pop_server.dele(num)
_logger.exception('Failed to process mail from %s server %s.', server.type, server.name) except Exception:
failed += 1 _logger.exception('Failed to process mail from %s server %s.', server.type, server.name)
if res_id and server.action_id: failed += 1
action_pool.run(cr, uid, [server.action_id.id], {'active_id': res_id, 'active_ids': [res_id], 'active_model': context.get("thread_model", server.object_id.model)}) if res_id and server.action_id:
cr.commit() action_pool.run(cr, uid, [server.action_id.id], {'active_id': res_id, 'active_ids': [res_id], 'active_model': context.get("thread_model", server.object_id.model)})
_logger.info("Fetched %d email(s) on %s server %s; %d succeeded, %d failed.", numMsgs, server.type, server.name, (numMsgs - failed), failed) cr.commit()
if numMsgs < MAX_POP_MESSAGES:
break
pop_server.quit()
_logger.info("Fetched %d email(s) on %s server %s; %d succeeded, %d failed.", numMsgs, server.type, server.name, (numMsgs - failed), failed)
except Exception: except Exception:
_logger.exception("General failure when trying to fetch mail from %s server %s.", server.type, server.name) _logger.exception("General failure when trying to fetch mail from %s server %s.", server.type, server.name)
finally: finally: