Skip to content

Commit 3f0ef65

Browse files
miss-islingtonserhiy-storchakaclaude
authored
[3.13] gh-108280: Give a meaningful error for an invalid imaplib greeting (GH-152768) (GH-152858)
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 fba6c1a commit 3f0ef65

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
@@ -282,6 +282,39 @@ def handle(self):
282282
self.assertRaises(imaplib.IMAP4.abort, self.imap_class,
283283
*server.server_address)
284284

285+
def test_invalid_greeting(self):
286+
# An invalid greeting, e.g. from a POP3 server on the IMAP port,
287+
# must not fail with "error: None" but report the server's line
288+
# (gh-108280).
289+
class Pop3Handler(socketserver.StreamRequestHandler):
290+
def handle(self):
291+
self.wfile.write(b'+OK POP3 server ready\r\n')
292+
_, server = self._setup(Pop3Handler, connect=False)
293+
with self.assertRaisesRegex(imaplib.IMAP4.error,
294+
r'invalid greeting: \+OK POP3 server ready'):
295+
self.imap_class(*server.server_address)
296+
297+
def test_invalid_greeting_untagged(self):
298+
# An untagged greeting that is neither OK nor PREAUTH (e.g. BYE)
299+
# is reported as is (gh-108280).
300+
class ByeHandler(socketserver.StreamRequestHandler):
301+
def handle(self):
302+
self.wfile.write(b'* BYE Server unavailable\r\n')
303+
_, server = self._setup(ByeHandler, connect=False)
304+
with self.assertRaisesRegex(imaplib.IMAP4.error,
305+
r'invalid greeting: \* BYE Server unavailable'):
306+
self.imap_class(*server.server_address)
307+
308+
def test_invalid_greeting_bare_continuation(self):
309+
# A bare continuation greeting is still reported (gh-108280).
310+
class BareHandler(socketserver.StreamRequestHandler):
311+
def handle(self):
312+
self.wfile.write(b'+\r\n')
313+
_, server = self._setup(BareHandler, connect=False)
314+
with self.assertRaisesRegex(imaplib.IMAP4.error,
315+
r'invalid greeting: \+'):
316+
self.imap_class(*server.server_address)
317+
285318
def test_line_termination(self):
286319
class BadNewlineHandler(SimpleIMAPHandler):
287320
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)