I've been struggling for weeks to create a console app to simply grab emails from an inbox and save them to a local text file,
If this is all you need to do then and the Mailboxes are on Office365 then EWS isn't the best method to use I would suggest you use the Graph API instead as EWS is now considered legacy. With the Authentication you need to choose a method to use based on your requirements eg a traditional approach would be ROPC userName and password https://github.com/AzureAD/microsoft-authentication-library-for-dotnet/wiki/Username-Password-Authentication but as the link mentions not recommended. For unattended code usually the best method is https://github.com/AzureAD/microsoft-authentication-library-for-dotnet/wiki/Client-credential-flows (this is the same if you where going to use EWS or Graph to access the Mailbox).
The simplest console app that got the last email from the Inbox and saved it to a file using the Graph SDK https://www.nuget.org/packages/Microsoft.Graph/ and ROPC would look like
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.Graph;
using System.Net;
using System.Net.Http;
namespace TestSimpleGraphApp
{
internal class Program
{
static void Main(string[] args)
{
string fileName = "c:\\temp\\lastEmail.eml";
var clientId = "xxx-bfc5-41c4-94e0-bdb99fb67cb2";
var tenantId = "xxx-65e0-4fc3-b967-b14d5057375b";
var scopes = new[] { "Mail.Read" };
var credential = new NetworkCredential("******@domain.onmicrosoft.com", "xxxx");
var graphClient = new GraphServiceClient(new ConsoleAppAuthenticationProvider(scopes, clientId, tenantId, credential));
//Get the Last Email in the Mailbox
var Messages = graphClient.Me.MailFolders["Inbox"].Messages.Request()
.Top(1).OrderBy("receivedDateTime").GetAsync().GetAwaiter().GetResult();
//Get MIMEcontent from email
var MimeContent = graphClient.Me.Messages[Messages[0].Id].Content.Request()
.GetAsync().GetAwaiter().GetResult();
var fileStream = System.IO.File.Create(fileName);
MimeContent.CopyTo(fileStream);
fileStream.Close();
}
}
public class ConsoleAppAuthenticationProvider : IAuthenticationProvider
{
private readonly Microsoft.Identity.Client.IPublicClientApplication _app;
private readonly IEnumerable<string> _scopes;
private readonly NetworkCredential _networkCredential;
public ConsoleAppAuthenticationProvider(IEnumerable<string> graphScopes, string clientId, string tenantId,NetworkCredential credential)
{
_scopes = graphScopes;
_app = Microsoft.Identity.Client.PublicClientApplicationBuilder
.Create(clientId)
.WithTenantId(tenantId)
.Build();
_networkCredential = credential;
}
public Task AuthenticateRequestAsync(HttpRequestMessage request)
{
var tokenResult = _app.AcquireTokenByUsernamePassword(_scopes,_networkCredential.UserName,_networkCredential.SecurePassword).ExecuteAsync().Result;
request.Headers.Add("Authorization", "Bearer " + tokenResult.AccessToken);
return Task.CompletedTask;
}
}
}
With EWS the link you pointed to was for the WSDL proxy code which doesn't support oAuth at all you an overide it to add in the necessary bearer header https://gist.github.com/gscales/a946025d143436ec64a8cc4cb27693c0. Else most people use the EWS Managed API which does support using oAuth tokens https://github.com/OfficeDev/ews-managed-api but unless you need to support OnPrem mailboxes I would use the Graph.