Thanks to visit codestin.com
Credit goes to github.com

Skip to content

bpo-45706: Add imaplib.IMAP4.login_plain #29398

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 16 additions & 2 deletions Doc/library/imaplib.rst
Original file line number Diff line number Diff line change
Expand Up @@ -330,8 +330,22 @@ An :class:`IMAP4` instance has the following methods:
.. method:: IMAP4.login_cram_md5(user, password)

Force use of ``CRAM-MD5`` authentication when identifying the client to protect
the password. Will only work if the server ``CAPABILITY`` response includes the
phrase ``AUTH=CRAM-MD5``.
the password. It will only work if the server ``CAPABILITY`` response includes
the phrase ``AUTH=CRAM-MD5``.


.. method:: IMAP4.login_plain(login, password)

Authenticate using PLAIN SASL mechanism.

This is a plain-text authentication mechanism that can be used
instead of :meth:`IMAP4.login()` when UTF-8 support is required.
See :RFC:`6855`, page 5.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure that referring to RFC 6855 is that relevant. All it does is recommend against UTF-8 support with LOGIN, and say that AUTHENTICATE supports UTF-8.


It will only work if the server ``CAPABILITY`` response includes
the phrase ``AUTH=PLAIN``.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The module partially supports RFC 3501, which says that AUTH=PLAIN is mandatory. I understand that means advertising it in CAPABILITY is optional, so it might work regardless.


.. versionadded:: 3.11


.. method:: IMAP4.logout()
Expand Down
12 changes: 12 additions & 0 deletions Lib/imaplib.py
Original file line number Diff line number Diff line change
Expand Up @@ -614,6 +614,18 @@ def login(self, user, password):
return typ, dat


def login_plain(self, user, password):
"""Authenticate using PLAIN SASL mechanism.

This is a plain-text authentication mechanism that can be used
instead of login() when UTF-8 support is required.
"""
return self.authenticate(
"PLAIN",
lambda _: "{0}\x00{0}\x00{1}".format(user, password).encode()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This sets the authorization identity (authzid) to the user name. Wouldn’t it be better to allow omitting authzid by default, let the server derive it? https://datatracker.ietf.org/doc/html/rfc4616#section-2

f'\x00{user}\x00{password}'.encode('utf-8')

)


def login_cram_md5(self, user, password):
""" Force use of CRAM-MD5 authentication.

Expand Down
30 changes: 30 additions & 0 deletions Lib/test/test_imaplib.py
Original file line number Diff line number Diff line change
Expand Up @@ -423,6 +423,36 @@ def cmd_AUTHENTICATE(self, tag, args):
ret, _ = client.login_cram_md5("tim", "tanstaaftanstaaf")
self.assertEqual(ret, "OK")

def test_login_plain_ascii(self):
class AuthHandler(SimpleIMAPHandler):
capabilities = 'LOGINDISABLED AUTH=PLAIN'
def cmd_AUTHENTICATE(self, tag, args):
self._send_textline('+')
r = yield
if r == b'cHJlbQBwcmVtAHBhc3M=\r\n':
self._send_tagged(tag, 'OK', 'Logged in.')
else:
self._send_tagged(tag, 'NO', 'No access')
client, _ = self._setup(AuthHandler)
self.assertTrue('AUTH=PLAIN' in client.capabilities)
ret, _ = client.login_plain("prem", "pass")
self.assertEqual(ret, "OK")

def test_login_plain_utf8(self):
class AuthHandler(SimpleIMAPHandler):
capabilities = 'LOGINDISABLED AUTH=PLAIN'
def cmd_AUTHENTICATE(self, tag, args):
self._send_textline('+')
r = yield
if r == b'cHLEmW0AcHLEmW0AxbzDs8WCxIc=\r\n':
self._send_tagged(tag, 'OK', 'Logged in.')
else:
self._send_tagged(tag, 'NO', 'No access')
client, _ = self._setup(AuthHandler)
self.assertTrue('AUTH=PLAIN' in client.capabilities)
ret, _ = client.login_plain("pręm", "żółć")
self.assertEqual(ret, "OK")

def test_aborted_authentication(self):
class MyServer(SimpleIMAPHandler):
def cmd_AUTHENTICATE(self, tag, args):
Expand Down
1 change: 1 addition & 0 deletions Misc/ACKS
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,7 @@ Stan Bubrouski
Brandt Bucher
Curtis Bucher
Colm Buckley
Przemysław Buczkowski
Erik de Bueger
Jan-Hein Bührman
Lars Buitinck
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add :meth:`imaplib.IMAP4.login_plain`.