![]() |
Indy und OAuth / Microsoft365
Hallo Zusammen,
ich versuche mich an microsoft365 und SMTP mit OAuth. Habe nach diversen Anleitungen eine App dort angelegt und entsprechende Rechte eingerichtet. Aktuell beziehe ich einen Token über eine Komponenten von ![]() das klappt soweit. Was nicht klappt ist der Indy SMTP Teil. Hier die Funktion mit der per OAuth eine Mail gesendet werden soll.
Delphi-Quellcode:
Der Token sieht wie folgt aus (gekürzt)
procedure TForm1.SendSMTP(ptToken:String);
Var lcSMTP:TIdSMTP; lcMail:TIdMessage; lcRec:TIdEMailAddressItem; ltAuth:String; lcAuthSASL:TIdSASLListEntry; lcIdSSLIOHandlerSocketSMTP:TidSSLIOHandlerSocketOpenSSL; lcUserPass:TIdUserPassProvider; lcDebug:TIdLogDebug; begin lcSMTP:=TIdSMTP.Create; Try lcSMTP.Host:='smtp.office365.com'; lcSMTP.Port:=587; lcMail:=TIdMessage.Create(lcSMTP); Try lcMail.Encoding:=meMime; lcRec:=lcMail.Recipients.Add; lcRec.Address:='XXX@YYY.de'; lcRec.Name:='XXX@YYY.de'; lcMail.Subject:='Test'; lcMail.Body.Text:='Testnachricht via OAuth'; lcIdSSLIOHandlerSocketSMTP:=TidSSLIOHandlerSocketOpenSSL.Create(lcSMTP); lcIdSSLIOHandlerSocketSMTP.SSLOptions.SSLVersions:=[sslvTLSv1_2]; lcUserPass:=TIdUserPassProvider.Create(lcSMTP); lcUserPass.Username:='myname@test.onmicrosoft.com'; lcUserPass.Password:=ptToken; lcAuthSASL:=lcSMTP.SASLMechanisms.Add; lcAuthSASL.SASL:=TIdSASLXOAuth2.Create(lcSMTP); TIdSASLXOAuth2(lcAuthSASL.SASL).UserPassProvider:=lcUserPass; lcDebug:=TIdLogDebug.Create(lcSMTP); lcDebug.OnReceive:=DoAddLogReceive; lcDebug.OnSend:=DoAddLogSend; lcSMTP.Intercept:=lcDebug; lcSMTP.AuthType:=satSASL; lcSMTP.Connect; -------------------------------------- - hier wird eine Exception ausgelöst - -------------------------------------- lcSMTP.Authenticate; lcSMTP.Send(lcMail); Finally lcMail.Free; End; lcSMTP.Disconnect; Finally lcSMTP.Free; End; end;
Code:
Über IdLogDebug kommen folgende Ausgaben:
{"token_type":"Bearer","expires_in":3599,"ext_expires_in":3599,"access_token":"eyJ0eXAiOiJKV1Q...iLCJub}
Zitat:
Aber was kann der Grund dafür sein ? Ist der Token nicht korrekt ? Nutze ich Indy an der Stelle falsch ? Vielen Dank für eure Hilfe. |
AW: Indy und OAuth / Microsoft365
Funktioniert es denn z.B. mit Telnet?
Mit der Kombination Telnet + OpenSSL habe ich es bishe rnoch nicht zu tun gehabt, aber es ist anscheinend möglich: ![]() ![]() Alternativ geht es eventuell mit einem einfachen Client in einer anderen gängigen Programmiersprache, z.B. Python: ![]() Zitat:
|
AW: Indy und OAuth / Microsoft365
Habe nochmal etwas gefunden und bin jetzt einen Schritt weiter.
Delphi-Quellcode:
Damit bekomme ich folgende Log Einträge:
procedure SendSMTP(ptToken:String);
Var lcSMTP:TIdSMTP; lcMail:TIdMessage; lcRec:TIdEMailAddressItem; lcAuthSASL:TIdSASLListEntry; lcProvider:TProviderInfo; lcIdSSLIOHandlerSocketSMTP:TidSSLIOHandlerSocketOpenSSL; lcUserPass:TIdUserPassProvider; lcDebug:TIdLogDebug; begin ctToken:=ptToken; lcSMTP:=TIdSMTP.Create; Try lcSMTP.Host:='smtp.office365.com'; lcSMTP.Port:=587; lcMail:=TIdMessage.Create(lcSMTP); Try lcMail.Encoding:=meMime; lcRec:=lcMail.Recipients.Add; lcRec.Address:='xxx@yyy.de'; lcRec.Name:='xxx@yyy.de'; lcMail.Subject:='Test'; lcMail.Body.Text:='Testnachricht via OAuth'; lcIdSSLIOHandlerSocketSMTP:=TidSSLIOHandlerSocketOpenSSL.Create(lcSMTP); lcIdSSLIOHandlerSocketSMTP.SSLOptions.SSLVersions:=[sslvTLSv1_2]; lcUserPass:=TIdUserPassProvider.Create(lcSMTP); lcUserPass.Username:='MyMail@test.onmicrosoft.com'; lcUserPass.Password:=ptToken; lcAuthSASL:=lcSMTP.SASLMechanisms.Add; lcAuthSASL.SASL:=TIdSASLXOAuth2.Create(lcSMTP); TIdSASLXOAuth2(lcAuthSASL.SASL).UserPassProvider:=lcUserPass; lcDebug:=TIdLogDebug.Create(lcSMTP); lcDebug.OnReceive:=DoAddLogReceive; lcDebug.OnSend:=DoAddLogSend; lcSMTP.Intercept:=lcDebug; lcSMTP.IOHandler:=lcIdSSLIOHandlerSocketSMTP; lcSMTP.UseTLS:=utUseExplicitTLS; lcSMTP.AuthType:=satSASL; lcSMTP.Connect; lcSMTP.Authenticate; lcSMTP.Send(lcMail); Finally lcMail.Free; End; lcSMTP.Disconnect; Finally lcSMTP.Free; End; end; Zitat:
eingerichtet, der SMTP Zugriff auf das Postfach ist erlaubt. Hat noch jemand eine Idee ? |
AW: Indy und OAuth / Microsoft365
Ich kann morgen mal schauen wie ich es mache.
Habe den Laptop gerade nicht hier. Aber dem Benutzer wurde die Rechte gegeben per SMTP zu Senden? Das ist beim Account bei der Arbeit default aus gewesen. Und beim Privaten Live/Hotmail war das schon erlaubt |
AW: Indy und OAuth / Microsoft365
Zitat:
Ist das bei dir "ptToken"? Bin mir nicht sicher, aber probiere Mal:
Code:
Bearer eyJ0eXAiOiJKV1Q...iLCJub
|
AW: Indy und OAuth / Microsoft365
Zitat:
Ich würde es gerne testen, habe aber meine 30 Tage für kostenlose Tests bereits aufgebraucht. Benötigt der Versand einen (virtuellen) MS Exchange Server? |
AW: Indy und OAuth / Microsoft365
Was Olli schreibt: du sendest nicht das Token, sondern du sendest die gesamte Antwort, also das gesamte JSON, des Authentifizierungsdienstes. Das Access-Token, das du senden musst, ist nur das, was in der Eigenschaft "access_token" steht.
|
AW: Indy und OAuth / Microsoft365
ist die TIdSASLXOAuth2 in Indy10\Protocols mitlerweile schon enthalten?
diese geht
Delphi-Quellcode:
unit IdSASLXOAUTH;
interface uses Classes, IdSASL ; type TIdSASLXOAuth = class(TIdSASL) private FToken: string; FUser: string; FTwoLinePopFormat: Boolean; public property Token: string read FToken write FToken; property User: string read FUser write FUser; property TwoLinePopFormat: Boolean read FTwoLinePopFormat write FTwoLinePopFormat; class function ServiceName: TIdSASLServiceName; override; constructor Create(AOwner: TComponent); destructor Destroy; override; function TryStartAuthenticate(const AHost, AProtocolName : String; var VInitialResponse: String): Boolean; override; function ContinueAuthenticate(const ALastResponse, AHost, AProtocolName : string): string; override; function StartAuthenticate(const AChallenge, AHost, AProtocolName: string): string; override; { For cleaning up after Authentication } procedure FinishAuthenticate; override; end; implementation { TIdSASLXOAuth } class function TIdSASLXOAuth.ServiceName: TIdSASLServiceName; begin Result := 'XOAUTH2'; end; constructor TIdSASLXOAuth.Create(AOwner: TComponent); begin inherited; end; destructor TIdSASLXOAuth.Destroy; begin inherited; end; function TIdSASLXOAuth.TryStartAuthenticate(const AHost, AProtocolName: String; var VInitialResponse: String): Boolean; begin if (AProtocolName = 'pop') and FTwoLinePopFormat then begin // Don't send anything yet end else begin VInitialResponse := 'user=' + FUser + Chr($01) + 'auth=Bearer ' + FToken + Chr($01) + Chr($01); end; Result := True; end; function TIdSASLXOAuth.StartAuthenticate(const AChallenge, AHost, AProtocolName: string): string; begin Result := 'user=' + FUser + Chr($01) + 'auth=Bearer ' + FToken + Chr($01) + Chr($01); end; function TIdSASLXOAuth.ContinueAuthenticate(const ALastResponse, AHost, AProtocolName: string): string; begin // Nothing to do end; procedure TIdSASLXOAuth.FinishAuthenticate; begin // Nothing to do end; end.
Delphi-Quellcode:
IdSASLXOAUTH := TIdSASLXOAuth.Create(SMTP);
IdSASLXOAUTH.Token := FToken; // ca. 2300 Zeichen lang bei Microsoft IdSASLXOAUTH.User := FBenutzername; IdSASLXOAUTH.TwoLinePopFormat := true; SMTP.SASLMechanisms.Add.SASL := IdSASLXOAUTH; |
AW: Indy und OAuth / Microsoft365
So, ich habe nochmal nachgesehen.
Es wird nur der tatsächliche Token verwendet, nicht das komplette JSON, das war nur eine Logausgabe von dem Teil, der den Token abfragt. Habe es auch mit der hier erwähnten Variante von TIdSASLXOAuth versucht. Eine TIdSASLXOAuth2 ist im Fork von Remy Lebeau enthalten, diesen Fork habe ich verwendet. Als Scope verwendet die Bibliothek (sgcWebSockets) 'https://graph.microsoft.com/.default' (Token Abfrage für eine Service App). Bekomme immer noch exakt den gleichen Fehler. Kann ich in Microsoft365 noch etwas entscheidendes übersehen haben ? Kann man in Microsft365 irgendwo fehlgeschlagene Anmeldeversuche anzeigen lassen ? Habe jetzt unter ![]() Mal schauen ob da dann etwas angezeigt wird. Hat jemand einen Source zur Abfrage des Tokens mit "Bordmitteln" oder eine Empfehlung für eine andere Bibliothek dazu mit der es schon mal funktioniert hat ? Eventuell stimmt ja was bei der Tokenabfrage nicht. Habe es mit ![]() schon nicht. Scheint als ob da die tenant-id nicht berücksichtigt wird. Vielen Dank für die Antworten bisher. |
AW: Indy und OAuth / Microsoft365
und mit Scopes:
Delphi-Quellcode:
https://outlook.office.com/SMTP.Send offline_access openid email profile kann sein das das für dich zu viele sind, die verwende ich |
Alle Zeitangaben in WEZ +1. Es ist jetzt 21:55 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz