Using Oauth2 to send email via Office365 C#
Asked Answered
R

3

7

I'm trying to send email in c# using Oauth2 with an office 365 account.

Currently I am able to get the token but not sure how I'm able to use that token and send the email.

System.Net.Mail does not support OAuth or OAuth2.

I've seen Mailkit but the samples are all for google mail and didn't see one for office 365 so I'm not really sure where to start.

Raceme answered 12/11, 2020 at 15:17 Comment(0)
R
7

The documentation for OAuth2 authentication using MailKit with Office365 can be found here: https://github.com/jstedfast/MailKit/blob/master/ExchangeOAuth2.md

var options = new PublicClientApplicationOptions {
    ClientId = "Application (client) ID",
    TenantId = "Directory (tenant) ID",
    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);

using (var client = new ImapClient ()) {
    await client.ConnectAsync ("outlook.office365.com", 993, SecureSocketOptions.SslOnConnect);
    await client.AuthenticateAsync (oauth2);
    await client.DisconnectAsync (true);
}
Romberg answered 13/11, 2020 at 15:24 Comment(5)
Is it true thatMailkit doesn't support Oauth with 'ConfidentialClient` ?Mccutchen
MailKit has no such limitation. If CredentialClient doesn't work, then it's a limitation with the server.Romberg
Getting error on publicClientApplication.AcquireTokenInteractive(scopes).ExecuteAsync();. Microsoft.Identity.Client.MsalClientException: 'Only loopback redirect uri is supported, but login.microsoftonline.com/common/oauth2/nativeclient was found. Configure localhost or localhost:port both during app registration and when you create the PublicClientApplication object. See aka.ms/msal-net-os-browser for details'. I tried with localhost as well then getting another error - having trouble to signing In.Akkad
Are you writing an ASP.NET app?Romberg
yes. Its my consoleApp in .Net. I am Getting Token now after change in AppRegistration. Now not getting authToke.Account.UserName. I am following your sample code .new SaslMechanismOAuthBearer(authToken.Account.UserName, authToken.AccessToken);Akkad
M
4

Setup app using this.

   namespace SendEmailWithMicrosoftGraph
    {
        class Program
        {
            static async Task Main(string[] args)
            {
                // Set up the Microsoft Graph API endpoint and version
                string graphApiEndpoint = "https://graph.microsoft.com/v1.0";
    
                // Set up the client application ID and secret
                string clientId = "<clientId>";
                string clientSecret = "<clientSecret>";
                string tenantId = "<tenentId>";
    
                // Set up the user's email address and message content
                string userEmail = "<userEmail>";
                string messageSubject = "Test email";
                string messageBody = "This is a test email sent via Microsoft Graph";
    
                // Set up the authentication context and acquire a token
                var authBuilder = ConfidentialClientApplicationBuilder.Create(clientId)
                    .WithAuthority($"https://login.microsoftonline.com/{tenantId}/v2.0")
                    .WithClientSecret(clientSecret)
                    .Build();
    
                var authResult = await authBuilder.AcquireTokenForClient(new[] { "https://graph.microsoft.com/.default" })
                    .ExecuteAsync();
    
                // Set up the HTTP client and add the access token to the authorization header
                var httpClient = new HttpClient();
                httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", authResult.AccessToken);
    
                // Set up the email message
                var emailMessage = new
                {
                    message = new
                    {
                        subject = messageSubject,
                        body = new
                        {
                            contentType = "Text",
                            content = messageBody
                        },
                        toRecipients = new[]
                        {
                            new
                            {
                                emailAddress = new
                                {
                                    address = userEmail
                                }
                            }
                        }
                    }
                };
    
                // Convert the email message to a JSON string and send the email via Microsoft Graph
                var jsonMessage = JsonConvert.SerializeObject(emailMessage);
                var response = await httpClient.PostAsync($"{graphApiEndpoint}/users/{userEmail}/sendMail", new StringContent(jsonMessage, System.Text.Encoding.UTF8, "application/json"));
    
                if (response.IsSuccessStatusCode)
                {
                    Console.WriteLine("Email sent successfully.");
                }
                else
                {
                    Console.WriteLine("Failed to send email. Status code: " + response.StatusCode);
                }
            }
        }
    }
Message answered 18/2, 2023 at 5:31 Comment(0)
Z
2

You can use the EWS managed api by creating an OAuthCredentials object using the OAuth token and then setting the credentials and endpoint on an ExchangeService object. You can then use the ExchangeService object to create and send the email.

var credentials = new OAuthCredentials(token);
var ews = new ExchangeService();
ews.Credentials = credentials;
ews.Url = endpointUrl;

var email = new EmailMessage(ews);
...

email.Send();

https://learn.microsoft.com/en-us/exchange/client-developer/web-service-reference/ews-managed-api-reference-for-exchange

The go forward method would be Microsoft Graph, but I'm not as familiar with it. https://learn.microsoft.com/en-us/graph/api/resources/mail-api-overview?view=graph-rest-1.0

Zinck answered 12/11, 2020 at 15:40 Comment(2)
sorry, what would be the value for the endpointUrl?Raceme
nevermind! found the answer I was looking for quicklaunch.ucworkspace.com/support/solutions/articles/…Raceme

© 2022 - 2024 — McMap. All rights reserved.