Skip to content
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

Issues with sending emails #3035

Closed
At0kir opened this issue Mar 13, 2024 · 13 comments
Closed

Issues with sending emails #3035

At0kir opened this issue Mar 13, 2024 · 13 comments

Comments

@At0kir
Copy link

At0kir commented Mar 13, 2024

I had phpmailer setup for automatic reminders that get sent out every week and everything has been working fine for the last 2 months but today the email's aren't getting sent out anymore. I'm using Azure AD and my token expires in 2025. I also re did the oauth and got all new tokens but that didn't seem to help. The error log when using $mail->SMTPDebug = SMTP::DEBUG_SERVER; doesn't show much.

2024-03-13 13:35:06 SERVER -> CLIENT: 220 YQXPR0101CA0058.outlook.office365.com Microsoft ESMTP MAIL Service ready at Wed, 13 Mar 2024 13:35:04 +0000
2024-03-13 13:35:06 CLIENT -> SERVER: EHLO localhost
2024-03-13 13:35:06 SERVER -> CLIENT: 250-YQXPR0101CA0058.outlook.office365.com Hello [xxx.xxx.xxx.xxx]250-SIZE 157286400250-PIPELINING250-DSN250-ENHANCEDSTATUSCODES250-STARTTLS250-8BITMIME250-BINARYMIME250-CHUNKING250 SMTPUTF8
2024-03-13 13:35:06 CLIENT -> SERVER: STARTTLS
2024-03-13 13:35:06 SERVER -> CLIENT: 220 2.0.0 SMTP server ready
2024-03-13 13:35:06 CLIENT -> SERVER: EHLO localhost
2024-03-13 13:35:06 SERVER -> CLIENT: 250-YQXPR0101CA0058.outlook.office365.com Hello [xxx.xxx.xxx.xxx]250-SIZE 157286400250-PIPELINING250-DSN250-ENHANCEDSTATUSCODES250-AUTH LOGIN XOAUTH2250-8BITMIME250-BINARYMIME250-CHUNKING250 SMTPUTF8
2024-03-13 13:35:06 CLIENT -> SERVER: QUIT
2024-03-13 13:35:07 SERVER -> CLIENT: 221 2.0.0 Service closing transmission channel

@Synchro
Copy link
Member

Synchro commented Mar 13, 2024

This looks like an auth issue. See if you get anything useful if you set debug to SMTP::DEBUG_LOWLEVEL, as that will show auth method details.

Also, unless you just did it for posting here, EHLO localhost is unlikely to go down well.

@decomplexity
Copy link
Contributor

It looks as if either:

  • the token server hasn't issued an access token (in response to your providing a refresh token)
    or
  • the access token has not been presented to the token server by your client

i.e. unless some debug information is missing, it doesn't look as if things have got a far as your presenting an access token to MSFT's SMTP gateway for authentication

So it is worth looking at the AAD sign-in logs to see if there is anything of relevance there. After you have signed in once, the MSFT authorization-code server should think that it has already passed you an authorization code when it calls the redirectURI (the code is suffixed to the URI).
Try:
• sign in to AAD
• select Enterprise Applications
• select your app
• select Sign-in Logs (near the bottom of the vertical list)
• select User-sign-ins (non-interactive)
• select Refresh
• select the Request ID ‘Aggregate’ item for today’s date and for Resource ‘Office 365 Exchange Online’, 'Graph' or other request you wish to check
• select the event for the time of your last failed event (or any other event in which you are interested)
This may have some useful information.

Then also:
• select the ‘…’ on the RHS of the title
• see the Oauth Scope Info field in the Additional Details tab

@Synchro
Copy link
Member

Synchro commented Mar 13, 2024

One simple thing that could be at work – if you don't set AuthType, it tries each of ['CRAM-MD5', 'LOGIN', 'PLAIN', 'XOAUTH2'] in turn. Your server supports LOGIN and XOAUTH2, and because of this order it will try LOGIN first, but using the XOAUTH2 credentials, which will fail. It would help to see your code.

@At0kir
Copy link
Author

At0kir commented Mar 13, 2024

I am currently testing the script on localhost which is why its showing EHLO localhost. It worked before without any issues but regardless it doesn't work on the live web server.

Here is what I get when using DEBUG_LOWLEVEL:

