【问题标题】:Read MS Exchange email in C#在 C# 中阅读 MS Exchange 电子邮件
【发布时间】:2010-10-13 17:53:28
【问题描述】:

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

使用 C#(或 VB.NET)执行此操作的最佳方法是什么?

【问题讨论】:

标签: c# email exchange-server mapi


【解决方案1】:

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

另一个选项是 WebDAV 访问。有一个library 可用。这可能是您的最佳选择。

我认为有使用 COM 对象访问 Exchange 的选项,但我不确定它是否容易。

这完全取决于您的管理员究竟愿意为您提供什么我猜的访问权限。

【讨论】:

    【解决方案2】:

    您应该能够使用 MAPI 访问邮箱并获取您需要的信息。不幸的是,我所知道的唯一 .NET MAPI 库 (MAPI33) 似乎没有维护。这曾经是通过 .NET 访问 MAPI 的好方法,但我现在无法评价它的有效性。您可以在此处获取更多信息:Download location for MAPI33.dll?

    【讨论】:

      【解决方案3】:

      我使用的代码是published on CodeProject.com。如果你想使用 POP3,这是我找到的更好的解决方案之一。

      【讨论】:

        【解决方案4】:

        真是一团糟。通过 .NET 互操作 DLL 的 MAPI 或 CDO 是 officially unsupported by Microsoft——它看起来工作正常,但由于它们的内存模型不同,存在内存泄漏问题。您可以使用 CDOEX,但这仅适用于 Exchange 服务器本身,而不适用于远程;无用。您可以与 Outlook 互操作,但现在您只是依赖于 Outlook;矫枉过正。最后,您可以使用 Exchange 2003's WebDAV support,但 WebDAV 很复杂,.NET 对其的内置支持很差,而且(雪上加霜)Exchange 2007 几乎完全放弃了 WebDAV 支持。 p>

        一个人要做什么?我最终使用AfterLogic's IMAP component 通过 IMAP 与我的 Exchange 2003 服务器进行通信,结果运行良好。 (我通常会寻找免费或开源的库,但我发现所有的 .NET 库都想要——尤其是在涉及到 2003 年 IMAP 实现的一些怪癖时——而且这个库足够便宜并且可以在第一个试试。我知道还有其他人。)

        但是,如果您的组织使用 Exchange 2007,那么您很幸运。 Exchange 2007 comes with a SOAP-based Web service interface 最终提供了一种与 Exchange 服务器交互的统一的、独立于语言的方式。如果您可以要求 2007+,这绝对是要走的路。 (可悲的是,我的公司有一个“但 2003 年没有被打破”的政策。)

        如果您需要同时连接 Exchange 2003 和 2007,IMAP 或 POP3 绝对是最佳选择。

        【讨论】:

        【解决方案5】:

        我最终得到了一个使用 Redemption 的解决方案,看看这些问题...

        【讨论】:

          【解决方案6】:

          这是我用来做 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; }
              }
          }
          

          【讨论】:

          • 注意:WebDAV 支持已从 Exchange Server 2010 中删除,请改用 EWS。
          【解决方案7】:

          一种选择是使用 Outlook。我们有一个邮件管理器应用程序可以访问交换服务器并使用 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);
                  }
          

          【讨论】:

          • 如果我想在 Win2003 中使用 Windows 服务来访问 Exchange 2003 ??我需要在服务器 win2003 中安装 Outlook 2003 或 2007 吗?
          【解决方案8】:

          嗯,

          我在这里可能有点太晚了,但这不是 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 );
          }
          

          【讨论】:

          • “EWS 托管 API 简化了与 Microsoft Exchange Server 2007 Service Pack 1 (SP1) 和更高版本的 Microsoft Exchange 通信的应用程序的实施”
          • 意识到这实际上是一个多年前的消息的 necrobump,但这段代码让我在大约五分钟内启动并运行了一个类似的项目。第一次完美运行。确实是比选定的答案 IMO 更现代/更全面的解决方案......注意其他人的参考。
          • 关于运行此程序的注意事项。您需要安装 NuGet 包“Microsoft Exchange WebServices”
          • 这对我来说是第一次尝试。这应该是新接受的答案。
          • 我可以知道如果我要在service.autodiscoverurl 中使用我自己的邮箱以外的电子邮件地址,我需要输入service.credentials,对吗?
          【解决方案9】:
          1. 当前首选(Exchange 2013 和 2016)API 是 EWS。它完全基于 HTTP,可以从任何语言访问,但有 .NetJava 特定库。

            您可以使用EWSEditor 来玩API。

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

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

            您可以使用 OutlookSpyMFCMAPI 使用 API。

          3. Outlook Object Model - 不特定于 Exchange,但它允许访问运行代码的计算机上 Outlook 中的所有可用数据。不能在服务中使用。

          4. Exchange Active Sync。 Microsoft 不再为此协议投入任何重要资源。

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

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

          7. WebDAV - 已弃用。

          8. Collaborative Data Objects for Exchange (CDOEX) - 已弃用。

          9. Exchange OLE DB 提供程序 (EXOLEDB) - 已弃用。

          【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2023-03-15
          • 2016-12-15
          • 2012-07-13
          • 2017-09-05
          • 2012-11-21
          • 2017-09-15
          • 1970-01-01
          相关资源
          最近更新 更多