ikvk / imap_tools

Work with email by IMAP

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

turning off Basic Authentication in Exchange Online - [b'LOGIN failed.']

buttergolemm opened this issue · comments

As of today, logging into the mailbox is no longer possible. Is it due to this: https://techcommunity.microsoft.com/t5/exchange-team-blog/basic-authentication-and-exchange-online-september-2021-update/ba-p/2772210 ??

Error -> imap_tools.errors.MailboxLoginError: Response status "OK" expected, but "NO" received. Data: [b'LOGIN failed.']

Credentials have never changed.

I have been able to turn off Basic Authentication for IMAP until the end of the year. This gives me a little more time. From 01.01.2023 I can no longer get around this problem.

Hi,

Same here, but we could not turn on Basic Auth. However, XOAUTH is not working either.

Are there any plans to support Microsoft Graph auth and use it to retrieve messages?

*See tags

Hello, I'm trying hard to make the xoauth method work, since Basic Auth is going to be removed completely starting from 2023.

Has someone been able to make it work? How do we should retrieve the access token instead of a password for an automatic application?
I tried the MSAL library provided by Microsoft. I'm able to retrieve an access token but then it gives:

imaplib.IMAP4.error: AUTHENTICATE failed.

when I try to login.

*Note - no external libs in imap_tools

Yes @ikvk I know that there are not external libs in imap_tools. But in some way I need to get an access token in order to use the Mailbox.xoauth2 method. My question was specifically targetting how to get that token.

By the way, I think the relevant documentation is written here: https://learn.microsoft.com/en-us/exchange/client-developer/legacy-protocols/how-to-authenticate-an-imap-pop-smtp-application-by-using-oauth

I'm still not able to authenticate, I'm sure I'm missing something Outlook/Exchange side.

I managed to make it work properly. The Mailbox.xoauth2 works, the tricky part was to setup Outlook. Read carefully that documentation and you should be ok.

* It seemed to me that this was a new authentication method.

@Eugenio-Liso could you share the code you used to resolve this? I'm stuck on the same issue, trying to set up oauth to access an Exchange mailbox.

Whilst not exactly an issue with imap_tools itself, I'd suggest a code example for Mailbox.xoauth2 login with Exchange would be a pretty helpful thing to document in the repo, since many users likely use this project to access Exchange mailboxes. Since Microsoft has now dropped support for basic authentication, using oauth is likely a more common use case.

@benjamingorman Hi there, sorry for the late answer.

I have been able to make it work with the following code:

from imap_tools import MailBox
import msal

class CustomBaseException(Exception):
    def __init__(self, **kwargs: Any):
        super().__init__()
        self.kwargs = kwargs

    def __repr__(self) -> str:
        return f"{self.__class__.__name__}: {repr(self.kwargs)}"

    def __str__(self) -> str:
        return repr(self)

class AccessTokenNotRetrieved(CustomBaseException):
    pass

def init_mailbox_with_xoauth2(client_id: str, client_secret: str, authority: str,
                              mailbox_server: str, mailbox_username: str, mailbox_source_folder: str) -> MailBox:
    """
    Initializes a Mailbox which internally uses XOAUTH2 authentication.

    :param client_id: the Client ID associated to the app created in AAD (Azure Active Directory)
    :param client_secret: the Client Secret associated to the app created in AAD (Azure Active Directory)
    :param authority: A URL that identifies a token authority. It should be of the format
            ``https://login.microsoftonline.com/your_tenant``
    :param mailbox_server: The server to which we should connect when fetching emails
    :param mailbox_username: The username to use when connecting to the mailbox. Usually an email address
    :param mailbox_source_folder: The folder in which we should read emails
    :return: A ready-to-use Mailbox instance
    """
    app = msal.ConfidentialClientApplication(
        client_id=client_id,
        authority=authority,
        client_credential=client_secret
        # token_cache=...  # Default cache is in memory only.
        # You can learn how to use SerializableTokenCache from
        # https://msal-python.readthedocs.io/en/latest/#msal.SerializableTokenCache
    )

    scope = ['https://outlook.office365.com/.default']
    access_token_dict_key = "access_token"
    token = app.acquire_token_silent(scope, account=None)

    if not token:
        token = app.acquire_token_for_client(scopes=scope)

    if access_token_dict_key in token:
        access_token = token[access_token_dict_key]

        mailbox = MailBox(mailbox_server).xoauth2(
            mailbox_username, access_token, initial_folder=mailbox_source_folder
        )

        return mailbox

    else:
        raise AccessTokenNotRetrieved(
            message="Unable to retrieve access token from AAD.",
            error=token.get("error"),
            error_description=token.get("error_description"),
            correlation_id=token.get("correlation_id")  # You may need this when reporting a bug
        )

If everything goes well, you have a Mailbox instance which you can use as usual.
Hope this helps.

@Eugenio-Liso Thanks so much for your sharing. follow your guide, I think I‘m close to success.

I'm currently getting error imaplib.error: AUTHENTICATE failed. , this may be because my org did not approve me to use Application permissions, so I have tried to use Delegated permissions but it does have POP and IMAP permissions. (related docs).

Traceback (most recent call last):
  File "C:\workspace\vmmj\test_xoauth2.py", line 83, in <module>
    ret = init_mailbox_with_xoauth2(
  File "C:\workspace\vmmj\test_xoauth2.py", line 59, in init_mailbox_with_xoauth2
    mailbox = MailBox(mailbox_server).xoauth2(
  File "C:\workspace\vmmj\venv\lib\site-packages\imap_tools\mailbox.py", line 87, in xoauth2
    result = self.client.authenticate('XOAUTH2', lambda x: auth_string)  # noqa
  File "C:\Users\xshen\AppData\Local\Programs\Python\Python39\lib\imaplib.py", line 444, in authenticate
    raise self.error(dat[-1].decode('utf-8', 'replace'))
imaplib.error: AUTHENTICATE failed.
(venv) 

My org provides me another way to get data, so I don't need to get data through outlook anymore, I just share why I might fail (maybe help).

@shenxianpeng That error, if I remember correctly, indicates that you do not have sufficient permissions. I think you need to give the Tenant Consent to your application (and yes, I have only tried Application Permissions).