2024-03-13 15:28:57 Connection: opening to smtp.office365.com:587, timeout=300, options=array()
2024-03-13 15:28:57 Connection: opened
2024-03-13 15:28:57 SMTP INBOUND: "220 YQBPR0101CA0221.outlook.office365.com Microsoft ESMTP MAIL Service ready at Wed, 13 Mar 2024 15:28:57 +0000"
2024-03-13 15:28:57 SERVER -> CLIENT: 220 YQBPR0101CA0221.outlook.office365.com Microsoft ESMTP MAIL Service ready at Wed, 13 Mar 2024 15:28:57 +0000
2024-03-13 15:28:57 CLIENT -> SERVER: EHLO localhost
2024-03-13 15:28:57 SMTP INBOUND: "250-YQBPR0101CA0221.outlook.office365.com Hello [xxx.xxx.xxx.xxx]"
2024-03-13 15:28:57 SMTP INBOUND: "250-SIZE 157286400"
2024-03-13 15:28:57 SMTP INBOUND: "250-PIPELINING"
2024-03-13 15:28:57 SMTP INBOUND: "250-DSN"
2024-03-13 15:28:57 SMTP INBOUND: "250-ENHANCEDSTATUSCODES"
2024-03-13 15:28:57 SMTP INBOUND: "250-STARTTLS"
2024-03-13 15:28:57 SMTP INBOUND: "250-8BITMIME"
2024-03-13 15:28:57 SMTP INBOUND: "250-BINARYMIME"
2024-03-13 15:28:57 SMTP INBOUND: "250-CHUNKING"
2024-03-13 15:28:57 SMTP INBOUND: "250 SMTPUTF8"
2024-03-13 15:28:57 SERVER -> CLIENT: 250-YQBPR0101CA0221.outlook.office365.com Hello [xxx.xxx.xxx.xxx]250-SIZE 157286400250-PIPELINING250-DSN250-ENHANCEDSTATUSCODES250-STARTTLS250-8BITMIME250-BINARYMIME250-CHUNKING250 SMTPUTF8
2024-03-13 15:28:57 CLIENT -> SERVER: STARTTLS
2024-03-13 15:28:57 SMTP INBOUND: "220 2.0.0 SMTP server ready"
2024-03-13 15:28:57 SERVER -> CLIENT: 220 2.0.0 SMTP server ready
2024-03-13 15:28:57 CLIENT -> SERVER: EHLO localhost
2024-03-13 15:28:57 SMTP INBOUND: "250-YQBPR0101CA0221.outlook.office365.com Hello [xxx.xxx.xxx.xxx]"
2024-03-13 15:28:57 SMTP INBOUND: "250-SIZE 157286400"
2024-03-13 15:28:57 SMTP INBOUND: "250-PIPELINING"
2024-03-13 15:28:57 SMTP INBOUND: "250-DSN"
2024-03-13 15:28:57 SMTP INBOUND: "250-ENHANCEDSTATUSCODES"
2024-03-13 15:28:57 SMTP INBOUND: "250-AUTH LOGIN XOAUTH2"
2024-03-13 15:28:57 SMTP INBOUND: "250-8BITMIME"
2024-03-13 15:28:57 SMTP INBOUND: "250-BINARYMIME"
2024-03-13 15:28:57 SMTP INBOUND: "250-CHUNKING"
2024-03-13 15:28:57 SMTP INBOUND: "250 SMTPUTF8"
2024-03-13 15:28:57 SERVER -> CLIENT: 250-YQBPR0101CA0221.outlook.office365.com Hello [xxx.xxx.xxx.xxx]250-SIZE 157286400250-PIPELINING250-DSN250-ENHANCEDSTATUSCODES250-AUTH LOGIN XOAUTH2250-8BITMIME250-BINARYMIME250-CHUNKING250 SMTPUTF8
2024-03-13 15:28:57 Auth method requested: XOAUTH2
2024-03-13 15:28:57 Auth methods available on the server: LOGIN,XOAUTH2
2024-03-13 15:28:58 CLIENT -> SERVER: QUIT
2024-03-13 15:28:58 SMTP INBOUND: "221 2.0.0 Service closing transmission channel"
2024-03-13 15:28:58 SERVER -> CLIENT: 221 2.0.0 Service closing transmission channel
2024-03-13 15:28:58 Connection: closed

@At0kir
Copy link
Author

At0kir commented Mar 13, 2024

Here is my code with redacted info:

$mail = new PHPMailer(true);

