繁体   English   中英

在 C# 中读取 MS Exchange email

[英]Read MS Exchange email in C#

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

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

一团糟。 MAPI or CDO via a .NET interop DLL is officially unsupported by Microsoft --it will appear to work fine, but there are problems with memory leaks due to their differing memory models. 您可以使用 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+,这绝对是 go 的方式。 (对我来说可悲的是,我的公司有一个“但 2003 年没有被打破”的政策。)

如果您需要同时连接 Exchange 2003 和 2007,IMAP 或 POP3 绝对是通向 go 的方式。

嗯,

我在这里可能有点太晚了,但这不是 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 的,可以从任何语言访问,但有.NetJava特定库。

    您可以使用EWSEditor来玩弄 API。

  2. 扩展 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 或MAPI 的独立 (Exchange) 版本(在扩展支持上,它不支持 Unicode PST 和 MSG 文件,并且无法访问 Exchange 2016)。 可在服务中使用扩展 MAPI。

    您可以使用OutlookSpyMFCMAPI玩 API。

  3. Outlook Object Model - not Exchange specific, but it allows access to all data available in Outlook on the machine where the code runs. 不能在服务中使用。

  4. 交换活动同步 Microsoft 不再为此协议投入任何重要资源。

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

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

  7. WebDAV - 已弃用。

  8. 用于 Exchange 的协作数据对象 (CDOEX) - 已弃用。

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

这是我用来做 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,它是我找到的更好的解决方案之一。

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

另一种选择是 WebDAV 访问。 有一个可用的 这可能是您最好的选择。

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

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

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

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

一种选择是使用 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);
        }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM