Search code examples
c#oauth-2.0exchangewebservices

Send & Receive email using EWS rather than IMAP/SMTP


This code works for sending and receiving emails using IMAP and SMTP protocols but I now need to send and receive emails using EWS (Exchange Web Service) protocols just in case someone has disabled IMAP/SMTP services on their account. Can anyone tell me what I must change in order to do that?

using (ImapClient client = new ImapClient())
{
    client.Connect("outlook.office365.com", 993, SecureSocketOptions.Auto);
    SaslMechanism oauth2;

    if (client.AuthenticationMechanisms.Contains("OAUTHBEARER"))
        oauth2 = new SaslMechanismOAuthBearer(this.Identity.Email, this.AccessToken);
    else
        oauth2 = new SaslMechanismOAuth2(this.Identity.Email, this.AccessToken);

    client.Authenticate(oauth2);
    FolderNamespaceCollection namespaces = client.PersonalNamespaces;
    int totalCount = 0;
    IList<IMailFolder> folders = client.GetFolders(client.PersonalNamespaces[0], StatusItems.Unread | StatusItems.Count);
    foreach (IMailFolder folder in folders)
    {
        folder.Open(FolderAccess.ReadOnly);
        totalCount += folder.Search(SearchQuery.NotSeen).Count;
        folder.Close();
    }
    client.Disconnect(true);
}

using (SmtpClient client = new SmtpClient())
{
    client.Connect("smtp-mail.outlook.com", 587, SecureSocketOptions.Auto);
    SaslMechanism oauth2;
        if (client.AuthenticationMechanisms.Contains("OAUTHBEARER"))
        oauth2 = new SaslMechanismOAuthBearer(this.Identity.Email, this.AccessToken);
    else
        oauth2 = new SaslMechanismOAuth2(this.Identity.Email, this.AccessToken);

    client.Authenticate(oauth2);
    using (MimeMessage message = new MimeMessage())
    {
        message.Sender = new MailboxAddress(this.Identity.Email, this.Identity.Email);
        message.From.Add(message.Sender);
        message.To.Add(new MailboxAddress("<Recipient>", "[email protected]"));
        message.Subject = "SMTP OAuth Test";
        TextPart body = new TextPart
        {
            Text = "If this was received then it worked"
        };
        message.Body = body;
        client.Send(message);
    }
    client.Disconnect(true);
}

Solution

  • If the Mailboxes are on Office365 then you probably want to skip EWS and just use the Microsoft Graph (as EWS is starting to be depreciated https://techcommunity.microsoft.com/t5/exchange-team-blog/upcoming-api-deprecations-in-exchange-web-services-for-exchange/ba-p/2813925)

    Changing over if you use the Graph SDK https://learn.microsoft.com/en-us/graph/sdks/sdks-overview is relatively easy eg

    Get Email https://learn.microsoft.com/en-us/graph/api/user-list-messages?view=graph-rest-1.0&tabs=csharp

    Send Email https://learn.microsoft.com/en-us/graph/api/user-sendmail?view=graph-rest-1.0&tabs=csharp

    You can send email as Mime using the Graph SDK if you want to avoid duplication of the existing Mimekit code eg here eg

    var message = new MimeMessage();
    message.From.Add(MailboxAddress.Parse(mailboxName));
    message.To.Add(MailboxAddress.Parse(recipient));
    message.Subject = "How you doin?";
    
    // create our message text, just like before (except don't set it as the message.Body)
    
    var builder = new BodyBuilder();
    
    // Set the plain-text version of the message text
    builder.TextBody = @"Hey Alice"
    
    // In order to reference inline image from the html text, we'll need to add it
    // to builder.LinkedResources and then use its Content-Id value in the img src.
    var image = builder.LinkedResources.Add(inlineImagePath);
    image.ContentId = MimeUtils.GenerateMessageId();
    
    // Set the html version of the message text
    builder.HtmlBody = string.Format(@"<p>Hey Alice,<br>>", image.ContentId);       
    
    // Now we just need to set the message body and we're done
    message.Body = builder.ToMessageBody();
    //End MimeKit Sample
    var stream = new MemoryStream();
    message.WriteTo(stream);
    
    stream.Position = 0;
    StringContent MessagePost = new StringContent(Convert.ToBase64String(stream.ToArray()),Encoding.UTF8, "text/plain");
    
    GraphServiceClient graphServiceClient = new GraphServiceClient(new AuthHelp(redirectUri, scope, mailboxName, clientId));
    var Message = new Message { };
    var sendMailRequest = graphServiceClient.Me.SendMail(Message, null).Request().GetHttpRequestMessage();
    sendMailRequest.Content = MessagePost;
    sendMailRequest.Method = HttpMethod.Post;
    var sendResult = graphServiceClient.HttpProvider.SendAsync(sendMailRequest).Result;