PHPMailer SMTP Gmail authentification error - oauth-2.0

I'm sending emails using PHPMailer 5.2.10 with the next code:
function SendGmail($to,$subj,$body)
{
$mail = new PHPMailer(); // create a new object
$mail->IsSMTP(); // enable SMTP
$mail->SMTPDebug = 1; // debugging: 1 = errors and messages, 2 = messages only
$mail->SMTPAuth = true; // authentication enabled
$mail->SMTPSecure = 'ssl'; // "ssl" secure transfer enabled REQUIRED for GMail
$mail->Host = "smtp.gmail.com";
$mail->Port = 465; // 465 or 587
$mail->IsHTML(true);
$mail->Username = "admin#mydomain.ru";
$mail->Password = "********";
$mail->SetFrom("admin#mydomain.ru");
$mail->Subject = $subj;
$mail->Body = $body;
$mail->AddAddress($to);
return $mail->Send();
}
Note: we use Google Apps, so the mail domain is not google.com, but some other, let's say, mydomain.ru.
Everything was fine until Google had recently implemented another "security enhancement" (AFAIK forcing OAuth2 authorisation). Now PHPMailer->Send() returns the following text:
2015-05-12 06:49:15 CLIENT -> SERVER: EHLO 127.0.0.1
2015-05-12 06:49:15 CLIENT -> SERVER: AUTH LOGIN
2015-05-12 06:49:15 CLIENT -> SERVER: [some base64 string]
2015-05-12 06:49:15 CLIENT -> SERVER: [some base64 string]
2015-05-12 06:49:16 SMTP ERROR: Password command failed: 535-5.7.8 Username and Password not accepted. Learn more at 535 5.7.8 http://support.google.com/mail/bin/answer.py?answer=14257 u10sm3566045lbb.30 - gsmtp
2015-05-12 06:49:16 SMTP Error: Could not authenticate.
2015-05-12 06:49:16 CLIENT -> SERVER: QUIT
2015-05-12 06:49:16 SMTP connect() failed. https://github.com/PHPMailer/PHPMailer/wiki/Troubleshooting bool(false) Done!
Ok, I go to http://support.google.com/mail/bin/answer.py?answer=14257 and doing the following:
Logging to this account via web interface - everything's Ok,
Opening this link in browser: http://www.google.com/accounts/DisplayUnlockCaptcha - google says everything is Ok,
Opening this link: https://support.google.com/accounts/answer/6010255 and then this link: https://www.google.com/settings/security/lesssecureapps where I see the following:
"Access for less secure apps: * Turn off / * Turn on" - for normal gmail account,
("This setting is inaccessible for google apps accounts") - for google apps account (not the exact text but my translation from russian as google shows it).
Yes, I have tried both SSL and TLS, 485 or 587 ports and everything else I've found on stackoverflow.com and here: https://github.com/PHPMailer/PHPMailer/wiki/Troubleshooting . Nothing helped.
PHPMailer troubleshooting page suggests to use "an OAuth2 client class": http://www.phpclasses.org/package/7700-PHP-Authorize-and-access-APIs-using-OAuth.html - but I have no idea of how to integrate it into PHPMailer and why it's not integrated yet by PHPMailer developers (this class is under BSD license), while it's necessary now for one of the most popular mail servers. I found no documentation for this OAuth2 about integrating it into PHPMailer, and I'm sure I can't do it myself - my PHP knowledge is poor.
The question is:
How can I avoid this goddamn OAuth2 and send emails as I did it before this "security enhancement" (for google apps account)? --OR:
How to easily integrate OAuth2 class mentioned above into PHPMailer? --OR:
Are there any other easy-to-use PHP solutions to send emails using gmail?
Lots of thanks in advance.

Thank you for reading the docs, it's much appreciated! The problem is that google has imposed this complicated authentication mechanism without much regard for its users, as you have experienced. It doesn't improve security because ultimately you still have to submit a username and password over SSL to get your token. OAuth is an authorisation (what you can do) protocol, but google are using it indirectly as an authentication (who you are) protocol.
The reason that nobody has implemented it is that while it's very clever, OAuth is generally unpleasant and confusing to work with, which is why we'd be very happy if someone got around to implementing it!
This article is very helpful and might form the basis of a PHPMailer implementation. Though that adds a dependency on ZF2, the principles will be the same for any other OAuth implementation such as the one from PHPClasses I linked to or this one.
Sorry I can't be much more help on this.
Update: PHPMailer now supports OAuth for gmail. This article describes how to use it, and yes it is still quite unpleasant!

