· Feb 3, 2023

Autentication OAuth 2.0 Microsoft Office 365


I use Caché COS and I'm having trouble doing a POP3 on the Microsoft email server using OAuth 2.0 authentication.

I'm using the following program to accomplish this task:

QGPOP ; Recebe e-mail da Microsoft Office 365
  Set server=##class(%Net.POP3).%New()
  Set server.port=995
  Set server.StoreAttachToFile=1
  Set server.AttachDir="D:\HOME\CNTIRET"
  Set servername=""
  Set user="",pass="xxxxxx"
  Set AccessToken="exxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
  set server.SSLConfiguration="Transnovag"
  Set status=server.Connect(servername,user,pass,AccessToken)
  Do $System.Status.DisplayError(status)
  set status=server.GetMailBoxStatus(.NumMensagens,.TamTotalMensagens)
  w !!,"Nr. de mensagens na pasta: ",NumMensagens,!!
  Do $System.Status.DisplayError(status)
  s closeserver=server.%Close()
I'm getting the following error message:

Erro #6015: Servidor POP3 reportou erro: -ERR Authentication failure: unknown user name or bad password..

Has anyone ever been able to make that connection?


Claudio Vieira

Product version: IRIS 2022.1
$ZV: IRIS for Windows (x86-64) 2022.1.1 (Build 374U) Tue Oct 18 2022 17:39:18 EDT
Discussion (4)3
Log in or sign up to continue

If you are using an access token, do not also send a password.

How are you getting the access token? Are you including the necessary scopes for email? You need to use scopes and (or similar) to send and receive email.

Microsoft also requires a tenant id in the request, for example:
where "common" is the tenant id for an email address, but you may need to use the tenant id for

Thank you for returning Mr. Clark,
When I do not send the password is presented another error:

Sending: Set status=server.Connect(servername,user,pass,AccessToken)
Error returned: "Erro #6015: Servidor POP3 reportou erro: -ERR Authentication failure: unknown user name or bad password.."

Sending: Sending: Set status=server.Connect(servername,user,AccessToken)
Error returned: "Erro #6015: Servidor POP3 reportou erro: -ERR Protocol error. Connection is closed. 10."

The Token is being obtained through Postman.
I'm using the following Scopo: "offline_access openid User.Read POP.AccessAsUser.All SMTP.Send IMAP.AccessAsUser.All"

I'm sending the following keys in the Postman:



Claudio Vieira

Set status=server.Connect(servername,user,AccessToken) needs to be
Set status=server.Connect(servername,user,,AccessToken)

To get the token I use:


scope="openid offline_access"

The client_secret is in the post form.
code_challenge/method, nonce, and state may be optional, but desirable for security.
prompt="consent" changes how the authorization is done and probably optional.
access_type="offline" is probably optional since you have the offline_access scope.

I found that adding some additional scopes would prevent the token from working for retrieving email.


I have the same problem.
I want to connect to office365 using OAuth2 and the IMAP protocol.

I was inspired by this post to use IMAP in IRIS :

I always have a system error when launching the command to connect in OAUT2

Do you know how to connect in OAUTH2 with IMAP in IRIS?

Here is the method : 

Method SendCommand(pCommand As %String = "") As %String


    Do ..Log("Dans BastideIMAPHelper :  SendCommand")

    Set currIO = $IO

    Set exception = ""

    Try {

        Set command = ""

        If (pCommand '= "") {

            Set tag = ..GetTag()

            Set command = tag_" "_pCommand


        Do ..Log("Using device: "_..Device)

        Use ..Device

        If ($FIND(command, " AUTHENTICATE ") > 0) {

            // don't log passwords

         Set command = "AUTHENTICATE XOAUTH2 " _ authorizationHeader

            Do ..Log("Sending command 1: "_$P(command, " ", 1, 3)_" <password hidden>")



        Write:(command '= "") command,!

       #; Set status = $zf(-1, command)

        Set ..CurrentCommand = pCommand

        Set ..CurrentTag = tag

        Do ..ReadResponse(.response)


    Catch ex {

        Set exception = ex

        Do ..Log("Error in command execution: "_ex.DisplayString())


    Use currIO

    Throw:$IsObject(exception) exception

    Return response


/// Description

Method ReadResponse(ByRef pResponse As %String) [ Internal ]


    Try {

    Set buffer = ""

    Set pResponse = ""

    Set tokensLine = ""

    While(1) {

        Read buffer:..Timeout

        Set readOK = $TEST

        Set pResponse = pResponse_buffer

        If (..CurrentCommand = "") Quit

        If (readOK) {

            // splits the current response by CRLF

            Set lines = $LISTFROMSTRING(buffer, $Char(13, 10))

            // if the whole response was retrieved, the line with the

            // tag of the command is the (n-1)-th, due the message

            // finishes with CRLF, so the n-th list element is ""

            Set ackLine = $LISTGET(lines, * - 1)

            // splits the lines by white space

            Set tokensLine = $LISTFROMSTRING(ackLine, " ")

            // if the whole message was retrieved, the first token has

            // the tag of the command

            Set tagToken = $LISTGET(tokensLine, 1)

            // check if the first token is the expeted tag, if so, the

            // whole message was retrieved and leave the loop

            If (tagToken = ..CurrentTag) Quit

        } Else {





    Catch ex {

        Set tSC=ex.AsStatus()

        Set exception = ex

        Do ..Log("Error in ReadResponse: "_ex.DisplayString())


    // check if the whole message was retrieved and its status is OK

    Set ackToken = $LISTGET(tokensLine, 2)

    If (ackToken '= "OK") {

      Throw ##class(IMAPException).%New("IMAP error: "_$LISTTOSTRING(tokensLine, " "))



Here is the command log 

command  : TAG1 AUTHENTICATE XOAUTH2 Bearer " AcccessToken value"

Here is error :

ERROR #5002: ObjectScript error: <WRITE>SendCommand+22

Thank you very much for your help