Using MailBee.NET EWS to access Office 365 mailbox in non-interactive case

I recently posted an article on how to access Office 365 mailbox for a non-interactive application (where users don’t need to provide their consent to the app to access their mailboxes). In that sample, we had to use MS Graph instead of IMAP access, to make use of OAuth 2.0. There is, however, another option – EWS.

Again, we’ll use MailBee.NET Objects as a library for making connections with the mail server. It’s a set of email components for .NET platform, and it allows for accessing MS Exchange servers (including Office 365) via Exchange Web Services. Since we’re speaking of a non-interactive case, we’ll be accessing the mailbox using credentials of an application in Azure portal.

The basics of creating an app registration in Azure are covered in OAuth 2.0 for Office 365 Accounts (installed applications) article or OAuth 2.0 with IMAP/SMTP for Office 365 in ASP.NET Core 3.1 MVC applications version for web apps. But in this case, we’re not using IMAP so we won’t need IMAP.AccessAsUser.All permission. At “API Permissions screen”, click “Add a permission” button and switch to “APIs my organization uses” tab. In search bar, type “office” and select “Office 365 Exchange Online”:

On the next screen under “Application permissions” section, select “full_access_as_app” and click “Add permissions”:

Once you’re back to “API permissions” screen, be sure to select the newly added permission and Grant admin access for organization.

The following sample demonstrates the use of MailBee.NET EWS component for accessing Office 365 mailbox non-interactively. We’ll obtain the authentication token, log onto Office 365 via Exchange Web Services to read the newest message in Inbox and to send a test email out.

To build this sample, you’ll need to add Microsoft.Exchange.WebServices, Microsoft.Identity.Client, MailBee.NET and MailBee.NET.EWS packages in Nuget.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MailBee;
using MailBee.EwsMail;
using Microsoft.Exchange.WebServices.Data;
using Microsoft.Identity.Client;

// We need this because MailMessage type exists in both MailBee and Managed EWS
using MailBeeMailMessage = MailBee.Mime.MailMessage;

namespace EwsWithOauthConsoleApp
{
    class Program
    {
        private static string Tenant = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"; // Directory (tenant) ID, from Azure app.
		private static string Instance = "https://login.microsoftonline.com/";
		private static string ClientId = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxx"; // Application (client) ID, from Azure app.
		private static string ClientSecret = "secret"; // You create one in "Certificates & secrets" of Azure app registration.
		private static string email = "user@some.office365.domain";

        static async System.Threading.Tasks.Task Main(string[] args)
        {
            MailBee.Global.LicenseKey = "MN120-nnnnnnnnnnnnnnnnnnnnnnnnnnnn-nnnn";

            // Using Microsoft.Identity.Client 4.22.0
            IConfidentialClientApplication app = ConfidentialClientApplicationBuilder
                .Create(ClientId)
                .WithClientSecret(ClientSecret)
                .WithTenantId(Tenant)
                .Build();

            // The permission scope required for EWS access
            var ewsScopes = new string[] { "https://outlook.office365.com/.default" };

            // Make the token request
            AuthenticationResult authResult = null;
            authResult = await app.AcquireTokenForClient(ewsScopes).ExecuteAsync();
            OAuthCredentials authCreds = new OAuthCredentials(authResult.AccessToken);

           // Access Office365 mailbox
            Ews ewsClient = new Ews();
            ewsClient.InitEwsClient(ExchangeVersion.Exchange2010_SP1, TimeZoneInfo.Utc);
            ewsClient.SetServerUrl("https://outlook.office365.com/EWS/Exchange.asmx");
            ewsClient.SetCredentials(authCreds);
            ewsClient.Service.ImpersonatedUserId = new ImpersonatedUserId(ConnectingIdType.SmtpAddress, email);

           // Retrieve information on Inbox and load the newest message
            FolderId foldId = null;
            foldId = ewsClient.FindFolderIdByFullName("Inbox");
            EwsItem mailItem = null;
            mailItem = ewsClient.DownloadItem(foldId, 0, EwsItemParts.GenericItem);
            Console.WriteLine("From: " + mailItem.From);
            Console.WriteLine("Date: " + mailItem.Date);
            Console.WriteLine(mailItem.Subject);

           // Send out a simple email message
            MailBeeMailMessage msg = new MailBeeMailMessage();
            msg.Subject = "Sending message from EWS";
            msg.BodyPlainText = "Message sent at: " + DateTime.Now.ToString();
            msg.BodyHtmlText = "<html>Message sent at: " + DateTime.Now.ToString() + "</html>";
            msg.To.AddFromString("test@mydomain.com");
            msg.From.AsString = email;
            msg.SetUniqueMessageID(null);
            ewsClient.SendMessage(msg);
        }
    }
}
Using MailBee.NET EWS to access Office 365 mailbox in non-interactive case

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s