Skip to content

Commit 262b6a0

Browse files
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) <noreply@anthropic.com>
1 parent c89b72a commit 262b6a0

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
@@ -253,7 +253,11 @@ def _connect(self):
253253
elif 'OK' in self.untagged_responses:
254254
self.state = 'NONAUTH'
255255
else:
256-
raise self.error(self.welcome)
256+
# A continuation ('+') greeting is returned as None; report its
257+
# raw line, still held by the last match (gh-108280).
258+
greeting = (self.welcome or self.mo.string).decode(
259+
self._encoding, 'replace')
260+
raise self.error('invalid greeting: ' + greeting)
257261

258262
self._refresh_capabilities()
259263
if __debug__:

Lib/test/test_imaplib.py

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

334+
def test_invalid_greeting(self):
335+
# An invalid greeting, e.g. from a POP3 server on the IMAP port,
336+
# must not fail with "error: None" but report the server's line
337+
# (gh-108280).
338+
class Pop3Handler(socketserver.StreamRequestHandler):
339+
def handle(self):
340+
self.wfile.write(b'+OK POP3 server ready\r\n')
341+
_, server = self._setup(Pop3Handler, connect=False)
342+
with self.assertRaisesRegex(imaplib.IMAP4.error,
343+
r'invalid greeting: \+OK POP3 server ready'):
344+
self.imap_class(*server.server_address)
345+
346+
def test_invalid_greeting_untagged(self):
347+
# An untagged greeting that is neither OK nor PREAUTH (e.g. BYE)
348+
# is reported as is (gh-108280).
349+
class ByeHandler(socketserver.StreamRequestHandler):
350+
def handle(self):
351+
self.wfile.write(b'* BYE Server unavailable\r\n')
352+
_, server = self._setup(ByeHandler, connect=False)
353+
with self.assertRaisesRegex(imaplib.IMAP4.error,
354+
r'invalid greeting: \* BYE Server unavailable'):
355+
self.imap_class(*server.server_address)
356+
357+
def test_invalid_greeting_bare_continuation(self):
358+
# A bare continuation greeting is still reported (gh-108280).
359+
class BareHandler(socketserver.StreamRequestHandler):
360+
def handle(self):
361+
self.wfile.write(b'+\r\n')
362+
_, server = self._setup(BareHandler, connect=False)
363+
with self.assertRaisesRegex(imaplib.IMAP4.error,
364+
r'invalid greeting: \+'):
365+
self.imap_class(*server.server_address)
366+
334367
def test_line_termination(self):
335368
class BadNewlineHandler(SimpleIMAPHandler):
336369
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)