Reputation: 17
We have a console application that uses Aspose email dll for sending mails and various other functionalities.
Since it uses basic authentication that is getting deprecated soon by microsoft so we are planning to have authentication using Microsoft Graph API.
So I have done below steps
1)Registered the app in Microsoft Azure active directory and gave permissions under Microsoft Graph. PFA(AzureAPP_permissions.png)
2)I added code for generating token using graph API and then tried fetching email,sending email using Aspose dll but every time it throws below error.
**Aspose.Email.AsposeBadServerResponceException: 'Server error Status: BadRequest Description: /me request is only valid with delegated authentication flow. Details:
POST: https://graph.microsoft.com/v1.0/me/mailFolders/inbox/messages ---------------------------------------** Please help what is going wrong here PFB the code part
using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
using Aspose.Email.Clients;
using Aspose.Email.Clients.Graph;
using Aspose.Email.Mapi;
using EASendMail;
namespace Email
{
internal class Graph_API
{
private static string _clientId = ConfigurationManager.AppSettings["ClientId"];
private static string _tenantId = ConfigurationManager.AppSettings["TenantId"];
private static string _secretValue = ConfigurationManager.AppSettings["SecretValue"];
static string _postString(string uri, string requestData)
{
HttpWebRequest httpRequest = WebRequest.Create(uri) as HttpWebRequest;
httpRequest.Method = "POST";
httpRequest.ContentType = "application/x-www-form-urlencoded";
using (Stream requestStream = httpRequest.GetRequestStream())
{
byte[] requestBuffer = Encoding.UTF8.GetBytes(requestData);
requestStream.Write(requestBuffer, 0, requestBuffer.Length);
requestStream.Close();
}
try
{
HttpWebResponse httpResponse = httpRequest.GetResponse() as HttpWebResponse;
var responseText = new StreamReader(httpResponse.GetResponseStream()).ReadToEnd();
Console.WriteLine(responseText);
return responseText;
}
catch (WebException ep)
{
if (ep.Status == WebExceptionStatus.ProtocolError)
{
var responseText = new StreamReader(ep.Response.GetResponseStream()).ReadToEnd();
Console.WriteLine(responseText);
}
throw ep;
}
}
public string GenerateToken()
{
string client_id = _clientId;
string client_secret = _secretValue;
string tenant = _tenantId;
string requestData =
string.Format("client_id={0}&client_secret={1}" + "&scope=https://graph.microsoft.com/.default&grant_type=client_credentials",
client_id, client_secret);
string tokenUri = string.Format("https://login.microsoftonline.com/{0}/oauth2/v2.0/token", tenant);
string responseText = _postString(tokenUri, requestData);
OAuthResponseParser parser = new OAuthResponseParser();
parser.Load(responseText);
var vv = parser.AccessToken;
return vv;
}
public void Generatemail()
{
interface_class bb = new interface_class();
IGraphClient client = GraphClient.GetClient(bb, _tenantId);
MapiMessage mm = new MapiMessage();
mm.Subject = "EMAILNET-39318 " + Guid.NewGuid().ToString();
mm.Body = "EMAILNET-39318 REST API v1.0 - Create Message";
mm.SetProperty(KnownPropertyList.DisplayTo, "[email protected]");
mm.SetProperty(KnownPropertyList.SenderName, "[email protected]");
mm.SetProperty(KnownPropertyList.SentRepresentingEmailAddress, "[email protected]");
// Create message in inbox folder
MapiMessage createdMessage = client.CreateMessage(Aspose.Email.Clients.Graph.KnownFolders.Inbox, mm);
}
public void FetchMail()
{
try
{
interface_class bb = new interface_class();
using (IGraphClient client = GraphClient.GetClient(bb, _tenantId))
{
FolderInfoCollection folderInfoCol1 = client.ListFolders();
FolderInfo inbox = null;
foreach (FolderInfo folderInfo in folderInfoCol1)
{
if (folderInfo.DisplayName.Equals("Inbox", StringComparison.InvariantCultureIgnoreCase))
{
inbox = folderInfo;
break;
}
}
MessageInfoCollection messageInfoCol = client.ListMessages(inbox.ItemId);
MessageInfo messageInfo = messageInfoCol[0];
MapiMessage message = client.FetchMessage(messageInfo.ItemId);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Aspose.Email.Clients;
using Aspose.Email.Clients.Graph;
namespace Email
{
internal class interface_class : ITokenProvider
{
Graph_API obj = new Graph_API();
DateTime expirationDate = DateTime.Today.AddDays(1);
public void Dispose()
{
throw new NotImplementedException();
}
public OAuthToken GetAccessToken()
{
string token = obj.GenerateToken();
return new OAuthToken(token, expirationDate);
}
public OAuthToken GetAccessToken(bool ignoreExistingToken)
{
throw new NotImplementedException();
}
}
}
Upvotes: 0
Views: 5735
Reputation: 15991
https://graph.microsoft.com/v1.0/me/mailFolders/inbox/messages
This endpoint is used to query inbox messages for a user right? Then who is /me
here? And this is the issue.
In your code snippet, I noticed that you set the grant_type=client_credentials
so you are using client credential flow. It's correct but pls note that you need to give application api permission. Application api permission is for client credential flow. And this api require Mail.ReadBasic.All, Mail.Read, Mail.ReadWrite
permissions.
If you can generate access token successfully, you may decode the token the check if the roles
claim contained correct permissions.
When you get a correct token, then pls use Get: /users/{id | userPrincipalName}/mailFolders/inbox/messages
instead of /me
. If you want to query emails for [email protected]
, then the url can be /users/[email protected]/mailFolders/inbox/messages
.
I also notice that you had GraphClient
in your code. So you may also try my code below:
using Azure.Identity;
using Microsoft.Graph;
var scopes = new[] { "https://graph.microsoft.com/.default" };
var tenantId = "your_tenant_name.onmicrosoft.com";
var clientId = "azure_ad_app_client_id";
var clientSecret = "client_secret_for_the_azuread_app";
var clientSecretCredential = new ClientSecretCredential(
tenantId, clientId, clientSecret);
var graphClient = new GraphServiceClient(clientSecretCredential, scopes);
var messages = await graphClient.Users["user_id/PrincipalName"].Messages
.Request()
.GetAsync();
Upvotes: 1