9

I have to build a .Net console application that runs on server side as a batch, and sends email to recipients using Office365 and MailKit.

Our company has recently introduced MultiFactor Authentication; I have already rewrite an interactive app that let user to send email using MailKit and MFA, but I am not able to implement the same functionality in an unattended app.

I already register the application on Microsoft Azure, create the Client Secret and implement the following class:

    public class Mailer {
    public async static void Send(string subject, string body) {
        string tenantID = "abcdef";
        string clientId = "ghilmn";
        string clientSecret = "opqrst";
        string appName = "MyApp";

        //clientSecret = Uri.EscapeDataString(clientSecret);
        //clientSecret = Uri.EscapeUriString(clientSecret);

        var MyConfidentialClientApplication = ConfidentialClientApplicationBuilder.Create(clientId)
            .WithClientSecret(clientSecret)
            .WithTenantId(tenantID)
            .Build();

        var scopes = new string[] {"https://graph.microsoft.com/.default"};

        try {
            var authToken = await MyConfidentialClientApplication.AcquireTokenForClient(scopes).ExecuteAsync();

            var oauth2 = new SaslMechanismOAuth2(appName, authToken.AccessToken);  //  SaslMechanismOAuth2(appName, authToken.AccessToken);
            var m_client = new SmtpClient(new ProtocolLogger("smtp.log"));
            await m_client.ConnectAsync("outlook.office365.com", 587, SecureSocketOptions.StartTls);
            await m_client.AuthenticateAsync(oauth2);
        }
        catch (Exception ex) {
            Debug.WriteLine(ex.Message);
            // do nothing;
        }
        return;

    }

While the token seems to be correctly acquired (the authToken.AccessToken is not null), the

await m_client.AuthenticateAsync(oauth2);

generate the following error:

Eccezione generata: 'MailKit.Security.AuthenticationException' in System.Private.CoreLib.dll
535: 5.7.3 Authentication unsuccessful [ZR0P278CA0036.CHEP278.PROD.OUTLOOK.COM]

Basically I don't understand

  • if the SaslMechanismOAuth2 is the correct one to be invoked
  • if yes, what userName shall I pass to the constructor of oauth2; i tried with AppName, AppID and even with user email, but with no success.

Any hint will be appreciated, thanks in advance.

Paolo

P.S. the interactive app that is working uses the PublicClientApplicationBuilder and the AcquireTokenInteractive calls, using the following code.

        public async Task  Connect_MFA() {
        
        var options = new PublicClientApplicationOptions {
            ClientId = "abcd",
            TenantId = "efgh",
            RedirectUri = "https://login.microsoftonline.com/common/oauth2/nativeclient"
        };

        var publicClientApplication = PublicClientApplicationBuilder
            .CreateWithApplicationOptions(options)
            .Build();

        var scopes = new string[] {
            "email",
            "offline_access",
            //"https://outlook.office.com/IMAP.AccessAsUser.All", // Only needed for IMAP
            //"https://outlook.office.com/POP.AccessAsUser.All",  // Only needed for POP
            "https://outlook.office.com/SMTP.Send", // Only needed for SMTP
        };

        var authToken = await publicClientApplication.AcquireTokenInteractive(scopes).ExecuteAsync();

        var oauth2 = new SaslMechanismOAuth2(authToken.Account.Username, authToken.AccessToken);

        m_client = new SmtpClient(new ProtocolLogger("smtp.log"));
        await m_client.ConnectAsync("outlook.office365.com", 587, SecureSocketOptions.StartTls);
        await m_client.AuthenticateAsync(oauth2);
    }
Paolo Ursini
  • 270
  • 1
  • 2
  • 9
  • 1
    SaslMechanismOAuth2 should be the correct SASL mechanism to use. I'm not sure what the userName should be, although I would expect it to be your account name (not the username of the person you are emailing, just in case there was any confusion). That said, you are not the only person having trouble with this but so far afaik, I have not seen a solution to it. It has been suggested that it's possible that this is not supported by Office365. – jstedfast Apr 28 '21 at 20:09
  • Thank you @jstedfast, can you suggest me an alternative way to implement my scenario (i.e., sending email from unattended app using O365 AND MultiFactor Authentication) or a place to get some additional information? Thanks in advance. And thank you for MailKit, great package ;) – Paolo Ursini Apr 29 '21 at 14:01
  • It seems that some users are having success using the Microsoft Graph Mail REST API: https://learn.microsoft.com/en-us/graph/api/resources/mail-api-overview?view=graph-rest-1.0 . Wish I knew how to get this working in MailKit (if it's even possible?). If you ever figure it out, please do let me know so that I can update my docs to explain how to do it. – jstedfast Apr 29 '21 at 14:54

1 Answers1

0

Late response, but I hope this saves someone else the week I spent researching this.

The simplest/best answer is to use Microsoft.Graph. See this: https://learn.microsoft.com/en-us/graph/api/user-sendmail?view=graph-rest-1.0&tabs=csharp

dwneder
  • 19
  • 3
  • While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes. - [From Review](/review/late-answers/32303797) – Jeremy Caney Jul 25 '22 at 01:31
  • 10
    This doesn't answer the question, it recommends using a completely different service/API – CervEd Aug 17 '22 at 13:10
  • I will jump in here. Because this is an ongoing issue. The problem here is, that Microsoft inofficially directs you towards MailKit for implementing Mailing Services. However - only POP3 and IMAP have been properly implemented for the new Modern Authentication. SMTP connections have not yet been implemented (date: 15.3.2023) - and one of the MS developers have said on the 2023 February blog post that they have no date when this is implemented for non-interactive oauth2 service mail accounts. As it currently stands, you will be directed to "just implement it with Microsoft Graph" for now. -.- – beggarboy Mar 15 '23 at 14:11