This way we avoid an immediate retry if the network is not yet ready exhausting the ratelimiter's
quota of two connection attempts. Also notify the ratelimiter only after a successful connection so
that it only limits the server load, but not connection attempts.
`a.clone_from(&b)` is equivalent to `a = b.clone()` in functionality,
but can be overridden to reuse the resources of a to avoid unnecessary
allocations.
Connection establishment now happens only in one place in each IMAP loop.
Now all connection establishment happens in one place
and is limited by the ratelimit.
Backoff was removed from fake_idle
as it does not establish connections anymore.
If connection fails, fake_idle will return an error.
We then drop the connection and get back to the beginning of IMAP
loop.
Backoff may be still nice to have to delay retries
in case of constant connection failures
so we don't immediately hit ratelimit if the network is unusable
and returns immediate error on each connection attempt
(e.g. ICMP network unreachable error),
but adding backoff for connection failures is out of scope for this change.
ratelimit can be exhausted quickly if the network is not available,
i.e. if every connection attempt returns "network unreachable" error.
When the network becomes available, we want to retry connecting
as soon as maybe_network is called without waiting for ratelimiter.
In this case connection failure
may be a connection timeout (currently 1 minute),
so it does not make sense to fake idle for another minute immediately after.
However, failure may be immediate if the port is closed
and the server refuses connection every time.
To prevent busy loop in this case
we apply ratelimit to connection attempts rather than login attempts.
This partially reverts ccec26ffa7
Restart the IO scheduler if needed to make the new config value effective (for `MvboxMove,
OnlyFetchMvbox, SentboxWatch` currently). Also add `set_config_internal()` which doesn't affect
running the IO scheduler. The reason is that `Scheduler::start()` itself calls `set_config()`,
although not for the mentioned keys, but still, and also Rust complains about recursive async calls.
Before moving emails to the mvbox we need to remember its UIDVALIDITY, otherwise emails moved before
that wouldn't be fetched but considered "old" instead.
Also:
- Don't use `session.create()` to create mvbox as `select_with_uidvalidity()` already creates mvbox
on its own.
- Don't try to create compat folders like "INBOX.DeltaChat", but only look for them.
If a Delta Chat message has the Message-ID already existing in the db, but a greater "Date", it's a
resent message that can be deleted. Messages having the same "Date" mustn't be deleted because they
can be already seen messages moved back to INBOX. Also don't delete messages having lesser "Date" to
avoid deleting both messages in a multi-device setting.
As ratelimit was introduced to avoid reconnecting immediately after disconnecting
in case of bugs in IMAP protocol handling,
connection attempts should only be counted when IMAP is actually used,
i.e. when the first command (LOGIN) is sent.
Limit the number of IMAP connections to 1 per minute regardless of the reason of reconnection, but
allow one immediate retry. This is more reliable than ratelimiting only in error conditions because
ratelimiting can't be skipped by mistake. Anyway connections shouldn't be frequent in normal
operation mode.
Otherwise when connection is lost IMAP may get into infinite loop
trying to parse remaining bytes:
11-21 18:00:48.442 14858 12946 W DeltaChat: src/imap.rs:1457: Failed to process IMAP FETCH result: io: bytes remaining in stream.
11-21 18:00:48.442 14858 12946 W DeltaChat: src/imap.rs:1457: Failed to process IMAP FETCH result: io: bytes remaining in stream.
11-21 18:00:48.442 14858 12946 W DeltaChat: src/imap.rs:1457: Failed to process IMAP FETCH result: io: bytes remaining in stream.
11-21 18:00:48.442 14858 12946 W DeltaChat: src/imap.rs:1457: Failed to process IMAP FETCH result: io: bytes remaining in stream.
11-21 18:00:48.442 14858 12946 W DeltaChat: src/imap.rs:1457: Failed to process IMAP FETCH result: io: bytes remaining in stream.
11-21 18:00:48.442 14858 12946 W DeltaChat: src/imap.rs:1457: Failed to process IMAP FETCH result: io: bytes remaining in stream.
Returning an error bubbles it up to `fetch_idle()`
which will call `trigger_reconnect()` and drop the connection.
Ensure the client does not busy loop
skipping IDLE if UIDNEXT of the mailbox is higher than
the last seen UID plus 1, e.g. if the message
with UID=UIDNEXT-1 was deleted before we fetched it.
We do not fallback to UIDNEXT=1 anymore
if the STATUS command cannot determine UIDNEXT.
There are no known IMAP servers with broken STATUS so far.
This allows to guarantee that select_with_uidvalidity()
sets UIDNEXT for the mailbox and use it in fetch_new_messages()
to ensure that UIDNEXT always advances even
when there are no messages to fetch.