-
-
Notifications
You must be signed in to change notification settings - Fork 9.7k
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
Added Azure XOAUTH2 help and examples #2793
Conversation
Fixes #2788 |
Bravo, thank you very much. I'm sure that many will appreciate your considerable efforts here. I've pinged a few people who were running into Azure problems to see if they will give it a test before I merge it. |
I forgot to add the example file - it has been committed now as well :) |
I didn't receive any feedback, however, you've done a great job here so I'm merging it anyway – if anyone has issues to report, I'm sure they will turn up eventually! |
Well, Packagist says 25 installs overall, and I may have the first 5-10 during development.. so at least 15 people have started using it, and if neither you nor I have heard anything yet, let's hope it works well 😀 |
Hello, I have been behind this topic of sending via PHPMailer, SMTP and Microsoft OAuth for a while without success. I recently found your guide on how to correctly configure Azure Active Directory for sending emails and after carefully following your guide and testing the code I ran into several errors and it never works. If I follow all the steps and keep this scope 'https://outlook.office.com/SMTP.Send' it doesn't give me any type of error, just this:
So I continued to investigate and found that I could use this scope: 'https://graph.microsoft.com/SMTP.Send' but it returns the following error:
What is this error due to? Is it a misconfiguration of Azure? Can outlook and office365 accounts send SMTP through Azure? How are those scopes different? I have also seen some scopes similar to this 'wl.smtp_send'. What does wl mean? Are they outdated? I know there are a lot of questions but we have been looking for a solution for several months and we have only found your guide. Thanks greetings! PS: The PHP code is similar to the one you use in your guide |
I suspect you may only have |
What permissions have you set in AAD against Graph resource? You need SMTP.Send. |
@adrianalumne Both @Synchro and @decomplexity have already given some great pointers. Give it a go - if it still fails, I'll be happy to see if I can help you further. |
Hello again! Thanks for your help @greew , regarding @Synchro's comment, we have changed I don't really see any error messages and everything seems to be working fine. It is true that by putting the scope mentioned by @decomplexity ( These are the permissions set in AAD: Actually in the PHP code we only request these:
Any idea what to try? For more information, we are using:
On the same server we have managed to get SMTP sending using Google's OAuth to work, so it is understood that the server is correctly configured for sending emails. |
Have you managed to get a refresh_token successfully from Microsoft with before sending the mail? |
Hi @greew |
Trivial point to check, but are you sure that this is a refresh token and not an authorization code? They both start in a similar way. |
I guess that is correct, initially I retrieved the AccessToken and later the RefreshToken. It is right? |
Looks OK. Have a look at the Signin log in AAD : |
Here are the requested data
|
Hmm.... those are both correct. To be sure it is the one really being used, you could add the following highlighted three lines temporarily to PHPMailer module OAuth.php: and then execute a PHPMailer send. |
We have modified the file but without success, it seems that it does not reach that point. We have made a var_dump of $mail and it returns us the correct data and in the immediately following line is the $mail->send() but it seems that it is not executed. Anyway, I wanted to ask you, on what occasion do you use the accessToken? we use the code that we receive through $_GET['code'], then with $token = $provider->getAccessToken() we obtain an object that, among other data, contains a refreshToken that is obtained with $token->getRefreshToken() and accessToken which is obtained with $token->getToken() but we do not use the latter and in your examples it is not mentioned either. Perhaps we are mixing name and variables, everything has a similar name |
You are correct. The refresh token is obtained in the way you suggest and plugged into PHPMailer via: |
Hi again, In the src/Provider/AbstractProvider.php file, within the getParsedResponse() function we have retrieved the data from the $parsed variable (line 635) and it returns the following:
What is this error due to? Is it a DAA thing? How could we solve it? We are still stuck and unable to move forward, thanks for your help |
That's weird... the very next thing after the |
Obvious point but has the user principal (usually the email address of the user who registered the app to AAD) granted Admin consent to the app in the permissions box (AAD => [select the app] => API permissions =>Configured permissions, then under Microsoft Graph you should have offline_access and SMTP.Send ] |
@decomplexity Great point! In the walkthrough I made in the wiki article, I used the same user for both user principal and for oauth2 authentication. @adrianalumne Let us know, if it helps using the "Grant Admin Consent" and I will update the wiki article with the updated data :) |
Hello! We have tried it, we have clicked on the button and the 'Status' column has been updated but nothing has changed, it is still showing the same error. In the following path:
The first two lines catch my attention, it seems that an error has occurred when making the request. Any ideas? After this debug is the one that happened to you yesterday, it seems that the one from yesterday is a consequence of this. PS: I have consulted and it seems that the account we are using is the same one that created the Azure Active Directory, so I understand that we are administrators |
After granting admin consent, have you regenerated the refresh token (whose settings in turn generate the access token)? |
Hello again, we have been reading all these messages and we have continued working to find a solution, but we are still the same, stuck in the same problem as @JosephAlonzo. We have been trying the solutions that you proposed to him, but nothing, maybe he and we have the same problem? I still think it may be a misconfiguration of the Azure account, some kind of subscription to send emails through SMTP or a failure to create the microsoft account. I am referring to the account itself, not the Azure portal, because it is rare to have administrator permissions missing, but that account is the administrator of the Azure portal. Can you think of any way to solve it? |
Worth checking the following: |
Reviewed! It is the same email, it is correct so that is not the fault. Now that it is mentioned, do we have to create groups or roles? we have not managed absolutely none of that, apart from that, is any extra configuration needed outside of AAD? I mean in home page. Following your guide doesn't mention any extra steps outside of AAD, but just in case we're missing something... |
There is no need to create groups or roles for authorization_code grant flows under Delegated Permissions. |
I tried with another azure account and i don't have anymore the error of permission, |
The 3rd link was broken on the wiki page, I went and fixed it myself thinking Github would stop me but it didn't. Maybe there should be some permissions? or is this an acceptable and trustful standard I just haven't seen before |
The wiki has flipped in and out of being publicly writeable over the years, but for the most part they have been ok being open. The wiki is fully versioned, so changes can always be reversed. Leaving it open means that not everything is left to maintainers (i.e. me!) |
Got a question. I've got this working. However something isnt clear in my mind. If I generate a secret token it's only the token for the account which i'm logged in with to generate the token. So for info@ it's a different token then support@. I know it's the case because I already tested it and with both I can mail with their own tokens. But why not one token for all mail accounts that are granted access (owners) in de APP in Azure. Something I missed? Or is it just how it works? Hope that microsoft is thinking of replacing that stupid credentials screen for code solution... |
@adrianalumne could you please respond if you have managed to get it working? I am setting everything exactly as specified on the wiki page, yet no success with sending emails. 535 5.7.3 Authentication unsuccessful |
A scope of "SMTP.Send" will force your resource API to be Graph. And Graph does not support SMTP.Send itself.
If this sounds bizarre, it is! See the explanation in "Microsoft OAuth2 SMTP issues" in the PHPMailer Wiki |
Thank you for such a quick response. I have: |
And what operands are you using in your global PHPMailer code when instantiating OAuth in (e.g.)
|
|
Try:
|
Here is my full script for email sending, removed some specific internal parts that are not needed here.
|
Other things to check:
Then also:
a. Get the initial access token from
b. plug it (temporarily!) into Oauth.php:
It is worth noting that whereas the authentication code (in the initial authorization flow run) is allowed to contain clashing scopes, multiple resources and so on, the token endpoint imposes more stringent criteria when generating an access token. Exactly why is known only to MSFT! |
|
|
Why not echo the access token that is produced from the initial run (the run that produced the refresh token) and also echo the token normally used within Oauth.php (i.e. the token generated from the refresh token). Then run each through jwt.io or jwt.ms (you may need to debase64 them) and post the contents of the ‘aud’ and ‘scope’ fields – or since the tokens expire after 90 minutes or less, just post the tokens. |
I have compared two access tokens and to my surprise - with both of them authentication now passes through, emails are sent. Either the first correct token pasted into OAuth.php made the path open for following tokens or some previous changes made in the administration panels finally propagated. I'm baffled, can't explain it. The only differences in both tokens are times (iat, nbf, exp), and fields aio and uti. Scope is the same, everything else is the same. Aud is "https://outlook.office.com", scope is Mail.Send Mail.Send.All Mail.Send.Shared SMTP.Send User.Read. |
Since you have an ‘aud’ of https://outlook.office.com/ in both tokens, that is half the battle of getting SMTP authentication to work! As I mentioned earlier in this thread, your client scope normally only needs to be:
Re the setup for allowing other users (within the tenant presumably) to ‘send as’ the base mailbox, two points:
Without experimenting, I really can’t say whether adding delegates to a shared mailbox in Send As mode and then hoping to allow each to use PHPMailer to send via SMTP will work even in principle. Logically it shouldn’t. |
After leaving it for the night, this morning "Send as" delegation started to work without a touch, so information for everyone - be patient, changes on MS side can take much more time than described in the panel (5 minutes). Thank you for all the help, I hope this will be of use for everyone else fighting with this. |
Hello, Fatal error: Uncaught League\OAuth2\Client\Provider\Exception\IdentityProviderException: Unauthorized in... |
Yes - you are right to be suspicious of the scopes shown in the Signin log!
The scopes presented to the authorization server do not include SMTP.Send, and subsequent authentication will fail.
From a very brief look at your settings, try:
- in new Provider\Azure([
remove the 'tenantId' and 'scopes' operands and their settings
in the subsequent few lines:
- uncomment the //$provider->scope ... line
- replace the //$provider->urlAPI = https://outlook.office.com;
by
$provider->urlAPI = https://graph.microsoft.com/;
- add:
$provider->API_VERSION = '1.0';
|
Hey, thanks. I got it to work, I found out that I had an old script loaded where I was setting the scope to the old params. |
Is there a route to achieving something similar but without the deprecated SMTP Auth? |
can you help me out maybe? I did everything as described in the tutorial, except that I don't know how to get "the user that gave consent" userName parameter (
If I use SSL instead of TLS the smtp connect times out. |
Probably something wrong with your refresh token.
Then also:
Let us have the Resource shown in the basic tab and the Scope shown in the Additional Details tab |
Thank you, pointed me in the right direction! the error was on my side, the token was truncated in the DB because of the size of the field... next I only had to enable SMTP auth as described here, which might be useful |
I hope it's quite self explanatory :)