Jump to content
marcin

Indy IMAP and Microsoft EWS

Recommended Posts

Hi

 

Is Indy IMAP component capable to connect to Office 365 account? How "mature" is Indy ssl-oauth branch?

I'm looking for some solution to only read 'unread' emails from this account, mark them as 'read' and optionally copy them to another folder

 

TIA

Marcin

Share this post


Link to post
9 hours ago, marcin said:

Is Indy IMAP component capable to connect to Office 365 account?

Yes.  And you don't actually need OAuth for it, you could use an App-specific password instead if you have 2-step verification enabled.

9 hours ago, marcin said:

How "mature" is Indy ssl-oauth branch?

Not very mature at all, considering I just created the branch a couple of months ago, and am still receiving feedback over whether it even works correctly.

 

Share this post


Link to post

Remy

 

Thanks for the answers, following your suggestion, first I'll try with App-specific password.

 

Marcin

Share this post


Link to post

Hi

 

Since Office 365 account I'm trying to connect to with TIdIMAP4  does not support App-specific password, I have to use TIdSASLXOAuth2 from ssl-oauth branch.

I have managed to obtain access token from login.microsoftonline.com, but I'm getting 'Authentication failed' when trying to log in to IMAP. How can I check (if possible) if there is something wrong with the token (i.e incorrect scope) or TIdSASLXOAuth2 itself requires some tweaking? Or maybe there is something wrong with my code:

 


 sslHandler := TIdSSLIOHandlerSocketOpenSSL.Create;
 sslHandler.SSLOptions.Method := sslvTLSv1_2;
 sslHandler.SSLOptions.SSLVersions := [sslvTLSv1_2];

 IMAP := TIdIMAP4.Create(Self);
 IMAP.IOHandler := sslHandler;
 IMAP.UseTLS := utUseImplicitTLS;
 IMAP.Host := 'outlook.office365.com';
 IMAP.Port := 993;
 IMAP.OnStatus := IdIMAP41Status;

 xoauthSASL := IMAP.SASLMechanisms.Add;
 xoauthSASL.SASL := TIdSASLXOAuth2.Create(nil);
 
 TIdSASLXOAuth2(xoauthSASL.SASL).UserPassProvider := TIdUserPassProvider.Create();
 TIdSASLXOAuth2(xoauthSASL.SASL).UserPassProvider.Username := microsoft_clientaccount;
 TIdSASLXOAuth2(xoauthSASL.SASL).UserPassProvider.Password := AccessToken;

 IMAP.AuthType := iatSASL;

 IMAP.Connect(True);

Can someone help?

TIA

Marcin

 

Share this post


Link to post
7 hours ago, marcin said:

I have managed to obtain access token from login.microsoftonline.com, but I'm getting 'Authentication failed' when trying to log in to IMAP. How can I check (if possible) if there is something wrong with the token (i.e incorrect scope) or TIdSASLXOAuth2 itself requires some tweaking? Or maybe there is something wrong with my code:

Offhand, the code you have shown looks OK (except for the potential memory leaks), but I can't really answer your question, because you didn't show how you are obtaining the token in the first place, or what settings you have used for it.

 

Share this post


Link to post

Remy

I'm obtaining the access_token the way you helped me in another thread:

 

  scope := 'https://graph.microsoft.com/.default';
  msUrl := 'https://login.microsoftonline.com/%s/oauth2/v2.0/token';

  
  sslHandler := TIdSSLIOHandlerSocketOpenSSL.Create;
  sslHandler.SSLOptions.Method := sslvTLSv1_2;
  sslHandler.SSLOptions.SSLVersions := [sslvTLSv1_2];

  httpClient := TIdHTTP.Create;
  httpClient.HTTPOptions := [hoForceEncodeParams, hoNoProtocolErrorException, hoWantProtocolErrorContent];
  httpClient.IOHandler := sslHandler;
  httpClient.Request.ContentType := 'application/x-www-form-urlencoded';

  tsRequestBody := TStringList.Create;
  tsRequestBody.Add('grant_type=client_credentials');
  tsRequestBody.Add('client_id=' + ClientID);
  tsRequestBody.Add('client_secret=' + ClientSecret);
  tsRequestBody.Add('scope=' + scope);

  sResponse := httpClient.Post(Format(msUrl, [TenantID]), tsRequestBody);
  responseCode := httpClient.ResponseCode;

  if responseCode = 200
   then begin
         jsonOject := TJSONObject.ParseJSONValue(sResponse) as TJSONObject;
         jsonValue := jsonOject.Values['access_token'];
         accessToken := jsonValue.ToString;
         Result := True;
        end
   else begin
         Result := False;
         accessToken := sResponse;
        end;

TIA

Marcin

Share this post


Link to post

and does the above procedure work?
I'm struggling with something similar - access to Dropbox and still errors

 

https://en.delphipraxis.net/topic/7838-delphi-xe-error-connect-dropbox-via-indy-tidhttp-htttps/?tab=comments#comment-65621

 

Edited by polasss

Share this post


Link to post
11 minutes ago, marcin said:

@polasss

You mean procedure for obtaing a token? Yest it works, I get "200" with JSON containing access_token

I mean mainly connecting to the resource after using idhttp including the token

Share this post


Link to post
11 hours ago, marcin said:

  scope := 'https://graph.microsoft.com/.default';

 

I'm no expert in OAuth, but are you sure that is the correct scope to use for requesting accessing to IMAP?

 

Also, it looks like you are bypassing the OAuth "/authorize" url, which returns an authorization token that you can submit to the "/token" url.  Why?  Is that even a valid flow?

Share this post


Link to post

Now I'm totally confused.

Getting back to square one and starting from very beginning...

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×