How can I avoid this goddamn OAuth2 and send emails as I did it
before this "security enhancement" (for google apps account)?
You can't. Unlike regular Google, Google Apps does not allow "less secure apps". And once your account has been flagged for extra security, you must switch to OAuth2.
How to easily integrate OAuth2 class mentioned above into PHPMailer?
You can't. Like the Thunderbird team, there is some pretty strong bias against OAuth2 in the PHP Mailer team. IMO, OAuth2 is a big improvement for email.
Are there any other easy-to-use PHP solutions to send emails
using gmail?
Yes. My solution for my own SMTP project, Postman, was to switch from PHP Mailer to Zend_Mail for OAuth2. Zend_Mail has had native OAuth2 support for quite a while.

Oops, that was my mistake, I've been editing the code in wrong place, not in the one it was executed from.
Strange, but in spite of OAuth2 and other google surprises, i had not to change anything to make old code work (just update password).

Related

Why do I need OAuth when sending emails to my clients via gmail?

I have basic legacy asp.net web application (no mvc, no .net core)
As of May 30 2022 google has stopped supporting less secure apps. So now if I want to send an email with mywebapp#gmail.com as from address, its not working!
SmtpException: The SMTP server requires a secure connection or the client was not authenticated. The server response was: 5.7.0 Authentication Required. Learn more...
I have tried setting up apppassword and sending mail using NetworkCredentials, it works but straight afterwards I get an Application_OnError event raised and again the above SmtpException is thrown.
Some googling says to resolve this I needed to implement OAuth2.0, but this relates to using user's gmail account or some permissions related to this gmail account.
which is irrelevant in my scenario. I only want to send emails to my customers from mywebapp gmail account, not the user's account.
Then why should my customer (while using mywebapp) give consent to receive emails from mywebapp gmail account? given they dont have login credentials.
how is OAuth2.0 relevant in my scenario?
Feeling confused.
Side Question: If you think apppassword is the way to go then why am I receiving smtpexception after the email is successfully sent? can share code if required
My smtpClient code
Public Function SendViaGmail(subject As String, body As String, recipients As String)
Dim fromEmail As String = ConfigurationSettings.AppSettings("ContactEmail")
Dim smtpClient As Mail.SmtpClient = New Mail.SmtpClient("smtp.gmail.com") With {
.Port = 587,
.DeliveryMethod = SmtpDeliveryMethod.Network,
.Credentials = New NetworkCredential(fromEmail, "APP_PWD"),
.EnableSsl = True
}
Dim mailMessage As MailMessage = New MailMessage With {
.From = New Mail.MailAddress(fromEmail),
.Subject = subject,
.Body = body,
.IsBodyHtml = True
}
mailMessage.[To].Add(recipients)
If smtpClient IsNot Nothing Then
smtpClient.Send(mailMessage)
End If
End Function
My full post related is mentioned here
Why do I need OAuth when sending emails to my clients via gmail?
Answer: You do not, necessary it depends on the use case.
There are two ways to send emails via the smtp server now that google has removed less secure apps.
you can enable 2fa on the google account and create an apps password
you can then take the exact same code you used before and simply replace the standard user gmail password with the apps password.
the second option would be to use xoauth2.
How is OAuth2.0 relevant in my scenario?
XOauth2 is a form of Oauth2 which allows an application to request consent of a user to access their private data in this case their gmail mail account. Using XOauth to imo would be over kill in your user case if you are only connecting to your own Gmail account then there is really no reason for you to use Xoauth2 and authorize a user.
Side Question: If you think apppassword is the way to go then why am I receiving smtpexception after the email is successfully sent? can share code if required
An smtpexception would imply to me there is an error in your code.
Note: Working example can be found in authors other question SmtpClient not working after setting up app password and 2-factor authentication enabled

IMAP + Office365 + XOAUTH2: Is there any way to re-authenticate a new accessToken without disconnecting/reconnecting to the server?

