]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
[3.14] gh-108280: Give a meaningful error for an invalid imaplib greeting (GH-152768...
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>
Thu, 2 Jul 2026 07:42:15 +0000 (09:42 +0200)
committerGitHub <noreply@github.com>
Thu, 2 Jul 2026 07:42:15 +0000 (07:42 +0000)
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.
(cherry picked from commit 262b6a0df5a325e788928ab0cd514fa4786571b4)

Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Lib/imaplib.py
Lib/test/test_imaplib.py
Misc/NEWS.d/next/Library/2026-07-01-12-00-00.gh-issue-108280.Nq8vTr.rst [new file with mode: 0644]

index b9c068f214886b295842a068b9328923b545632f..0bdb9ff047ba7bb9ce6ea006320d0151dc06d66d 100644 (file)
@@ -256,7 +256,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__:
index ea3c1cce35b3bc925e6d083ecef86740848f2a01..3bad7872df36525e930e37e19c1cf127afda827d 100644 (file)
@@ -332,6 +332,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 (file)
index 0000000..487c9da
--- /dev/null
@@ -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``.