Как читать почтовые ящики Outlook.com из WinForms?

СЦЕНАРИЙ


Я хотел бы разработать очень простое приложение, написанное на C # или Vb.Net с использованием технологии WinForms . Это поможет мне автоматизировать простую задачу, состоящую в доступе к моей учетной записи Outlook.com, чтобы прочитать мои письма, полученные от Youtube, затем извлеките видео URL.

ПРОБЛЕМА


Мои знания, связанные с сетью, не очень хорошие, я застрял в самом важном пункте, пытаясь найти самый простой способ выполнить эту задачу (я имею в виду официальные API-интерфейсы Microsoft для API .Net или сторонних API или другой способ сделать это), пытаясь применить требуемую авторизованную авторизацию OAuth2 для доступа к учетной записи электронной почты.

Я знаю, что следующий код не сфокусирован в правильном направлении, потому что отсутствие авторизации, но я не знаю, как реализовать это, как не читать электронные письма, так что это то, что я пробовал:

string url = "https://outlook.office.com/api/v2.0/me/messages"; string result = ""; HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url); req.Method = "GET"; try { using (WebClient wc = new WebClient()) { wc.Encoding = Encoding.UTF8; result = wc.DownloadString(url); } } catch (Exception ex) { MessageBox.Show(ex.Message); } 

ВОПРОС


Как я мог получить доступ к моей учетной записи Outlook.com, чтобы прочитать заголовок и содержимое сообщений электронной почты, которые у меня есть ?. И, кроме того, но необязательно отвечать (только если это возможно и не слишком много спрашивает), как я могу удалить электронное письмо ?.

Обратите внимание, что этот вопрос относится к онлайн-сервису Outlook.com , а не к настольному клиенту Outlook не к использованию их COM- библиотек или Office365 .

ОТВЕТНЫЕ РЕВИЗИОНЫ


Я знаю, что я никого не прошу о помощи и не помещаю некоторые реквизиты, вся моя помощь ценится для меня, но на этот раз мне нужно поставить специальный реквизит, потому что моя голова сошла с ума, пытаясь понять, использовать и адаптировать OAuth2 решения, созданные с нуля, генерируют очень длинные коды, которые я вообще не понимаю, это слишком много для меня.

По этой причине я приму ответ в этом вопросе только в том случае, если предоставленное решение основано на использовании библиотеки третьего pary, которая облегчит всю эту задачу, поскольку она будет служить полной абстракцией реализации OAuth2 , такой как RestSharp , CodeScales или DotNetOpenAuth , или любой другой (бесплатный) lib, который будет обрабатывать нужные мне вещи, вместо того, чтобы самостоятельно разрабатывать алгоритмы OAuth2 с нуля.

ИССЛЕДОВАНИЕ


Мое расследование начало читать этот Microsoft Outlook. страницу, следуя этой ссылке API-интерфейса Mail API, эту документацию API REST, этот API Outlook.com, такую начальную статью и заканчивая этим полностью иллюстративным примером с использованием ASP.Net.

То, что я понял из статей Microsoft, просто … ничего из ничего, я зарегистрировал приложение и создал идентификатор клиента и секрет, но Microsoft не предоставляет никаких примеров для Winforms, поэтому я попытался перевести их официальный Пример ASP.NET для WinForms без успеха.

После этой траты времени я нашел эту страницу документации OAuth, которая предоставляет некоторые библиотеки для .NET, которые, как мне кажется, облегчат авторизацию OAuth2, тогда я обнаружил библиотеку DotNetOpenAuth, которая кажется очень полной, а также я нашел этот пример кода для Outlook с помощью DotNetOpenAuth но опять же это для ASP.NET , а также эти общие и официальные образцы кода DotNetOpenAuth, но я не могу найти ничего, что могло бы помочь мне в том, что я хочу делать.

Общая идея заключается в следующем: ознакомьтесь с API-интерфейсами REST API, календарей и контактов, но я попытаюсь упростить его и продемонстрировать с помощью образца Winforms.

Зарегистрировать приложение

