在C#中阅读MS Exchange电子邮件

我需要能够监视和阅读MS Exchange Server上的特定邮箱(公司内部)的电子邮件。 我还需要能够阅读发件人的电子邮件地址,主题,邮件正文并下载附件(如果有的话)。

用C#(或Vb.net)做这件事的最好方法是什么?

一团糟。 MAPI或CDO通过.NET互操作DLL 正式不被Microsoft支持 – 它看起来工作正常,但由于内存模型不同,存在内存泄漏问题。 您可以使用CDOEX,但只能在Exchange服务器上运行,而不能远程运行。 无用。 你可以与Outlook进行互操作,但是现在你只是依赖于Outlook; 矫枉过正。 最后,您可以使用Exchange 2003的WebDAV支持 ,但WebDAV比较复杂,.NET内置的支持较差,并且(增加了伤害),Exchange 2007 几乎完全丢弃了 WebDAV支持。

什么是一个人要做的? 我最终使用了AfterLogic的IMAP组件来通过IMAP与我的Exchange 2003服务器进行通信,并且最终运行得非常好。 (我通常在寻找免费或开源的库,但是我发现所有的.NET都需要 – 特别是当涉及到2003年IMAP实现的一些怪癖 – 而且这个库很便宜,并且在第一个试试,我知道那里还有其他人。)

但是,如果您的组织位于Exchange 2007上,那么您很幸运。 Exchange 2007随附了一个基于SOAP的Web服务接口 ,最终提供了与Exchange服务器交互的统一的,语言无关的方式。 如果你可以做出2007+的要求,那肯定是要走的路。 (可惜对我来说,我的公司有一个“但是2003年不坏”的政策。)

如果您需要桥接Exchange 2003和2007,则IMAP或POP3绝对是您的select。

嗯,

我可能在这里有点晚了,但这不是EWS的意义吗?

https://msdn.microsoft.com/en-us/library/dd633710(EXCHG.80).aspx

需要大约6行代码才能从邮箱中获取邮件:

ExchangeService service = new ExchangeService(ExchangeVersion.Exchange2007_SP1); //service.Credentials = new NetworkCredential( "{Active Directory ID}", "{Password}", "{Domain Name}" ); service.AutodiscoverUrl( "First.Last@MyCompany.com" ); FindItemsResults<Item> findResults = service.FindItems( WellKnownFolderName.Inbox, new ItemView( 10 ) ); foreach ( Item item in findResults.Items ) { Console.WriteLine( item.Subject ); } 
  1. 目前首选的(Exchange 2013和2016)API是EWS 。 它纯粹是基于HTTP的,可以从任何语言访问,但是.Net和Java特定的库。

    你可以使用EWSEditor来玩API。

  2. 扩展MAPI 。 这是Outlook使用的本机API。 它最终使用MSEMS Exchange MAPI提供程序,该提供程序可以使用RPC(Exchange 2013不再支持它)或RPC-over-HTTP(Exchange 2007或更新版本)或MAPI-over-HTTP(Exchange 2013和更新版本)与Exchange交谈。

    API本身只能从非托pipe的C ++或Delphi访问。 您也可以使用Redemption (任何语言) – 它的RDO系列对象是一个扩展的MAPI包装器。 要使用扩展MAPI,您需要安装Outlook或独立(Exchange)版本的MAPI (在扩展支持上,并且不支持Unicode PST和MSG文件,并且无法访问Exchange 2016)。 扩展MAPI可用于服务。

    您可以使用OutlookSpy或MFCMAPI使用API​​进行游戏。

  3. Outlook对象模型 – 不是Exchange特有的,但它允许访问运行代码的机器上Outlook中可用的所有数据。 不能在服务中使用。

  4. Exchange Active Sync 。 微软不再投入任何重要的资源到这个协议。

  5. Outlook用于安装CDO 1.21库(它包装扩展MAPI),但它已被Microsoft弃用,不再收到任何更新。

  6. 曾经有一个称为MAPI33的第三方.Net MAPI包装,但不再被开发或支持。

  7. WebDAV – 已弃用。

  8. 协作数据对象for Exchange(CDOEX) – 不build议使用。

  9. Exchange OLE DB提供程序(EXOLEDB) – 不build议使用。