try {

$mail->isSMTP();
            
//Enable SMTP debugging
//SMTP::DEBUG_CLIENT = client messages
//SMTP::DEBUG_SERVER = client and server messages
$mail->SMTPDebug = SMTP::DEBUG_LOWLEVEL;
$mail->Host = 'smtp.office365.com';
$mail->Port = 587;
$mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS;
$mail->SMTPAuth = true;
$mail->AuthType = 'XOAUTH2';

$email = '[email protected]';
$clientId = 'aae';
$clientSecret = 'ouP';
$tenantId = '23b';

$refreshToken = '0.ATcA';

$provider = new Azure(
    [
        'clientId' => $clientId,
        'clientSecret' => $clientSecret,
        'tenantId' => $tenantId,
    ]
);

$mail->setOAuth(
    new OAuth(
        [
            'provider' => $provider,
            'clientId' => $clientId,
            'clientSecret' => $clientSecret,
            'refreshToken' => $refreshToken,
            'userName' => $email,
        ]
    )
);
$mail->ClearAddresses();
$mail->setFrom($email, 'Do Not Reply');

$mail->addAddress('[email protected]');

$mail->isHTML(true);
$mail->Subject = 'Summary of stuff';
$mail->Body = $combinedContent;

$mail->send();
// echo 'Message has been sent';

} catch (Exception $e) {
// echo "Message could not be sent. Mailer Error: {$mail->ErrorInfo}";
}

@Synchro
Copy link
Member

Synchro commented Mar 13, 2024

Thanks, that output is useful. Looking at the output, we can see you're getting the Auth method requested and Auth methods available... messages, and then nothing (where the next thing we expect to happen is it sending an AUTH command, which we are not seeing), and I think the only way that can happen is if you get to this point, suggesting that null === $OAuth is true, so I suggest you look at that.

@At0kir
Copy link
Author

At0kir commented Mar 13, 2024

My question is how could the null === $OAuth be true now if it wasn't on Friday? The code hasn't been touched in the last month. The only thing I can think of is the refresh token or secret token expiring but I just made new ones and still having the same issue.

So I just checked and the Azure AD is saying that the refresh token is expired due to inactivity. The token was issued on {issueDate} and was inactive for {time}.

@Synchro
Copy link
Member

Synchro commented Mar 13, 2024

Having expiry and inactivity on the refresh token seems a bit unsporting! So is your issue now solved?

@At0kir
Copy link
Author

At0kir commented Mar 13, 2024

Lol yeah the issue is fixed now I just had to generate a new refresh token. One question when do the refresh tokens expire? This one was only valid for about 2 months

@decomplexity
Copy link
Contributor

decomplexity commented Mar 13, 2024

Generous but safety-conscious Mr MSFT gives refresh tokens 90 days maximum life (less for single-page apps).
Like some other things, use it or lose it!
You either need to store them date-stamped or request a new one with each access token.

@Synchro
Copy link
Member

Synchro commented Mar 13, 2024

Glad it's fixed. Refresh expiry depends on the service; I expect it will be documented somewhere, but you'll need to find it.

@Synchro Synchro closed this as completed Mar 13, 2024
@scollovati
Copy link

scollovati commented Apr 24, 2024

@decomplexity @Synchro official doc is here https://learn.microsoft.com/en-us/entra/identity-platform/refresh-tokens.

The default lifetime for the refresh tokens is 24 hours for single page apps and 90 days for all other scenarios. Refresh tokens replace themselves with a fresh token upon every use. The Microsoft identity platform doesn't revoke old refresh tokens when used to fetch new access tokens. Securely delete the old refresh token after acquiring a new one.

So very likely there is the need to store somewhere the new refresh token issued on every use, instead of using just the "first" one (that very likely is put in a .ENV conf).

@decomplexity
Copy link
Contributor

Storage of the new refresh token is already done when using the 'full' version of the wrapper (i.e. when using SendOauth2A instead of PHPMailer's OAuthTokenProvider interface). The new refresh token is automatically written to the SendOAuth2 interchange file.
I don't think it is possible to delete an old refresh token programmatically; there is a 'user-revokesigninpermissions' API in Graph but this revokes the lot!
When you use the OAuthTokenProvider interface or the familiar $mail->setOAuth(new OAuth(, ...), you provide a refresh token that has been generated 'elsewhere' by get_oauth_token.php. It is then up to you to obtain and store any new refresh token.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants