Authenticate the SmtpClient using AppID and APPSecret instead of passing the username and password

Viewed 722

I have the following SharePoint CSOM code inside my c# console application to send an email using the office 365 admin username and password :-

 static private void sendemail(ClientContext context, string subject, string body, FieldUserValue[] to, string username, SecureString passWord)
        {

            try
            {
                using (MailMessage mail = new MailMessage())
                {

                    mail.From = new MailAddress("sharepoint@***.com");
                    mail.Subject = subject;
                    mail.IsBodyHtml = true;
                    SmtpClient client = new SmtpClient("***-com.mail.protection.outlook.com", 25);
                    client.DeliveryMethod = SmtpDeliveryMethod.Network;
                    client.UseDefaultCredentials = false;
                    client.Credentials = new NetworkCredential(username, passWord);
                    client.EnableSsl = true;
                    mail.Body = body;
                    string approvalemailTo = "";

                    foreach (var t in to)
                    {
                        mail.To.Add(t.Email);
                        approvalemailTo = approvalemailTo + t.Email + ";";
                    }
                    client.Send(mail);
                    }
            }


            catch (Exception e)
            {

                   

            }

        }

but to make my code more secure, how i can authenticate the SmtpClient using AppID and APPSecret instead of passing the username and password?

Thanks

1 Answers

Your code is just standard SMTP code from the System.net.mail assembly it has no dependencies on the Sharepoint CSOM. If you want use Modern Auth in SMTP you can't do that using the client credentials flow https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-client-creds-grant-flow as per

This feature announcement is for interactive applications to enable OAuth for IMAP and SMTP. At this time, there are no plans to enable IMAP and SMTP OAuth for non-interactive applications using client credentials flow. For that, we suggest to use our Graph API.

https://techcommunity.microsoft.com/t5/exchange-team-blog/announcing-oauth-2-0-support-for-imap-and-smtp-auth-protocols-in/ba-p/1330432

You need to use Microsoft Graph API if you want to do that which would be pretty simple for you to migrate to. If you want to stick with SMTP and use Modern Auth you will need to look at using something like MailKit https://github.com/jstedfast/MailKit which supports it eg a simple sample using MSAL and Interactive Auth

        String ClientId = "20773535-6b8f-4f3d-8f0e-4b7710d79afe";
        string UserName = "user@domain.com";
        string scope = "https://outlook.office.com/SMTP.Send";
        string redirectUri = "msal20773535-6b8f-4f3d-8f0e-4b7710d79afe://auth";
        string From = "Fromouser@domain.com;
        String To = "Touser@domain.com";
        String SMTPServer = "smtp.office365.com";
        Int32 SMTPPort = 587;

        PublicClientApplicationBuilder pcaConfig = PublicClientApplicationBuilder.Create(ClientId)
         .WithAuthority(AadAuthorityAudience.AzureAdMultipleOrgs);

        pcaConfig.WithRedirectUri(redirectUri);
        var TokenResult = await pcaConfig.Build().AcquireTokenInteractive(new[] { scope })
         .WithPrompt(Prompt.Never)
         .WithLoginHint(UserName).ExecuteAsync();


        var message = new MimeMessage();
        message.From.Add(MailboxAddress.Parse(From));
        message.To.Add(MailboxAddress.Parse(To));
        message.Subject = "Test";
        message.Body = new TextPart("plain")
        {
            Text = @"Hey Joe"
        };
        using (var client = new SmtpClient())
        {
            client.Connect(SMTPServer, SMTPPort, SecureSocketOptions.StartTls);
            var oauth2 = new SaslMechanismOAuth2(UserName, TokenResult.AccessToken);
            client.Authenticate(oauth2);

            await client.SendAsync(message);
            client.Disconnect(true);
        }
Related