From d20e396c69d328288e9beeb09b2f51140d013014 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Wed, 1 Jul 2026 11:24:10 +0300 Subject: [PATCH] gh-108280: Give a meaningful error for an invalid imaplib greeting Connecting to a server that does not send a valid IMAP4 greeting, such as a POP3 server answering on the IMAP port, failed with the unhelpful "imaplib.IMAP4.error: None". A meaningful message is now raised instead. Co-Authored-By: Claude Opus 4.8 (1M context) --- Lib/imaplib.py | 6 +++- Lib/test/test_imaplib.py | 33 +++++++++++++++++++ ...-07-01-12-00-00.gh-issue-108280.Nq8vTr.rst | 4 +++ 3 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 Misc/NEWS.d/next/Library/2026-07-01-12-00-00.gh-issue-108280.Nq8vTr.rst diff --git a/Lib/imaplib.py b/Lib/imaplib.py index 497b5a60cecb08..af6b009d0446ec 100644 --- a/Lib/imaplib.py +++ b/Lib/imaplib.py @@ -253,7 +253,11 @@ def _connect(self): elif 'OK' in self.untagged_responses: self.state = 'NONAUTH' else: - raise self.error(self.welcome) + # A continuation ('+') greeting is returned as None; report its + # raw line, still held by the last match (gh-108280). + greeting = (self.welcome or self.mo.string).decode( + self._encoding, 'replace') + raise self.error('invalid greeting: ' + greeting) self._get_capabilities() if __debug__: diff --git a/Lib/test/test_imaplib.py b/Lib/test/test_imaplib.py index fb256fb7cbcd34..fdab4cd0ede3cf 100644 --- a/Lib/test/test_imaplib.py +++ b/Lib/test/test_imaplib.py @@ -329,6 +329,39 @@ def handle(self): self.assertRaises(imaplib.IMAP4.abort, self.imap_class, *server.server_address) + def test_invalid_greeting(self): + # An invalid greeting, e.g. from a POP3 server on the IMAP port, + # must not fail with "error: None" but report the server's line + # (gh-108280). + class Pop3Handler(socketserver.StreamRequestHandler): + def handle(self): + self.wfile.write(b'+OK POP3 server ready\r\n') + _, server = self._setup(Pop3Handler, connect=False) + with self.assertRaisesRegex(imaplib.IMAP4.error, + r'invalid greeting: \+OK POP3 server ready'): + self.imap_class(*server.server_address) + + def test_invalid_greeting_untagged(self): + # An untagged greeting that is neither OK nor PREAUTH (e.g. BYE) + # is reported as is (gh-108280). + class ByeHandler(socketserver.StreamRequestHandler): + def handle(self): + self.wfile.write(b'* BYE Server unavailable\r\n') + _, server = self._setup(ByeHandler, connect=False) + with self.assertRaisesRegex(imaplib.IMAP4.error, + r'invalid greeting: \* BYE Server unavailable'): + self.imap_class(*server.server_address) + + def test_invalid_greeting_bare_continuation(self): + # A bare continuation greeting is still reported (gh-108280). + class BareHandler(socketserver.StreamRequestHandler): + def handle(self): + self.wfile.write(b'+\r\n') + _, server = self._setup(BareHandler, connect=False) + with self.assertRaisesRegex(imaplib.IMAP4.error, + r'invalid greeting: \+'): + self.imap_class(*server.server_address) + def test_line_termination(self): class BadNewlineHandler(SimpleIMAPHandler): def cmd_CAPABILITY(self, tag, args): diff --git a/Misc/NEWS.d/next/Library/2026-07-01-12-00-00.gh-issue-108280.Nq8vTr.rst b/Misc/NEWS.d/next/Library/2026-07-01-12-00-00.gh-issue-108280.Nq8vTr.rst new file mode 100644 index 00000000000000..487c9da67f1832 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-07-01-12-00-00.gh-issue-108280.Nq8vTr.rst @@ -0,0 +1,4 @@ +Connecting :mod:`imaplib` to a server that does not send a valid IMAP4 +greeting (for example a POP3 server answering on the IMAP port) now raises +an error reporting the server's response instead of +``imaplib.IMAP4.error: None``.