0

I've the following class:

using Microsoft.Graph;
using Microsoft.Identity.Client;
using System;
using System.Linq;
using System.Collections.Generic;
using System.Configuration;
using System.Net.Http.Headers;
using System.IO;
using System.Security;
using Azure.Identity;
using System.Threading;
using System.Threading.Tasks;

namespace Helper.Mail
{
    public class GraphMail
    {
        private static GraphServiceClient _userClient;
        private static User _user;

        public GraphMail()
        {
            InitializeGraphForUserAuth((info, cancel) =>
            {
                Console.WriteLine(info.Message);
                return Task.FromResult(0);
            });
        }

        private async static void InitializeGraphForUserAuth(Func<DeviceCodeInfo, 
            CancellationToken, Task> deviceCodePrompt)
       {
           string auth = string.Concat("https://login.microsoftonline.com/", 
               ConfigurationManager.AppSettings["TenantId"]);

           try
           {
                string clientID = ConfigurationManager.AppSettings["ClientId"];
                string clientSecret = ConfigurationManager.AppSettings["ClientSecret"];
                Uri authUri = new Uri(auth);
                IConfidentialClientApplication application = 
                   ConfidentialClientApplicationBuilder.Create(clientID)
                              .WithClientSecret(clientSecret)
                              .WithAuthority(authUri)
                              .Build();
            try
            {
                _userClient = new GraphServiceClient("https://graph.microsoft.com/v1.0",
                    new DelegateAuthenticationProvider(async (requestMessage) =>
                    {
                        AuthenticationResult AuthToken = await 
                            application.AcquireTokenForClient(new string[] { 
                            "https://graph.microsoft.com/.default" }).ExecuteAsync(); 
//Jumps to here and die
                        requestMessage.Headers.Authorization = new 
                            AuthenticationHeaderValue("bearer", AuthToken.AccessToken);
                    }
                    ));
            }
            catch (MsalUiRequiredException ex)
            {
                // The application doesn't have sufficient permissions.
                // - Did you declare enough app permissions during app creation?
                // - Did the tenant admin grant permissions to the application?
                Console.WriteLine("Exception: {0}", ex.Message);
            }
            catch (MsalServiceException ex) when (ex.Message.Contains("AADSTS70011"))
            {
                // Invalid scope. The scope has to be in the form 
"https://resourceurl/.default"
                // Mitigation: Change the scope to be as expected.
                Console.WriteLine("Scope provided is not supported");
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.InnerException);
            }
        }
        catch (FileLoadException ex)
        {
            System.Windows.MessageBox.Show(ex.InnerException.ToString());
        }
        catch (SecurityException ex)
        {
            System.Windows.MessageBox.Show(ex.InnerException.ToString());
        }
        //catch (Exception ex)
        //{
        //    System.Windows.MessageBox.Show(ex.InnerException.ToString());
        //}

    }

    public async void Mail(string mailFrom, string mailTo, string mailSubject, string 
 mailBody, bool withReadReceipt = true)
    {            
        var _userList = await _userClient.Users                
       .Request()
       .Filter($"mail eq '" + mailFrom + "'")
       .Select(e => new
       {
           e.DisplayName,
           e.Mail,
           e.Id
       })
       .GetAsync();

        _user = (User)_userList.FirstOrDefault();         

        var message = new Message
        {
            IsReadReceiptRequested = withReadReceipt,
            IsDeliveryReceiptRequested = withReadReceipt,
            Subject = mailSubject,
            Body = new ItemBody
            {
                ContentType = BodyType.Text,
                Content = mailBody
            },
            ToRecipients = new List<Recipient>()
            {
                new Recipient { EmailAddress = new EmailAddress { Address = mailTo }}
            }
        };

        _userClient
            .Users[_user.Id]
            .SendMail(message, true)
        .Request()
        .PostAsync().Wait();
    }

    public async void ReadAttachments(string mailFrom)
    {
        //try
        //{
            var _userList = await _userClient.Users
           .Request()  // Jumps to line in above code
           .Filter($"mail eq '" + mailFrom + "'")
           .Select(e => new
           {
               e.DisplayName,
               e.Mail,
               e.Id
           })
           .GetAsync();

            _user = (User)_userList.FirstOrDefault();

            IList<Message> messages = await _userClient
                .Users[_user.Id]
                .MailFolders.Inbox
                .Messages
                .Request()
                .Filter($"HasAttachments eq 'true'")
                .Expand($"Attachments")
                .Select(e => new
                {
                    e.Id
                }).GetAsync();

        //}
        //catch(Exception ex)
        //{ 
        //}

        //return new List<FileAttachment>();
    }
}
}

This works for the Mail procedure.

However when trying to do the ReadAttachments procedure it jumps to earlier code and just die. No error.

The MailFrom between the procedures differ, but even when the same it fails.

I know the result now is not very usefull, but I've get to past this error first.

Mail is done from a Windows WPF application, readattachtments is done from a Windows service. Read attachments from Windows application works Mail from windows service has same problem.

Do I need a different Client ID for both apps?

I'm lost how to find out what is going on here, or what to change.

Jeroen

  • Try creating a new app in Azure and use the credentials of that. – Jeroen E Oct 17 '22 at 14:53
  • No luck, same result – JeroenZenM Oct 18 '22 at 11:14
  • I'm finding warnings like this: Severity Code Description Project File Line Suppression State Warning No way to resolve conflict between "System.Net.Http, Version=4.2.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" and "System.Net.Http, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a". Choosing "System.Net.Http, Version=4.2.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" arbitrarily. AfvoerCheckSwissKnifeAppeee-Test Could be a cause, now trying to solve – JeroenZenM Oct 18 '22 at 14:33
  • See https://stackoverflow.com/questions/48866419/found-conflicts-between-system-net-http – Jeroen E Oct 19 '22 at 08:58
  • For getting the access token please check:https://learn.microsoft.com/en-us/graph/auth/auth-concepts#access-tokens – Mehtab Siddique Oct 24 '22 at 08:28
  • Thanks for the input but getting the token is not the problem. One patth works perfectly, other fails. – JeroenZenM Oct 27 '22 at 10:13
  • 1
    I'm currently rebuilding part of the application. So far ir it's looking good. I'm guessing the problem has to do with the port form .net 4.5 to 4.6.2 during development. I found the necessity for the port when installing packages, so some were installed against 4.5. New project(s), default on 4.6.2 – JeroenZenM Oct 27 '22 at 10:14

0 Answers0