Support for SMTP OAuth authentication #17142
Replies: 3 comments 4 replies
-
Sounds like a good idea, if you can make the current implementation of |
Beta Was this translation helpful? Give feedback.
-
@bergmania I got a client requesting this, as their IT department is going to shut down Basic Auth start of 2025, so I'll take a stab at making whatever here-and-now solution I'm building into a suitable pull request. |
Beta Was this translation helpful? Give feedback.
-
@bergmania @aguyfromdenmark I've made a pull request here #17484 Longer Read: So it turns out this is complicated. MailKit has a rudementary OAuth2 implementation where you hand it a username and a token and it goes off and does it's thing, and I now understand why it doesn't help you get the token. It turns out we would have to write -many- oauth options and implementations to be able to get an access token, and even then it would most of the time not accomplish what an user was actually hoping to do, which is to send an e-mail. Microsofts Azure/Exchange solution is neigh impossible to set up correctly, and definitely currently not possible to set up following Microsoft's documentation. They are leaning heavily towards you using Microsoft Graph as a means of sending e-mails, which means abandoning SMTP. (If ANYONE has gotten this to work without giving the app registration godlike powers, write me) Google's api's for authorization (Google.Apis.Auth) as of this date, returns service worker access tokens that are too big to send over SMTP and will get rejected by Google's own servers. Again. leaning towards you using their APIs to send the email instead of SMTP. Sendgrid/Mailchimp/Mailgun etc. currently don't support SMTP with OAuth, so the case for actually using OAuth2 for authorization in SMTP is right now very small. Even assuming all of the above actually worked, and wasn't hard/impossible to do right now, we are still left with way too many variables as to how you fetch your original access token to be able to make a general solution that would support pretty much anything, as it can be based of client-id/secret, client-id/secret-as-json-file or client-id/p12-certificate and I'm sure and bunch of others. Instead I lean towards supporting basic SMTP authentication with username/password like now, and instead making integration to other providers solutions easier. There is still nothing preventing anything from rolling their own client, but with my pull request, now you can add your own "IEmailSenderClient" to your solution and only have to implement a single method to be in control of how Umbraco sends out your e-mail. I have updated EmailSender to use a default implementation of IEmailSenderClient (that is the Mailkit SMTP client) and it will then be trivial to support other sending-methods by just applying your own implementation, without having to also implement all the logic Umbraco already has in constructing the MimeMessage. Following quick example would send the e-mail through Microft Graph and could also make for a bunch of small packages for Umbraco so people can quickly get up to speed with a new email solution. public class MicrosoftGraphEmailClientComposer : IComposer
{
public void Compose(IUmbracoBuilder builder)
{
builder.Services.AddTransient<IEmailSenderClient, MicrosoftGraphEmailClient>();
}
}
public class MicrosoftGraphEmailClient : IEmailSenderClient
{
private ClientSecretCredential? credentials;
public MicrosoftGraphEmailClient()
{
var tenantId = "<tenant-id>";
// Values from app registration
var clientId = "<client-id>";
var clientSecret = "<client-secret>";
// using Azure.Identity;
var options = new TokenCredentialOptions
{
AuthorityHost = AzureAuthorityHosts.AzurePublicCloud
};
credentials = new ClientSecretCredential(
tenantId, clientId, clientSecret, options);
if (credentials == null)
{
throw new ArgumentNullException(nameof(credentials));
}
}
public async Task SendAsync(MimeMessage? mimeMessage)
{
if (mimeMessage == null)
{
throw new ArgumentNullException(nameof(mimeMessage));
}
var scopes = new[] { "https://graph.microsoft.com/.default" };
var graphClient = new GraphServiceClient(credentials, scopes);
var stream = new MemoryStream();
mimeMessage.WriteTo(stream);
var base64content = Convert.ToBase64String(stream.ToArray());
var ri = graphClient.Users[mimeMessage.From.ToString()].SendMail.ToPostRequestInformation(new SendMailPostRequestBody());
ri.Headers.Clear();// replace the json content header
ri.SetStreamContent(new MemoryStream(Encoding.UTF8.GetBytes(base64content)), "text/plain");
var result = await graphClient.RequestAdapter.SendAsync<Message>(ri, Message.CreateFromDiscriminatorValue);
}
} This will allow some the community to easliy roll packages that implements cloud/vendor-specific email-clients |
Beta Was this translation helpful? Give feedback.
-
Lately, we have been contacted by multiple clients who would like to use OAuth for SMTP authentication. As it is, Umbraco CMS only supports Basic Auth. As Microsoft is deprecating Basic Authentication for SMTP by September 2025, I only expect more of these inquiries.
For now, you can implement your own IEmailSender. But if this is going to be prevalent, Ithink it will make sense for Umbraco CMS to support this out of the box.
Beta Was this translation helpful? Give feedback.
All reactions