I am using ConfidentialClientApplicationBuilder to get token and then send email
var pca = ConfidentialClientApplicationBuilder
.Create(ClientId)
.WithClientSecret(clientSecret)
.WithAuthority(AzureCloudInstance.AzurePublic, Tenant)
.WithRedirectUri(RedirectUrl)
.Build();
var outlookScope = new string[] { "https://outlook.office365.com/SMTP.Send" }; // for graph use "https://graph.microsoft.com/.default"
AuthenticationResult result = null;
try
{
result = await pca.AcquireTokenForClient(outlookScope)
.ExecuteAsync();
}
catch (MsalException ex)
{
Console.WriteLine($"Error acquiring access token: {ex}");
}
But i get this error when on result Microsoft.Identity.Client.MsalServiceException: 'AADSTS1002012: The provided value for scope https://outlook.office365.com/SMTP.Send is not valid. Client credential flows must have a scope value with /.default suffixed to the resource identifier (application ID URI).
What scope should i use to get token successfully, further i am using this smpt to send email
using (var emailClient = new MailKit.Net.Smtp.SmtpClient())
{
var oauth2 = new SaslMechanismOAuth2(result.Account.Username, result.AccessToken);
await emailClient.ConnectAsync(SMPTServerName, SMPTServerPort, SecureSocketOptions.StartTls); //google smtp.gmail.com
await emailClient.AuthenticateAsync(oauth2);
// Message Body
await emailClient.SendAsync(message);
Update Thanks to Rukmini, i was to able to get access token using
var outlookScope = new string[] { "https://outlook.office365.com/.default" };
Now the issue that i am having is to authenticate that token . This is the code
if (result != null)
{
Console.WriteLine($"Access token: {result.AccessToken}");
var message = new MimeMessage();
message.From.Add(new MailboxAddress("Sender Name", "sender@example.com"));
message.To.Add(new MailboxAddress("Recipient Name", "recipient@example.com"));
message.Subject = "Test Email";
message.Body = new TextPart("plain")
{
Text = "This is a test email sent using MailKit and Microsoft.Identity.Client."
};
using (var emailClient = new SmtpClient())
{
var oauth2 = new SaslMechanismOAuth2(result.Account.Username, result.AccessToken);
await emailClient.ConnectAsync("smtp.office365.com", 587, SecureSocketOptions.StartTls);
await emailClient.AuthenticateAsync(oauth2);
await emailClient.SendAsync(message);
await emailClient.DisconnectAsync(true);
}
}
Now firstly result Account is null, so I get this error
Even if i put a random username, get this error MailKit.Security.AuthenticationException: '535: 5.7.3 Authentication unsuccessful [DX0P273CA0070.AREP273.PROD.OUTLOOK.COM 2023-10-16T04:50:43.626Z 08DBCDB69CE3A094]'
I tried the same code in my environment and got the same error as below:
Note that: If you are using client credential flow to generate the access token, then the scope must have /.default as suffix to the resource. In your case the scope must be
https://outlook.office365.com/.default
I modified the code like below to fetch the access token for outlook resource:
using Microsoft.Identity.Client;
using System;
namespace ConsoleApp1
{
class Program
{
static async System.Threading.Tasks.Task Main(string[] args)
{
string ClientId = "ClientID";
string clientSecret = "ClientSecret";
string Tenant = "TenantID";
string RedirectUrl = "https://jwt.ms";
var pca = ConfidentialClientApplicationBuilder
.Create(ClientId)
.WithClientSecret(clientSecret)
.WithAuthority(AzureCloudInstance.AzurePublic, Tenant)
.WithRedirectUri(RedirectUrl)
.Build();
var outlookScope = new string[] { "https://outlook.office365.com/.default" };
AuthenticationResult result = null;
try
{
result = await pca.AcquireTokenForClient(outlookScope)
.ExecuteAsync();
}
catch (MsalException ex)
{
Console.WriteLine($"Error acquiring access token: {ex}");
}
if (result != null)
{
Console.WriteLine($"Access token: {result.AccessToken}");
}
}
}
}
Decoded token:
UPDATE:
You can make use of Microsoft Graph API to send mail like below:
Grant API permissions:
Use the below code:
using Azure.Identity;
using Microsoft.Graph;
using Microsoft.Graph.Models;
using Microsoft.Graph.Models.ODataErrors;
var scopes = new[] { "https://graph.microsoft.com/.default" };
var clientId = "XXX";
var tenantId = "XXX";
var clientSecret = "***";
var options = new ClientSecretCredentialOptions
{
AuthorityHost = AzureAuthorityHosts.AzurePublicCloud,
};
var clientSecretCredential = new ClientSecretCredential(
tenantId, clientId, clientSecret, options);
var graphClient = new GraphServiceClient(clientSecretCredential, scopes);
var requestBody = new Microsoft.Graph.Users.Item.SendMail.SendMailPostRequestBody
{
Message = new Message
{
Subject = "Test mail",
Body = new ItemBody
{
ContentType = BodyType.Html,
Content = "This is Test mail",
},
ToRecipients = new List<Recipient>
{
new Recipient
{
EmailAddress = new EmailAddress
{
Address = "user@***.onmicrosoft.com",
},
},
},
},
};
try
{
await graphClient.Users["user1@**.onmicrosoft.com"].SendMail.PostAsync(requestBody);
Console.WriteLine("Successfully sent mail");
}
catch (ODataError odataError)
{
Console.WriteLine(odataError.Error.Code);
Console.WriteLine(odataError.Error.Message);
}