From: Serhiy Storchaka Date: Thu, 2 Jul 2026 07:15:13 +0000 (+0300) Subject: gh-108280: Give a meaningful error for an invalid imaplib greeting (GH-152768) X-Git-Url: http://git.ipfire.org/gitweb/index.cgi?a=commitdiff_plain;h=262b6a0df5a325e788928ab0cd514fa4786571b4;p=thirdparty%2FPython%2Fcpython.git gh-108280: Give a meaningful error for an invalid imaplib greeting (GH-152768) 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) --- diff --git a/Lib/imaplib.py b/Lib/imaplib.py index 26773fb0ee08..ca2ae40726b2 100644 --- a/Lib/imaplib.py +++ b/Lib/imaplib.py @@ -253,7 +253,11 @@ class IMAP4: 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._refresh_capabilities() if __debug__: diff --git a/Lib/test/test_imaplib.py b/Lib/test/test_imaplib.py index fa23d09806e6..67bf47ad41a1 100644 --- a/Lib/test/test_imaplib.py +++ b/Lib/test/test_imaplib.py @@ -331,6 +331,39 @@ class NewIMAPTestsMixin: 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 000000000000..487c9da67f18 --- /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``.