So, last week my application that connects to Office365 using IMAP suddenly stopped working with Basic Authentication (gee, thanks for the early cut-off with no warning Microsoft). I tried troubleshooting that issue for hours, and could find literally nothing wrong since everything was already configured to work with Basic Auth (and was working). I do know they've been threatening to shut-off Basic Auth for a while now, and with a new looming deadline of October, 2022.
After getting nowhere with why it suddenly stopped working, I finally decided to just bite the bullet and switch to using the XOAUTH2 authentication mechanism. After a day and a half of trial-and-error to put together the right series of incantations to make that work correctly, I got that working. Microsoft's documentation is borderline garbage with conflicting information and confusing examples. That and a complete lack of any reasonable error response from the IMAP server about why authentication failed (just the lovely "NO AUTHENTICATE failed" message).
Note: I am using the Client Credentials flow and the AccessToken is being issued to expire after 1 hour.
So, here's the question:
My app basically loops on IDLE and/or processing new mail. When the AccessToken expires, the server will respond with a "Session invalidated - AccessTokenExpired" and then just close or reset the connection. This does make sense, but I would prefer to keep the connection open and just re-authenticate.
My first idea was just re-issue the "AUTHENTICATE" command 1 minute before the AccessToken expired. Server did not like that and gave me a "Command received in Invalid state." response. Hrmph.
Second idea was 1 minute before the AccessToken expired, issue a "LOGOUT" and then "AUTHENTICATE" again. However, Microsoft's IMAP server responds to the "LOGOUT" with "OK" and then closes the connection... Hrmph.
C: R0001 AUTHENTICATE XOAUTH2
S: +
C: <username:token base64>
S: R0001 OK AUTHENTICATE completed.
C: R0002 CAPABILITY
S: * CAPABILITY IMAP4 IMAP4REV1 AUTH=PLAIN AUTH=XOAUTH2 SASL-IR UIDPLUS MOVE ID UNSELECT CLIENTACCESSRULES CLIENTNETWORKPRESENCELOCATION BACKENDAUTHENTICATE CHILDREN IDLE NAMESPACE LITERAL+
S: R0002 OK CAPABILITY completed.
C: R0003 SELECT INBOX
... <59 mins later> ...
C: R0021 LOGOUT
S: * BYE Microsoft Exchange Server IMAP4 server signing off.
S: R0021 OK LOGOUT completed.
Connection closed.
I did notice there's a server capability called "BACKENDAUTHENTICATE", but there literally is no documentation that I could find on what the heck that capability is about or used for...
What I would really like to do is just issue something like "AUTHENTICATE" again, but with the new AccessToken and then go back to the IDLE/new mail loop. Or maybe a "REAUTHENTICATE" command (that doesn't currently exist).
And yes, I have read RFC4959, RFC3501, and even RFC2222 (as well as a lot of SO posts).
For now, I have just accepted the fact that the connection is going to close and then I'll turn around and re-open a new one...
I would love to hear if anyone has any other bright ideas.
I am considering re-implementing the application using their Graph API, which might be the slightly better long-term option assuming we stay on Microsoft Office365.
I did like that IMAP was a more generic and broadly accepted mailbox protocol and why I chose it in the first place.
Let me try to answer some of your questions.
I do know they've been threatening to shut-off Basic Auth for a while now, and with a new looming deadline of October, 2022. After getting nowhere with why it suddenly stopped working
Microsoft says that in early 2022, they will pick tenants (using some unpublished criteria) and disable basic authentication for all the chosen protocols except SMTP AUTH for a period of between 12 and 48 hours. SMTP AUTH is excluded because it might affect important operational aspects like multi-functional devices or PowerShell scripts sending updates about a job’s progress. When the period expires, Microsoft will enable basic authentication automatically.
Please refer to this link : https://office365itpros.com/2021/09/24/basic-authentication-exchange/
The Basic Auth has been already disabled for many of my clients, so the above statement is valid.
I am using the Client Credentials flow and the AccessToken is being issued to expire after 1 hour.
Using the Client Credentials flow, you do not get a refresh Token which can be used to get a valid Token without losing/dropping/closing the connection.
Based on the RFC6749 (https://www.rfc-editor.org/rfc/rfc6749#section-4.4.3), a refresh Token should not be included.
As #Max mentioned in his comment, "RFC3501 does not include any ability to reauthenticate an existing connection".
Since you don't want to lose/close the connection, I would recommend to use the
Oauth2 authorization code flow (https://learn.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-auth-code-flow), which will give you a refresh Token as well.
Also, I would recommend to use the Microsoft Authentication Library (MSAL) (https://learn.microsoft.com/en-us/azure/active-directory/develop/msal-overview)
The Microsoft Authentication Library (MSAL) enables developers to acquire tokens from the Microsoft identity platform in order to authenticate users and access secured web APIs. It can be used to provide secure access to Microsoft Graph, other Microsoft APIs, third-party web APIs, or your own web API. MSAL supports many different application architectures and platforms including .NET, JavaScript, Java, Python, Android, and iOS.

PHPMailer authentication issue xoauth2

I am using Google Business Apps for emails, and trying to send emails through PHPMailer. Now there is an issue with the SSL certificate so I have to turn off the SSL verification, but this errors is thrown up:
Auth method requested: XOAUTH2
Auth methods available on the server: PLAIN,LOGIN
SMTP Error: Could not authenticate.
Now my host isn't particularly helpful as its saying I need to use the correct email/pass, but that's not the way it works as we have to create an App via Google Developer and the connection is verified.
I am wondering if XOAUTH2 needs to be installed to the server? I have access to cPanel, but can't find the module.
Read the troubleshooting guide that the error links you to.
I'd bet that your ISP is intercepting your traffic and redirecting you to their own mail server, which will fail to match gmail's SSL certificate, and also lacks gmail's XOAUTH2 authentication scheme.
You should pay attention to why you're getting these errors - certificate verification is there to protect you and when it fails a check it's telling you that someone is intercepting your traffic and trying to MITM you - and by disabling it you've already given away your gmail credentials.

MVC google login - OpenID auth request contains an unregistered domain

When I try to login today via google in my web app, I get that error:
400 That’s an error.
OpenID auth request contains an unregistered domain:
http://XXX.XXX.XXX/ (IP here)
But on localhost everything works fine. What is more - on other project also everything works nice.
I'm using default OAuth:
OAuthWebSecurity.RegisterGoogleClient();
How to resolve it?
I would like to add some context to this thread together with a potential solution to developers that are currently blocked.
Back in February we announced the deprecation of OpenID 2.0 (OID2) scheduled for April 2015. We also announced that new OID2 relying parties (RPs) registrations** will no longer be accepted after April 2014.
Given that the API will be shut-down in less than a year’s time, our intention is to avoid having new RPs integrating with Google's OID2 API. Instead, we suggest to use our OpenID Connect API which we consider more secure and easier to implement.
Registrations were effectively closed on May 19th (as documented in the Google’s OID2 developer documentation). All RPs already using OID2 should not be affected by this the closure.
As for developers currently working on an integration with our OID2 API (presumably because they missed the announcement and warnings in our OID2 documentation), we will do our best to minimize the friction caused by the registration closure. If you are in such situation, please let us know by posting a registration request before June 15th. The post should contain a sample OID2 request used by your application, in case you prefer not to disclose such information, please post an email address and we will reach out. We plan to look into each case and try to get you unblocked in the best possible way.
Miguel.
** OID2 does not have a registration procedure for RPs integrating with an identity provider. RPs are associated to the realm value (e.g., www.example.com) used when contacting Google OID2 API. Thus, a RP is considered "registered" if its realm value has been used to contact our OID2 API.
This approach is obsolete as Google changed their auth to OAuth2
I didn't delete this answer because formerly approved api users are still valid to use.
== Original post below ==
If you are OWIN-based MVC5 user, just change Startup.Auth.cs file
app.UseGoogleAuthentication();
to
app.UseGoogleAuthentication(
clientId: "000-000.apps.googleusercontent.com",
clientSecret: "00000000000");
according to the http://www.asp.net/mvc/tutorials/mvc-5/create-an-aspnet-mvc-5-app-with-facebook-and-google-oauth2-and-openid-sign-on page.
Google has disabled OpenID2 for new domains. Existing relying parties can continue to use the API at least until the end of the deprecation period that runs through to April 2015. The announcement is at: https://developers.google.com/+/api/auth-migration#timetable

Using 2-legged OAuth with Gmail IMAP

I am trying to use OAuth to do a 2 legged authorization to the Gmail IMAP server, as documented
in https://developers.google.com/gmail/oauth_protocol. I am having trouble, getting "invalid credentials" in response to the AUTHENTICATE XOAUTH command.
Obviously there are many potential points of error in my code, but I believe I have the SHA1 generation, URL encoding, Base64 encoding, all done correctly. My specific question right now is regarding how to identify my application as being allowed to use 2LO. This documentation
(https://developers.google.com/accounts/docs/OAuth#GoogleAppsOAuth) says that third party software vendors must register their application with Google to use 2LO, and that domain administrators must grant access to those vendors. However, I have experimented with a commercial application that does this, and I am not required at any point to grant access to it, just supply it with my domain's consumer key and secret. It works fine. (Nevertheless, I have gone into the Google Apps console and checked "enable this consumer key" and "allow access to all APIs").
In the IMAP XOAUTH protocol, where would I tell it what my application is? The only place I see would be the "XOauth_requestor_id" parameter. Is that it? What do I put there? I have tried the email address and various other values that I get from the Google API control panel, but nothing works.
Any help or examples (of all the input data and resulting base64-encoded output) you can provide would be appreciated.

Resources