Skip to content

Simpler and more conformant keepalive feature #406

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

augfab
Copy link

@augfab augfab commented Jun 8, 2025

The keepalive feature of DavMail is implemented in a way that doesn't please Python's imaplib, and by extension offlineimap3. There must be exactly one space after the * in an untagged response. See commit messages for more details.

This branch is (I believe) a proper fix for issues #41 #122 #343. As a bonus, I've rewritten the logic to make the keepalive code path a pure addition on top of the regular code path (main thread).

I have had these patches over release 6.2.1 for some months now.

Thanks for this project.

augfab added 3 commits March 10, 2025 21:47
Before the change, the keepalive was always sent, even if the thread had
completed before the join timeout.

After the change, we break the loop immediately after the thread join if
the folder load is complete.
When the load folder thread join timeout expires send a keepalive
message of the form:

 * OK in progress...

This response is conform to RFC3501 and understood by Python's imaplib,
used by offlineimap3.

See sections 7.1 and 7.1.1 of RFC3501 (IMAP4rev1), sections 7.1 and
7.1.1 of RFC9051 (IMAP4rev2), and RFC9585 (response code INPROGRESS).

Fixes: mguessan#41 mguessan#122 mguessan#343.
Linked-to: python/cpython#81588 python/cpython#117152 python/cpython#62353.
Perform the long-running in the main thread, and start a parallel thread
to send the keep-alive message at regular interval.  This makes the code
more regular and the feature more encapsulated.  The parallel thread is
started only when the number of messages to load is greater than 500,
and the keep-alive feature is enables.  The keep-alive thread is
canceled as soon as the folder has loaded its messages.  The keep-alive
task is scheduled to be sent every 20 s, after an initial delay of 20 s.
@esabol
Copy link

esabol commented Jun 9, 2025

Time and again, @mguessan's response has to been that, if you don't want two spaces, then to set

davmail.enableKeepAlive=false

and that doing so should "please Python's imaplib", as you put it. Did you try doing that? Is that not the case?

Does your PR also fix the issue with client's timing out when interacting with large folders in a way that's superior to the current workaround employed for large folders when davmail.enableKeepAlive is not false?

@augfab
Copy link
Author

augfab commented Jun 9, 2025

Yes I have tried the official workaround of disabling the keepalive feature, and indeed offlineimap is pleased.

However, I was convinced that it was possible to implement a keepalive mechanism conforming to the IMAP protocol. I think that I have found such a solution.

The second commit in the branch sends an untagged OK response every twenty seconds. From RFC 3501 (IMAP4rev1), § 7.1.1:

The OK response indicates an information message from the server. […] The untagged form indicates an information-only message; the nature of the information MAY be indicated by a response code.

RFC 9585 adds an untagged response code INPROGRESS dedicated to the task of keeping the client connection alive. Example from the RFC:

* OK [INPROGRESS] Hang in there...

However Davmail implements RFC 3501 (IMAP4rev1) which states (§ 7.1):

Client implementations SHOULD ignore response codes that they do not recognize.

So it is a bit risky to send this unexpected/unknown response code to clients.

On the other hand RFC 9051 (IMAP4rev2) states:

Client implementations MUST ignore response codes that they do not recognize.

@mguessan
Copy link
Owner

I like this new approach to implement keepalive using only standard responses. Would need some testing to confirm we don't get any regressions.

mguessan added a commit that referenced this pull request Jun 15, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants