Skip to content

Commit c8663d3

Browse files
miss-islingtonserhiy-storchakaclaude
authored
[3.14] gh-108280: Give a meaningful error for an invalid imaplib greeting (GH-152768) (GH-152857)
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 262b6a0) Co-authored-by: Serhiy Storchaka <storchaka@gmail.com> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 9f4a944 commit c8663d3

3 files changed

Lines changed: 42 additions & 1 deletion

File tree

Lib/imaplib.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,11 @@ def _connect(self):
256256
elif 'OK' in self.untagged_responses:
257257
self.state = 'NONAUTH'
258258
else:
259-
raise self.error(self.welcome)
259+
# A continuation ('+') greeting is returned as None; report its
260+
# raw line, still held by the last match (gh-108280).
261+
greeting = (self.welcome or self.mo.string).decode(
262+
self._encoding, 'replace')
263+
raise self.error('invalid greeting: ' + greeting)
260264

261265
self._refresh_capabilities()
262266
if __debug__:

Lib/test/test_imaplib.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,39 @@ def handle(self):
332332
self.assertRaises(imaplib.IMAP4.abort, self.imap_class,
333333
*server.server_address)
334334

335+
def test_invalid_greeting(self):
336+
# An invalid greeting, e.g. from a POP3 server on the IMAP port,
337+
# must not fail with "error: None" but report the server's line
338+
# (gh-108280).
339+
class Pop3Handler(socketserver.StreamRequestHandler):
340+
def handle(self):
341+
self.wfile.write(b'+OK POP3 server ready\r\n')
342+
_, server = self._setup(Pop3Handler, connect=False)
343+
with self.assertRaisesRegex(imaplib.IMAP4.error,
344+
r'invalid greeting: \+OK POP3 server ready'):
345+
self.imap_class(*server.server_address)
346+
347+
def test_invalid_greeting_untagged(self):
348+
# An untagged greeting that is neither OK nor PREAUTH (e.g. BYE)
349+
# is reported as is (gh-108280).
350+
class ByeHandler(socketserver.StreamRequestHandler):
351+
def handle(self):
352+
self.wfile.write(b'* BYE Server unavailable\r\n')
353+
_, server = self._setup(ByeHandler, connect=False)
354+
with self.assertRaisesRegex(imaplib.IMAP4.error,
355+
r'invalid greeting: \* BYE Server unavailable'):
356+
self.imap_class(*server.server_address)
357+
358+
def test_invalid_greeting_bare_continuation(self):
359+
# A bare continuation greeting is still reported (gh-108280).
360+
class BareHandler(socketserver.StreamRequestHandler):
361+
def handle(self):
362+
self.wfile.write(b'+\r\n')
363+
_, server = self._setup(BareHandler, connect=False)
364+
with self.assertRaisesRegex(imaplib.IMAP4.error,
365+
r'invalid greeting: \+'):
366+
self.imap_class(*server.server_address)
367+
335368
def test_line_termination(self):
336369
class BadNewlineHandler(SimpleIMAPHandler):
337370
def cmd_CAPABILITY(self, tag, args):
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Connecting :mod:`imaplib` to a server that does not send a valid IMAP4
2+
greeting (for example a POP3 server answering on the IMAP port) now raises
3+
an error reporting the server's response instead of
4+
``imaplib.IMAP4.error: None``.

0 commit comments

Comments
 (0)