M365: Microsoft Graph – Part 10 – Send Email using Graph API from Console Application (Background Job)

Hi All,
LIFE IS BEAUTIFUL 🙂 Today with MS Graph, my favorite feature of M365 🙂
In following previous articles we have discussed regarding Microsoft Graph. Today again long time back new article on MS GRAPH 🙂
- Office 365 – Microsoft Graph and Graph Explorer
- Office 365 – Microsoft Graph beginning – Part 1
- Office 365 – Microsoft Graph – Part 2 – Granting permission to Azure Apps to use Microsoft Graph APIs using CSOM
- Office 365 – Microsoft Graph – Part 3 – Azure Access Token: to call Graph APIs from CSOM
- Office 365 – Microsoft Graph – Part 4 – Fetching all Office 365 groups using CSOM- Codebase
- Office 365 – Microsoft Graph – Part 5 – Fetching Office 365 group owners using CSOM – Codebase
- Office 365 – Microsoft Graph – Part 6 – Adding Office 365 Group Owner using CSOM – Codebase
- Office 365 – Microsoft Graph – Part 7 – Removing owner from Office 365 Group using CSOM – Codebase
- Office 365 – Microsoft Graph – Part 8 – Getting all users of our tenant using CSOM
- Office 365 – Microsoft Graph – Part 9 – Few important points while consuming Microsoft Graph APIs in SharePoint Framework components
In today’s article we will simple discuss steps to send an email from console application (background job) using Graph API.
Prerequisites:
- Azure App – For authentication, we will execute our code on be half of Azure App. To register new Azure App – Office 365 – Azure Active Directory – Registering/Creating new Azure App – detailed steps
- Once we have Azure App, we need to give the Application permissions to send the mail “Mail.Send“.
- Please follow the article to assign the permission to Azure App – Office 365 – Microsoft Graph – Part 2 – Granting permission to Azure Apps to use Microsoft Graph APIs using CSOM

Detailed Steps:
- Once we have Azure App with respective permission, we are ready to consume the GraphServiceClient (Microsoft.Graph) class which requires instance of IAuthenticationProvider (Microsoft.Graph ) as
AuthProvider authProvider = new AuthProvider(); // AuthProvider is our custom class. Please have a look at below code snippet.
GraphServiceClient _graphClient = new GraphServiceClient(authProvider);
- We have our own AuthProvider class inherited from IAuthenticationProvider interface and implementing AuthenticateRequestAsync() method as
- Here we are using X509Certificate2 certificate and AppId for authentication. We are not using Client Secret key.
namespace KnowledgeJunction.Azure
{
public class AuthProvider : IAuthenticationProvider
{
/// <summary>
/// This method is called when actual request is made
/// </summary>
/// <param name="request">Request object, in header we add the access token</param>
/// <returns></returns>
public async Task AuthenticateRequestAsync(HttpRequestMessage request)
{
try
{
string resource = "https://graph.microsoft.com";
//reading tenant id from config file
string authority = "https://login.windows.net/" + ConfigurationManager.AppSettings["TenantId"];
AuthenticationContext auth = new AuthenticationContext(authority, false);
// Here we are using AppID and certificate for authentication. We are not
// using client secret key
//Reading azure app id from config file
// My certificate - X509Certificate2
//(System.Security.Cryptography.X509Certificates).
var cac = new ClientAssertionCertificate(ConfigurationManager.AppSettings["AzureAppId"], X509Certificate2);
var authResult = await auth.AcquireTokenAsync(resource, cac);
var accessToken = authResult.AccessToken;
request.Headers.Add("Authorization", "Bearer " + accessToken);
}
catch (Exception ex)
{
//ToDo : Proper exception handling
}
}
- Create the Message (Microsoft.Graph.Message) object as
var message = new Microsoft.Graph.Message
{
Subject = subj,
Body = new ItemBody
{
ContentType = Microsoft.Graph.BodyType.Html,
Content = body
},
ToRecipients = new List<Recipient>()
{
new Recipient
{
EmailAddress = new Microsoft.Graph.EmailAddress
{
Address = to
}
}
}
};
- Call SendMail method of GraphServiceClient class as
await graphClient.Me
.SendMail(message,false)
.Request()
.PostAsync();
- When above request is made, method “AuthenticateRequestAsync” of AuthProvider class is getting called.
- If we don’t want to send email on be half of specific user, we could use shared email box as well.
References:
Thanks a lot for reading 🙂 Enjoy the beautiful LIFE 🙂 HAVE A SAFE LIFE 🙂 TAKE CARE 🙂
You would be the first person I’ve seen posting use of GraphServiceClient using the Daemon app design utilizing a certificate instead of a client secret. The documentation in this area is quite sparse so its hard to find adequate examples so thanks for posting what you done here.
I do have a question though. How do you go about caching the token using ConfidentialClientApplicationBuilder? MSAL provides in memory caching by default for ASP.Net, but for Daemon apps that are not blessed as a web service how do you enable app file based caching? Again, there are tons of examples for User Token caching, but the Daemon app cache is different in that there is no refresh token and again… documentation seems to have tanked in this realm. Microsoft doesn’t seem to have updated documentation and code examples for using ConfidentialClientApplicationBuilder with app cache, but there’s plenty of documentation and examples for using app cache with the deprecated ConfidentialClientApplication API version.
Hi Pete,
Thanks a lot 🙂
Regarding answer to your question, I am sorry but I didnt require to use cache in my Jobs. MSAL refreshes the token automatically.
Hi,
I tried your code to send emails in background service, but I got an error as below:
Error :Code: BadRequest
Message: Current authenticated context is not valid for this request. This occurs when a request is made to an endpoint that requires user sign-in. For example, /me requires a signed-in user. Acquire a token on behalf of a user to make requests to these endpoints. Use the OAuth 2.0 authorization code flow for mobile and native apps and the OAuth 2.0 implicit flow for single-page web apps.
Inner error
Can you tell me where I have been wrong?
Thanks
Hi Minal,
Is it possible to share your code here. I’ll like to check once. Or you can share on my email – psabadra@gmail.com
I have sent you the code on your email id. Kindly review
Has your error been resolved? I also encountered the same error, do you have any solutions?
Can you please share your code to sshrishi@gmail.com
Hi Hrishikesh,
Thanks for reading the article.
I tried to incorporate as much as code in the article. I would say please try to build from this and in case any errors occurs please let me know. We will defiantly check.
Thanks!
Br,
Prasham Sabadra
psabadra@gmail.com
+91 7410017229