Skip to content
Snippets Groups Projects
Commit 72cd8d07 authored by Nicolas Martinelli's avatar Nicolas Martinelli
Browse files

[FIX] fetchmail: do not loop endlessly


- Set up a POP account
- On the POP account, receive emails addressed to various recipients,
  e.g. `my_alias_1` and `my_alias_2`. Receive more than 50 emails to
  `my_alias_2`.
- In Odoo, create a mail alias for `my_alias_1`
- Run the fetchmail cron

The cron runs endlessly until it is killed. In the logs, inconsistent
messages are shown:

```
...
Fetched 3507 email(s) on pop server xxx; -16493 succeeded, 20000 failed.
Fetched 3507 email(s) on pop server xxx; -16543 succeeded, 20050 failed.
...
```

First the message count is incorrect in the log. We fetched at most 50
emails, not the total number of emails. Then, the endless loop is due
to the fact that
- we do not delete failed messages (= messages addressed to
  `my_alias_2`)
- we always fetch messages from `num=1`

If the first 50 messages fail, we fetch them endlessly until the cron is
killed.

To avoid this, we compare the number of failed messages with the number
of messages retrieved. If all messages retrieved have failed, we stop
the loop.

After the fix, consistent messages are show in the logs and the process
stops after the first complete failure:

```
start checking for new emails on pop server xxx
Fetched 50 email(s) on pop server xxx; 0 succeeded, 50 failed.
```

Note that it doesn't solve the core of the issue; we just fail faster. A
proper way would probably be to use an offset so we don't always start
at `num=1`. On the other hand, it is just a matter of time before the
cron times out: if the mailbox is full of messages which canot be
treated, we will just spend more and more time trying to find the ones
which can be treated.

closes odoo/odoo#81115

Signed-off-by: default avatarNicolas Martinelli (nim) <nim@odoo.com>
parent 17465e2b
No related branches found
No related tags found
No related merge requests found
......@@ -182,6 +182,7 @@ odoo_mailgate: "|/path/to/odoo-mailgate.py --host=localhost -u %(uid)d -p PASSWO
elif server.server_type == 'pop':
try:
while True:
failed_in_loop = 0
pop_server = server.connect()
(num_messages, total_size) = pop_server.stat()
pop_server.list()
......@@ -195,11 +196,13 @@ odoo_mailgate: "|/path/to/odoo-mailgate.py --host=localhost -u %(uid)d -p PASSWO
except Exception:
_logger.info('Failed to process mail from %s server %s.', server.server_type, server.name, exc_info=True)
failed += 1
failed_in_loop += 1
self.env.cr.commit()
if num_messages < MAX_POP_MESSAGES:
_logger.info("Fetched %d email(s) on %s server %s; %d succeeded, %d failed.", num, server.server_type, server.name, (num - failed_in_loop), failed_in_loop)
# Stop if (1) no more message left or (2) all messages have failed
if num_messages < MAX_POP_MESSAGES or failed_in_loop == num:
break
pop_server.quit()
_logger.info("Fetched %d email(s) on %s server %s; %d succeeded, %d failed.", num_messages, server.server_type, server.name, (num_messages - failed), failed)
except Exception:
_logger.info("General failure when trying to fetch mail from %s server %s.", server.server_type, server.name, exc_info=True)
finally:
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment