Reputation: 101
I am developing an application in Xamarin Android using .NET Standard 2.0. I need to send emails to users within my organization at a certain time. I am trying to implement OAuth 2 authentication since basic authentication will no longer be feasible in Microsoft.
I obtain a token correctly, but when I try to send the email, I get an error: "MailKit.Security.AuthenticationException: 535: 5.7.3 Authentication unsuccessful."
I can't figure out what I'm doing wrong. Could you please help me? Here are two versions of the code I have for sending the email; neither of them works and both give me the same error.
using System;
using System.Threading.Tasks;
using MailKit.Net.Smtp;
using MailKit.Security;
using MimeKit;
using Microsoft.Identity.Client;
namespace TancarOFs.Services
{
public class EmailService2
{
private static string[] scopes = new string[] { "https://outlook.office365.com/.default" };
private static readonly string tenantId = "AAAAAAA";
private static readonly string clientId = "BBBBBBBBB";
private static readonly string clientSecret = "CCCCCCC";
public async Task SendEmailAsync(string to, string cc, string subject, string body)
{
try
{
var confidentialClient = ConfidentialClientApplicationBuilder.Create(clientId)
.WithClientSecret(clientSecret)
.WithAuthority(new Uri($"https://login.microsoftonline.com/{tenantId}"))
.Build();
var authResult = await confidentialClient.AcquireTokenForClient(scopes).ExecuteAsync();
var message = new MimeMessage();
message.From.Add(new MailboxAddress("no-reply", "[email protected]"));
//message.To.Add(new MailboxAddress(to, to));
foreach (var recipient in to.Replace(" ", "").Split(new[] { ',', ';' }))
{
message.To.Add(new MailboxAddress(recipient, recipient));
}
if (cc != null)
{
foreach (var copy in cc.Replace(" ", "").Split(new[] { ',', ';' }))
{
message.Cc.Add(new MailboxAddress(copy, copy));
}
}
message.Subject = subject;
message.Body = new TextPart("plain") { Text = body };
using (var client = new SmtpClient())
{
await client.ConnectAsync("smtp.office365.com", 587, SecureSocketOptions.StartTls);
client.Authenticate(new SaslMechanismOAuth2("[email protected]", authResult.AccessToken));
await client.SendAsync(message);
await client.DisconnectAsync(true);
}
}
catch (Exception e)
{
throw;
}
}
}
}
Aqui otra versión con el mismo error
using System;
using System.Collections.Generic;
using System.Text.Json;
using System.Net.Http;
using System.Threading.Tasks;
using MailKit.Net.Smtp;
using MailKit.Security;
using MimeKit;
namespace TancarOFs.Services
{
public class EmailService
{
private string _scope = "https://outlook.office365.com/.default";
private static readonly string TenantId = "AAAAAAAA";
private static readonly string _clientId = "BBBBBBBBBB";
private static readonly string _clientSecret = "CCCCCCCC";
private static readonly string _username = "[email protected]";
public async Task SendEmailAsync(string to, string cc, string subject, string body)
{
try
{
var token = await GetAccessTokenAsync("");
var message = new MimeMessage();
message.From.Add(new MailboxAddress("no-reply", _username));
//message.To.Add(new MailboxAddress(to, to));
foreach (var recipient in to.Replace(" ", "").Split(new[] { ',', ';' }))
{
message.To.Add(new MailboxAddress(recipient, recipient));
}
if (cc != null)
{
foreach (var copy in cc.Replace(" ", "").Split(new[] { ',', ';' }))
{
message.Cc.Add(new MailboxAddress(copy, copy));
}
}
message.Subject = subject;
message.Body = new TextPart("plain") { Text = body };
using (var client = new SmtpClient())
{
await client.ConnectAsync("smtp.office365.com", 587, SecureSocketOptions.StartTls);
await client.AuthenticateAsync(new SaslMechanismOAuth2(_username, token));
await client.SendAsync(message);
await client.DisconnectAsync(true);
}
}
catch (Exception e)
{
throw;
}
}
private async Task<string> GetAccessTokenAsync(string code)
{
var request = new HttpRequestMessage(HttpMethod.Post, $"https://login.microsoftonline.com/{TenantId}/oauth2/v2.0/token");
request.Content = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("client_id", _clientId),
new KeyValuePair<string, string>("client_secret", _clientSecret),
new KeyValuePair<string, string>("grant_type", "client_credentials"),
new KeyValuePair<string, string>("scope", _scope)
});
var client = new HttpClient();
var response = await client.SendAsync(request);
var content = await response.Content.ReadAsStringAsync();
var tokenResponse = JsonDocument.Parse(content);
return tokenResponse.RootElement.GetProperty("access_token").GetString();
}
}
}
I forgot to mention that I have created the application in Azure AD with several permissions, but it still doesn't work.
Thanks in advance
Upvotes: 0
Views: 32