这里有一些旧的代码,我已经做了WebDAV的铺设。 我认为它是针对Exchange 2003编写的,但我不记得了。 随意借用,如果它的帮助…

 class MailUtil { private CredentialCache creds = new CredentialCache(); public MailUtil() { // set up webdav connection to exchange this.creds = new CredentialCache(); this.creds.Add(new Uri("http://mail.domain.com/Exchange/me@domain.com/Inbox/"), "Basic", new NetworkCredential("myUserName", "myPassword", "WINDOWSDOMAIN")); } /// <summary> /// Gets all unread emails in a user's Inbox /// </summary> /// <returns>A list of unread mail messages</returns> public List<model.Mail> GetUnreadMail() { List<model.Mail> unreadMail = new List<model.Mail>(); string reqStr = @"<?xml version=""1.0""?> <g:searchrequest xmlns:g=""DAV:""> <g:sql> SELECT ""urn:schemas:mailheader:from"", ""urn:schemas:httpmail:textdescription"" FROM ""http://mail.domain.com/Exchange/me@domain.com/Inbox/"" WHERE ""urn:schemas:httpmail:read"" = FALSE AND ""urn:schemas:httpmail:subject"" = 'tbintg' AND ""DAV:contentclass"" = 'urn:content-classes:message' </g:sql> </g:searchrequest>"; byte[] reqBytes = Encoding.UTF8.GetBytes(reqStr); // set up web request HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create("http://mail.domain.com/Exchange/me@domain.com/Inbox/"); request.Credentials = this.creds; request.Method = "SEARCH"; request.ContentLength = reqBytes.Length; request.ContentType = "text/xml"; request.Timeout = 300000; using (Stream requestStream = request.GetRequestStream()) { try { requestStream.Write(reqBytes, 0, reqBytes.Length); } catch { } finally { requestStream.Close(); } } HttpWebResponse response = (HttpWebResponse)request.GetResponse(); using (Stream responseStream = response.GetResponseStream()) { try { XmlDocument document = new XmlDocument(); document.Load(responseStream); // set up namespaces XmlNamespaceManager nsmgr = new XmlNamespaceManager(document.NameTable); nsmgr.AddNamespace("a", "DAV:"); nsmgr.AddNamespace("b", "urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/"); nsmgr.AddNamespace("c", "xml:"); nsmgr.AddNamespace("d", "urn:schemas:mailheader:"); nsmgr.AddNamespace("e", "urn:schemas:httpmail:"); // Load each response (each mail item) into an object XmlNodeList responseNodes = document.GetElementsByTagName("a:response"); foreach (XmlNode responseNode in responseNodes) { // get the <propstat> node that contains valid HTTP responses XmlNode uriNode = responseNode.SelectSingleNode("child::a:href", nsmgr); XmlNode propstatNode = responseNode.SelectSingleNode("descendant::a:propstat[a:status='HTTP/1.1 200 OK']", nsmgr); if (propstatNode != null) { // read properties of this response, and load into a data object XmlNode fromNode = propstatNode.SelectSingleNode("descendant::d:from", nsmgr); XmlNode descNode = propstatNode.SelectSingleNode("descendant::e:textdescription", nsmgr); // make new data object model.Mail mail = new model.Mail(); if (uriNode != null) mail.Uri = uriNode.InnerText; if (fromNode != null) mail.From = fromNode.InnerText; if (descNode != null) mail.Body = descNode.InnerText; unreadMail.Add(mail); } } } catch (Exception e) { string msg = e.Message; } finally { responseStream.Close(); } } return unreadMail; } } 

和model.Mail:

 class Mail { private string uri; private string from; private string body; public string Uri { get { return this.uri; } set { this.uri = value; } } public string From { get { return this.from; } set { this.from = value; } } public string Body { get { return this.body; } set { this.body = value; } } } 

我使用CodeProject.com上发布的代码 。 如果你想使用POP3,这是我find的更好的解决scheme之一。

如果您的Exchange服务器configuration为支持POP或IMAP,那么这是一个简单的方法。

另一种select是WebDAV访问。 有一个图书馆可用于此。 这可能是你最好的select。

我认为有select使用COM对象来访问Exchange,但我不知道它是多么容易。

这一切都取决于你的pipe理员愿意给你什么访问我猜。

您应该能够使用MAPI访问邮箱并获取所需的信息。 不幸的是,我所知道的唯一一个.NET MAPI库(MAPI33)似乎没有维护。 这曾经是通过.NET访问MAPI的好方法,但现在我不能说它的有效性。 有关于在哪里可以得到它的更多信息: 下载MAPI33.dll的位置?

我有一个解决scheme,最后使用Redemption工作,看看这些问题…

  • 使用兑换…

  • 在64位机器上使用Redemption

一种select是使用Outlook。 我们有一个邮件pipe理器应用程序访问交换服务器,并使用Outlook作为接口。 它肮脏,但它的作品。

示例代码:

 public Outlook.MAPIFolder getInbox() { mailSession = new Outlook.Application(); mailNamespace = mailSession.GetNamespace("MAPI"); mailNamespace.Logon(mail_username, mail_password, false, true); return MailNamespace.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderInbox); } 

我认为最好使用EWS。按照这个链接 – MSDN-EWS