Во-первых, вам необходимо создать и зарегистрировать приложение на портале регистрации приложений (вам нужно только сделать это один раз для конкретного приложения):

  1. создать приложение
  2. сгенерировать новый пароль
  3. добавьте платформу и выберите мобильный («мобильный» здесь означает «любое устройство» или «не для браузера» …)
  4. не забудьте нажать на сохранение!

Аутентификация

Теперь, в вашем коде «любого устройства» (включая winforms), вам нужно пройти аутентификацию. Самый простой способ – использовать ADAL («Библиотека проверки подлинности Active Directory»). Источник доступен здесь https://github.com/AzureAD/azure-activedirectory-library-for-dotnet, а двоичный файл доступен как nuget.

К сожалению, последняя версия, которую вы можете получить на nuget сегодня с именем Microsoft.IdentityModel.Clients.ActiveDirectory не работает для меня (у нее была ошибка, о которой я сообщил здесь https://github.com/AzureAD/azure-activedirectory-library -for-dotnet / issues / 412, который уже исправлен, но теперь сервер жалуется на несовместимость некоторых приложений и серверов).

Поэтому вы должны использовать старый «Экспериментальный» (помните об этом, как когда-нибудь в будущем, нам придется переключиться): Microsoft.Experimental.IdentityModel.Clients.ActiveDirectory

Вы хотите убедиться, что используете нужные области, когда приобретаете токен аутентификации. Области определяются здесь: области почты Outlook, календарь и контакты и представляют собой область разрешения. Без указания области действия вы можете ничего не делать, кроме аутентификации.

Итак, если вы хотите читать письма, используйте область « https://outlook.office.com/mail.read ».

Когда вы попробуете приложение, после диалога проверки подлинности он должен отобразить пользователю экран согласия (здесь мы видим, что мы попросили почтовый ящик: «Прочитайте свою почту»):

введите описание изображения здесь

API Office / Outlook / OData

После того, как аутентификация работает, вы можете использовать REST api напрямую, что не так просто, или быть ленивым и использовать другой пакет: Microsoft.Office365.OutlookServices-V2.0 , который сделает все, что подходит для REST / OData magic. Хорошая новость заключается в том, что этот API вполне закончен, поэтому он должен позволять вам делать другие вещи, такие как создание сообщений, удаление и т. Д.

Существует важное замечание для случая outlook.com: не все учетные записи включены для всего этого REST API (см. Главу «Доступность REST API» здесь: Почта Outlook ), поэтому вам может понадобиться создать новую для тестирования.

Вот код winforms для примера приложения, которое будет запрашивать 10 сообщений и добавлять их в список.

 using System; using System.Threading.Tasks; using System.Windows.Forms; using Microsoft.Experimental.IdentityModel.Clients.ActiveDirectory; using Microsoft.Office365.OutlookServices; namespace WindowsFormsApplication1 { public partial class Form1 : Form { private const string authority = "https://login.microsoftonline.com/common"; private const string clientId = "blablabl-abla-blab-abla-blablablab"; // TODO: put your application id here private const string redirectUri = "urn:ietf:wg:oauth:2.0:oob"; // put your redirect uri here (should be the same) // we cache the token for the duration of this form // you could/should use the FileCache class provided in the sample here https://dev.outlook.com/restapi/tutorial/dotnet private TokenCache _cache = new TokenCache(); public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { // since all packages force async, // we have to avoid threading issues BeginInvoke((Action)(() => GetMessages())); } private async void GetMessages() { // use the Microsoft.Experimental.IdentityModel.Clients.ActiveDirectory nuget package for auth var authContext = new AuthenticationContext(authority, _cache); var result = await authContext.AcquireTokenAsync( new[] { "https://outlook.office.com/mail.read" }, null, clientId, new Uri(redirectUri), new PlatformParameters(PromptBehavior.Always, this)); // use the Microsoft.Office365.OutlookServices-V2.0 nuget package from now on var client = new OutlookServicesClient(new Uri("https://outlook.office.com/api/v2.0"), () => Task.FromResult(result.Token)); var messages = await client.Me.Messages .Take(10) // get only 10 messages .ExecuteAsync(); // fill some list box // (beware, some messages have a null subject) foreach (var msg in messages.CurrentPage) { listBox1.Items.Add(msg.Subject); } } } } 

Я просто хотел бы поделиться (почти) окончательным решением, я немного расширил решение, предоставленное @ Simon Mourier , для повторения всех электронных писем определенной папки и, если письмо от Youtube, отмените URL-адреса внутри, затем повторите отправку электронной почты.

Когда применять это ?, ну, просто адаптируйте его для любого случая, когда вам нужно разобрать электронные письма, мой случай очень специфичен, у меня около 500 подписчиков на каналы, поэтому я собираю около 200 emais из Youtube через месяц, большая часть письма из музыкальных каналов, которые я только что прочитал, чтобы скопировать URL-адрес, чтобы загрузить его с помощью JDownloader, так что это полезно как savetimer, потому что он выполнит всю задачу для меня.

 Private Const Authority As String = "https://login.microsoftonline.com/common" Private Const ClientId As String = "OUR API ID" ' Put your redirect uri here (should be the same). Private Const RedirectUri As String = "urn:ietf:wg:oauth:2.0:oob" ' We cache the token for the duration of this Form. ' You could/should use the FileCache class provided in the sample here: ' https://dev.outlook.com/restapi/tutorial/dotnet Private cache As New TokenCache() Private Sub Form1_Shown() Handles MyBase.Shown ' Since all packages force async, we have to avoid threading issues. Me.BeginInvoke(Sub() GetMessages()) End Sub Private Async Sub GetMessages() ' Use the 'Microsoft.Experimental.IdentityModel.Clients.ActiveDirectory' Nuget package for auth. Dim authContext As New AuthenticationContext(Authority, cache) Dim result As AuthenticationResult = Await authContext.AcquireTokenAsync({"https://outlook.office.com/mail.readwrite"}, Nothing, ClientId, New Uri(RedirectUri), New PlatformParameters(PromptBehavior.Auto, Me)) ' Use the 'Microsoft.Office365.OutlookServices-V2.0' Nuget package from now on. Dim client As New OutlookServicesClient(New Uri("https://outlook.office.com/api/v2.0"), Function() Task.FromResult(result.Token)) ' I have a rule set to automatically move all emails received from Youtube to a folder with name "Youtube". Dim folder As IMailFolder = Await client.[Me].MailFolders.Where(Function(f As IMailFolder) f.DisplayName = "Youtube").ExecuteSingleAsync() Dim messages As IPagedCollection(Of IMessage) = Await client.[Me].MailFolders.GetById(folder.Id).Messages.ExecuteAsync() Do While True Me.ParseYoutubeMessages(messages.CurrentPage) If messages.MorePagesAvailable Then messages = Await messages.GetNextPageAsync Else Exit Do End If Loop End Sub Private Async Sub ParseYoutubeMessages(ByVal messageList As IReadOnlyList(Of IMessage)) Dim urlRegex As New Regex("""http://www.youtube.com/.+watch.+uploademail""", RegexOptions.IgnoreCase) For Each msg As IMessage In messageList If (msg.From.EmailAddress.Name.Equals("YouTube", StringComparison.OrdinalIgnoreCase)) Then Dim body As String = msg.Body.Content Dim isMatch As Boolean = urlRegex.IsMatch(body) If Not (isMatch) Then Throw New InvalidOperationException("Youtube url regex doesn't match.") Else Dim urlMatches As MatchCollection = urlRegex.Matches(body) Dim urls As String() = (From m As Match In urlMatches.Cast(Of Match) Select Environment.NewLine & m.Value).Distinct().ToArray() File.AppendAllText("C:\Youtube Urls.txt", String.Join("", urls)) msg.IsRead = True Await msg.MoveAsync("DeletedItems") End If End If Next msg End Sub 

Обновление для 2018 года – теперь API-интерфейс Microsoft Graph имеет контроль над предоставлением доступа к объектам в мире 365, включая электронную почту. См. Эту ссылку для 4-шагового обзора: https://developer.microsoft.com/en-us/graph/docs/concepts/auth_v2_user