python / cpython

The Python programming language
https://www.python.org
Other
61.97k stars 29.8k forks source link

Implementation of RFC 2971 for imaplib #98092

Open noudin-ledger opened 1 year ago

noudin-ledger commented 1 year ago

Feature or enhancement

imaplib currently does not support RFC 2971

Pitch

This extension is easy to implement, and enables better debugging on the server side and statistics collection.

Previous discussion

None.

noudin-ledger commented 1 year ago

I propose myself to implement this.

ericvsmith commented 1 year ago

Please give a brief description of the RFC.

noudin-ledger commented 1 year ago

Sure:

RFC defines a new command ID. The sole purpose of the ID extension is to enable clients and servers to exchange information on their implementations for the purposes of statistical analysis and problem determination. ID command can be used by client to send an ID (hex information such as:

Client can also ask Server for its parameters.

Implementations MUST NOT use contact information to submit automatic bug reports. Implementations may include information from an ID response in a report automatically prepared, but are prohibited from sending the report without user authorization.

Basically by example:

C: a023 ID ("name" "sodr" "version" "19.34"
            "vendor" "Pink Floyd Music Limited")
S: * ID NIL
S: a023 OK ID completed

And

C: a042 ID NIL
S: * ID ("name" "Cyrus" "version" "1.5" "os" "sunos"
         "os-version" "5.5" 
         "support-url" "mailto:cyrus-bugs+@andrew.cmu.edu")
S: a042 OK ID command completed

Adding this RFC implementation (which already exists in customs versions of imaplib would allow all IMAP clients using it (such as https://github.com/OfflineIMAP/offlineimap3) to benefit from it and better support and bug leveraging.

nuffin commented 3 months ago

I just copy the code from imaplib2, and monkey patched imaplib at runtime 🤣 the code is simple, as blow:

###
# Monkey-patch imaplib to support the ID command ([RFC 2971](https://www.rfc-editor.org/rfc/rfc2971)) - begin
###
imaplib.Commands['ID'] = ('AUTH', 'SELECTED')

def imap_id_rfc2971(self, *kv_pairs, **kw):
    """(typ, [data]) = <instance>.id(kv_pairs)
    'kv_pairs' is a possibly empty list of keys and values.
    'data' is a list of ID key value pairs or NIL.
    NB: a single argument is assumed to be correctly formatted and is passed through unchanged
    (for backward compatibility with earlier version).
    Exchange information for problem analysis and determination.
    The ID extension is defined in RFC 2971. """

    name = 'ID'

    if not kv_pairs:
        data = 'NIL'
    elif len(kv_pairs) == 1:
        data = kv_pairs[0]     # Assume invoker passing correctly formatted string (back-compat)
    else:
        data = '(%s)' % ' '.join([(arg and self._quote(arg) or 'NIL') for arg in kv_pairs])

    return self._simple_command(name, data, **kw)

imaplib.IMAP4.id = imap_id_rfc2971
###
# Monkey-patch imaplib to support the ID command (RFC 2971) - end
###

This code should be used as a temporary fix to work with the servers that require ID command, and it have not processed the response from server yet.