Microsoft.Graph SDK SendMail как пользователь - 400 - Неожиданные исключения или открытые свойства навигации не поддерживаются - PullRequest
0 голосов
/ 19 сентября 2018

Я работаю над приложением, которое должно отправлять уведомления по электронной почте и напоминания пользователям, когда у них есть действия, которые необходимо выполнить.Пользователь отправляет данные, затем приложение уведомляет других пользователей о выполнении действий в определенном порядке (т. Е. Пользователь 1: Задача 1, после завершения Задачи 1, Пользователь 2: Задача 2 и т. Д.) - если пользователю требуется слишком много времени длявыполнить их действие, система будет напоминать им, а затем передать их своему менеджеру (через службу Windows или подобное).Из-за этого я не могу отправлять сообщения от имени текущего вошедшего в систему пользователя - он должен иметь возможность отправлять сообщения самостоятельно.Рекомендуется отправлять сообщения от имени пользователя, отправившего данные, чтобы последующие пользователи могли отвечать непосредственно на них.

Я использую клиентскую библиотеку Microsoft Graph v1.10.0.Выполнение моего кода дает статистическое исключение, в конечном итоге сводящееся к коду 400, коду "generalException", сообщению "Unexpected exception returned from the service.". Я использовал LinqPad для просмотра объектов Graph и попытался воспроизвести вызов в Postman, который выдает 400 ссообщение "Open navigation properties are not supported on OpenTypes. Property name: 'microsoft.graph.sendmail'."

Более подробные сведения:

  • Приложение имеет разрешения Microsoft Graph -> Send mail as any user, Read all groups, Read all users' full profiles.
  • Вызов GraphServiceClient.Client.Users["MyUPN"].SendMail(email, true).Request().PostAsync() дает общее исключение 400 с Unexpected exception returned from the service. (полный код ниже)
  • Глядя на запрос, я обнаружил, что он звонит https://graph.windows.net:443/{{tenantId}}/users/{{MyUPN}}/microsoft.graph.sendMail?api-version=1.6, и попытался сделать такой же вызов черезПочтальон (с действительным токеном), который выдал 400 неверных запросов с сообщением Open navigation properties are not supported on OpenTypes. Property name: 'microsoft.graph.sendMail'.

Полный код:

String MyEmailAddress = "";
String MyUpn = "";
String TenantId = "";
String AppGuid = "";
String AppKey = "";

var sender = new Microsoft.Graph.Recipient()

{
    EmailAddress = new Microsoft.Graph.EmailAddress() { Address = MyEmailAddress }
};
var email = new Microsoft.Graph.Message
{
    Sender = sender,
    From = sender,
    Subject = "Test",
    Body = new Microsoft.Graph.ItemBody()
    {
        Content = "Test Body",
        ContentType = Microsoft.Graph.BodyType.Text
    }
};

email.ToRecipients = new List<Microsoft.Graph.Recipient>(){ sender };

email.BodyPreview = "Test Summary";


GraphSdk _Sdk = new GraphSdk(TenantId, AppGuid, AppKey);

// Where the error throws
await _Sdk.Client.Users[MyUpn].SendMail(email, true).Request().PostAsync();

В качестве теста я также попытался await _Sdk.Client.Users[MyUpn].Messages.Request().Top(20).GetAsync();который дал ту же ошибку.Другие вызовы Graph, такие как получение групп пользователей или менеджера, работают нормально - эта ошибка появляется только при вызовах, связанных с электронной почтой.


Обновление 19.09.2008 AM

Похоже, что я могу заставить работать электронную почту, если я использую сертификат для генерации токена вместо Ключа -> Пароль;и вместо этого вызовите Outlook API.К сожалению, это не работает через GraphServiceClient и Graph API - он может использовать сертификат и использовать базовый URL-адрес API Outlook, но действие microsoft.graph.sendMail в API Outlook является просто sendMail.

Для удобства обслуживания я бы хотел, чтобы все это работало в Graph API, поэтому я все еще ищу ответ на оригинальный вопрос.

Ответы [ 2 ]

0 голосов
/ 20 сентября 2018

Согласно вашему описанию, вы хотите отправить электронное письмо, но получите ошибку 400.

На основании моего теста мы можем использовать следующие шаги для отправки электронного письма.

step1, мыдолжен получить graphClient, который является аутентифицированным HttpClient.

Код, подобный следующему:

GraphServiceClient graphServiceClient = new GraphServiceClient(
            new DelegateAuthenticationProvider(
                async (requestMessage) =>
                {
                    string accessToken = await MsalAuthProvider.Instance.GetUserAccesstokenAsync();
                    requestMessage.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("bearer", accessToken);
                }));
        return graphServiceClient;

Мы можем сослаться на простой код в официальном документе.

step2, мы можем использовать следующий код для отправки почты:

public async Task<bool> SendAsync(EmailAddress toaddress)
    {
        var email = new Message
        {
            Body = new ItemBody
            {
                Content = "Test for sending eamil ",
                ContentType = BodyType.Text,
            },
            Subject = "Test for sending eamil",
            ToRecipients = new List<Recipient>
            {
                new Recipient
                {
                   EmailAddress = toaddress 
                }
            },
        };
        try
        {
            await _serviceClient.Me.SendMail(email).Request().PostAsync(); // the _serviceClient is the result in the step1.
            return true;
        }
        catch (Exception ex)
        {
            return false;
        }
0 голосов
/ 19 сентября 2018

В какой-то момент я установил BaseUrl для клиента на https://graph.windows.net:443/{{tenantId}}, возможно, из-за различий в брендинге за последние несколько лет (Microsoft Graph против Azure Graph).В соответствии с текущими рекомендациями для Microsoft.Graph это должно быть https://graph.microsoft.com/v1.0/ - что также является значением по умолчанию.

Кроме того, мне пришлось переключиться на использование сертификата вместо ключа, сгенерированного Azure -> Парольдля приложения.

Общий рабочий код:

String AADTenantId = "";
String AppGuid = "";
String SenderAddress = "";
String SenderId = "";
String ToAddress = "";
String SubjectText = "";
String BodyText = "";
Byte[] Certificate = ...GetCertBytes...
String CertPassword = "";

var client = new GraphServiceClient(new DelegateAuthenticationProvider(
    async requestMessage =>
    {
        var authContext = new AuthenticationContext($"https://login.microsoftonline.com/{AADTenantId}");
        var cert = new X509Certificate2(Certificate, CertPassword);
        var clientAssertion = new ClientAssertionCertificate(AppGuid, cert);
        AuthenticationResult authresult = await authContext.AcquireTokenAsync("https://graph.microsoft.com", clientAssertion);

        // Append the access token to the request
        requestMessage.Headers.Authorization = new AuthenticationHeaderValue("Bearer", authresult.AccessToken);
    }));

var sender = new Recipient()
{
    EmailAddress = new EmailAddress() { Address = SenderAddress }
};
var email = new Message
{
    Sender = sender,
    From = sender,
    Subject = SubjectText,
    Body = new ItemBody()
    {
        Content = BodyText,
        ContentType = BodyType.Text
    },
    ToRecipients = new List<Recipient>() {
        new Recipient() { EmailAddress = new EmailAddress { Address = ToAddress }}
    }
};

await client.Users[SenderId].SendMail(email, true).Request().PostAsync();
...