Skip to content

imaplib 3.14 regression: IMAP4.file became read-only property, breaking subclass overrides (affects imapclient IMAP4_TLS) #142307

@seanthegeek

Description

@seanthegeek

Bug report

Bug description:

In Python 3.14, imaplib.IMAP4.file was changed from a normal attribute to a read-only property.
This breaks legitimate subclassing patterns used by third-party libraries such as imapclient, which override open() and assign to self.file.

Example failure

Running imapclient’s IMAP4_TLS on Python 3.14 produces:

AttributeError: property 'file' of 'IMAP4_TLS' object has no setter

Regression cause

In Python 3.14, imaplib.IMAP4.file was changed to:

 @property
    def file(self):
        # The old 'file' attribute is no longer used now that we do our own
        # read() and readline() buffering, with which it conflicts.
        # As an undocumented interface, it should never have been accessed by
        # external code, and therefore does not warrant deprecation.
        # Nevertheless, we provide this property for now, to avoid suddenly
        # breaking any code in the wild that might have been using it in a
        # harmless way.
        import warnings
        warnings.warn(
            'IMAP4.file is unsupported, can cause errors, and may be removed.',
            RuntimeWarning,
            stacklevel=2)
        return self._file

with no setter provided.

https://github.com/python/cpython/blob/3.14/Lib/imaplib.py#L319-L333

Prior to 3.14, file was a normal attribute and writable.

 def open(self, host='', port=IMAP4_PORT, timeout=None):
        """Setup connection to remote server on "host:port"
            (default: localhost:standard IMAP4 port).
        This connection will be used by the routines:
            read, readline, send, shutdown.
        """
        self.host = host
        self.port = port
        self.sock = self._create_socket(timeout)
        self.file = self.sock.makefile('rb')

https://github.com/python/cpython/blob/3.13/Lib/imaplib.py#L307-L316

Why this is a compatibility break

Even though file was undocumented, turning a previously writable instance attribute into a read-only property introduces a silent backward-incompatible change for:

  • Subclasses which override the I/O layer
  • SSL/TLS IMAP wrappers such as imapclient’s IMAP4_TLS
  • Any code that monkeypatches or replaces the socket reader

Making file immutable removes the ability to replace the buffered reader the base class uses.

Expected behavior

At minimum, subclass overrides should continue to work.
Options include:

  1. Add a setter to the property that writes to _file
  2. Or rename the internal attribute (e.g., _imaplib_file) instead of shadowing a long-existing public attribute name
  3. Or provide an explicit API for replacing the buffered input stream
  4. Or adjust the documentation to specify expected subclass hooks and ensure compatibility

Impact

This change breaks:

  • imapclient (over 1 million downloads per month)
  • Libraries layered on top of imapclient, including mailsuite and parsedmarc
  • All users of IMAP SSL/TLS wrappers relying on custom socket readers

The imapclient maintainers have an open issue tracking this:
mjs/imapclient#618

parsedmarc has an open issue here: domainaware/parsedmarc#636

Request

Please consider restoring backward compatibility by adding a setter or by adjusting the refactor so that subclass assignment to self.file is still possible.

CPython versions tested on:

3.14

Operating systems tested on:

No response

Linked PRs

Metadata

Metadata

Assignees

Labels

3.14bugs and security fixes3.15new features, bugs and security fixesstdlibStandard Library Python modules in the Lib/ directorytopic-emailtype-bugAn unexpected behavior, bug, or error

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions