Skip to content

Commit d20e396

Browse files
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) <noreply@anthropic.com>
1 parent 564c58c commit d20e396

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._get_capabilities()
259263
if __debug__:

Lib/test/test_imaplib.py

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

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