Пишите эффективные запросы с OutlookServicesClient

Я использую API почты Office 365, и моя цель — получить общее количество сообщений электронной почты, которые пользователь отправил (1.) и получил (2.) сегодня.

Для этого я сначала создал, попробовал и выполнил несколько запросов в Office 365 API Playground:

  1. https://outlook.office.com/api/v2.0/me/mailfolders/sentitems/messages?$filter=sentdatetime%20ge%202015-12-10T08:00:00.000Z&$select=Subject,CreatedDateTime,ToRecipients
  2. https://outlook.office.com/api/v2.0/me/messages?$count=true&$filter=receiveddatetime%20ge%202015-12-09T10:00:00.000Z&$select=Subject,CreatedDateTime,ToRecipients

Теперь я изо всех сил пытаюсь написать эти запросы с помощью API OutlookServicesClient. Я не нашел много примеров, которые выходят за рамки очень простых запросов... Что у меня есть до сих пор:

  1. var mailResults = await client.Me.MailFolders.Where(f => f.DisplayName == "Sent Items").ExecuteAsync(); Это еще не возвращает просто сообщения и не фильтрует их по текущей дате.

  2. var mailResults = await client.Me.Messages.Where(m => m.ReceivedDateTime.Value == date.UtcDateTime).ExecuteAsync(); не возвращает никаких результатов, несмотря на то, что я получил много писем. Кроме того, я хотел бы исключить электронные письма, которые я получил в папках «Кластер», «Удаленные» и «Нежелательная почта».

Как правило, я не уверен, что фильтровать имена папок на английском языке — хорошая идея, так как мне нужно будет изменить код для других языков. Существуют ли специальные идентификаторы для специальных папок Outlook, таких как «Отправленные», «Нежелательная почта», «Кластер» и т. д.?

Кроме того, чтобы решить мои два запроса, я мог бы просто получить все электронные письма и выполнить фильтрацию самостоятельно, но это неэффективно, и API уже поддерживает фильтрацию (как видно из необработанных запросов), я просто не знаю, как писать их с помощью API OutlookServicesClient.


person casaout    schedule 10.12.2015    source источник


Ответы (1)


Обычно OutlookServicesClient использует LINQ для построения своих запросов, поэтому вам нужно будет использовать метод Where для создания параметра запроса $filter. Например, если вы хотите получить все сообщения, полученные сегодня, вы должны сделать что-то вроде:

DateTimeOffset startOfDay = DateTimeOffset.Now.Date.ToUniversalTime();

client.Me.Messages.Where(m => m.ReceivedDateTime >= startOfDay).ExecuteAsync();

По вашим вопросам:

  1. Не фильтровать по имени папки. API имеет постоянные идентификаторы папок для папки «Входящие», «Удаленные», «Отправленные» и «Черновики». Итак, чтобы получить папку «Отправленные», вы должны сделать:

    client.Me.MailFolders.GetById("SentItems")
    
  2. Ваш запрос Where(m => m.ReceivedDateTime.Value == date.UtcDateTime) не вернет значения, потому что вы проверяете, что значение даты и времени равно константе, которая практически никогда не вернет результат. Сравнение идет до уровня секунд, поэтому, если у вас нет сообщений, полученных точно в дату и время в вашей переменной date, вы не получите совпадений.

Я написал несколько запросов, которые, как мне кажется, соответствуют вашим намерениям:

DateTimeOffset startOfDay = DateTimeOffset.Now.Date.ToUniversalTime();

var receivedMessages = await client.Me.Messages
  // $orderby=ReceivedDateTime desc
  .OrderByDescending(m => m.ReceivedDateTime)
  // $filter=ReceivedDateTime ge 2015-12-11T05:00:00Z
  .Where(m => m.ReceivedDateTime >= startOfDay)
  // $top=10
  .Take(10)
  // $select=Subject,ReceivedDateTime,From
  .Select(m => new { m.Subject, m.ReceivedDateTime, m.From })
  .ExecuteAsync();

string resultMessage = "";
foreach (var message in receivedMessages.CurrentPage)
{
  resultMessage += "Received: " + message.ReceivedDateTime.ToString() + " from " + message.From.EmailAddress.Address
                   + ": " + message.Subject + "\n";
}

MessageBox.Show(resultMessage, "Received messages");

var sentMessages = await client.Me.MailFolders.GetById("SentItems").Messages
  // $orderby=SentDateTime desc
  .OrderByDescending(m => m.SentDateTime)
  // $filter=SentDateTime ge 2015-12-11T05:00:00Z
  .Where(m => m.SentDateTime >= startOfDay)
  // $top=10
  .Take(10)
  // $select=Subject,ReceivedDateTime,From
  .Select(m => new { m.Subject, m.SentDateTime, m.ToRecipients })
  .ExecuteAsync();

resultMessage = "";
foreach (var message in sentMessages.CurrentPage)
{
  resultMessage += "Sent: " + message.SentDateTime.ToString() + " to " + message.ToRecipients.Count
                 + " recipients: " + message.Subject + "\n";
}

MessageBox.Show(resultMessage, "Sent messages");
person Jason Johnston    schedule 11.12.2015
comment
Потрясающе, спасибо большое, Джейсон! Я не знал о методе GetById(..) и дата была глупой ошибкой с моей стороны. Можно ли также просто запустить подсчет (т.е. # сообщений в папке «Входящие»)? И если я хочу получить количество всех сообщений, отправленных за день, я могу изменить метод Take на 10000 или что-то в этом роде. Есть ли более эффективный/быстрый способ сделать это? (Я также заметил, что максимум может быть 500 на странице?) Еще раз спасибо! - person casaout; 11.12.2015
comment
Я не уверен, что вы можете сделать отфильтрованный подсчет в библиотеке .NET. Существует метод CountAsync вне client.Me.Messages, но он не применяется, когда вы начинаете добавлять Where или Select или что-то в этом роде. Я свяжусь с разработчиками и посмотрю, не упустил ли я что-то очевидное. - person Jason Johnston; 11.12.2015
comment
У меня тоже были такие же выводы. Спасибо за проверку! - person casaout; 12.12.2015
comment
Без проблем. Я только что проверил, и это невозможно с библиотекой в ​​​​нынешнем виде. Таким образом, вы хотели бы реализовать пейджинг и сделать это, чтобы убедиться, что вы получите все результаты. - person Jason Johnston; 12.12.2015
comment
Спасибо за проверку! Я это сделаю. Вы знаете, есть ли это в дорожной карте? Является ли 500 максимальным количеством элементов, которые я могу получить на одной странице (с Take(500)? Или вы бы предложили мне использовать значение по умолчанию (10)? - person casaout; 12.12.2015
comment
привет @Jason Johnston Я только что понял, что полученные сообщения также содержат отправленные мной электронные письма, хотя мы сверяемся с REceivedDateTime. У вас есть идея, почему это так и как я могу это исправить? Спасибо! - person casaout; 03.01.2017
comment
.Me.Messages получает доступ ко всем вашим папкам, включая "Отправленные". Вместо этого извлеките из нужной папки. - person Jason Johnston; 03.01.2017
comment
Спасибо Джейсон! Поскольку я хочу получить «все» полученные электронные письма, сейчас я просматриваю Me.Messages и вычитаю отправленные электронные письма и электронные письма в папке черновиков / нежелательной почты / корзины :) - person casaout; 03.01.2017