web-dev-qa-db-ja.com

C#でMS Exchangeメールを読む

MS Exchange Server(会社の内部)上の特定のメールボックスを監視し、そのメールを読む機能が必要です。また、送信者の電子メールアドレス、件名、メッセージ本文を読み、添付ファイルがある場合はダウンロードできる必要があります。

C#(またはVb.net)を使用してこれを行う最良の方法は何ですか?

88
vajarov

それは混乱です。 .NET interopを介したMAPIまたはCDO DLLは Microsoftによって公式にサポートされていません -正常に動作するように見えますが、メモリモデルが異なるためメモリリークの問題があります。 CDOEXを使用できますが、これはExchangeサーバー自体でのみ機能し、リモートでは機能しません。役に立たない。 Outlookと相互運用できますが、Outlookに依存するようになりました。やりすぎ。最後に、 Exchange 2003のWebDAVサポート を使用できますが、WebDAVは複雑で、.NETの組み込みサポートは不十分であり、(傷害にinjury辱を加えるために)Exchange 2007ほぼ完全にドロップしますWebDAVサポート。

やる人は?最終的に AfterLogicのIMAPコンポーネント を使用してIMAPを介してExchange 2003サーバーと通信し、これは非常にうまく機能しました。 (私は通常無料またはオープンソースのライブラリを探しますが、特に2003年のIMAP実装のいくつかの癖になると、必要なすべての.NETライブラリを見つけました。これは十分に安く、最初のもので動作しました試してみてください。他にもあることは知っています。)

ただし、組織がExchange 2007を使用している場合は、幸運です。 Exchange 2007にはSOAPベースのWebサービスインターフェイスが付属しています 最終的に、Exchangeサーバーと対話するための統合された、言語に依存しない方法を提供します。 2007+を要件にすることができれば、これは間違いなく進むべき方法です。 (残念ながら、私の会社には「しかし2003年は壊れていません」というポリシーがあります。)

Exchange 2003と2007の両方をブリッジする必要がある場合、IMAPまたはPOP3が間違いなく道です。

89

あの、

私はここで少し遅すぎるかもしれませんが、これはちょっと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( "[email protected]" );

FindItemsResults<Item> findResults = service.FindItems(
   WellKnownFolderName.Inbox,
   new ItemView( 10 ) 
);

foreach ( Item item in findResults.Items )
{
   Console.WriteLine( item.Subject );
}
64
War
  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以降)。

    API自体は、アンマネージC++または Delphi からのみアクセスできます。 Redemption (任意の言語)を使用することもできます-その RDO オブジェクトファミリは拡張MAPIラッパーです。拡張MAPIを使用するには、Outlookまたは スタンドアロン(Exchange)バージョンのMAPI (拡張サポート上で、Unicode PSTおよびMSG_ファイルをサポートせず、 Exchange 2016にアクセスします)。拡張MAPIはサービスで使用できます。

    OutlookSpy または MFCMAPI を使用してAPIで遊ぶことができます。

  3. Outlook Object Model -Exchange固有ではありませんが、コードが実行されるマシン上のOutlookで利用可能なすべてのデータへのアクセスを許可します。サービスでは使用できません。

  4. Exchange Active Sync 。マイクロソフトは、このプロトコルに重要なリソースを投資しなくなりました。

  5. OutlookはCDO 1.21ライブラリ(Extended MAPIをラップする)をインストールするために使用されていましたが、Microsoftによって廃止され、更新プログラムを受信しなくなりました。

  6. 以前はMAPI33と呼ばれるサードパーティの.Net MAPIラッパーがありましたが、現在は開発もサポートもされていません。

  7. WebDAV-非推奨です。

  8. Exchangeの共同データオブジェクト(CDOEX)-非推奨。

  9. Exchange OLE DB Provider(EXOLEDB)-非推奨です。

17

ここに、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/[email protected]/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/[email protected]/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/[email protected]/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; }
    }
}
10
CodingWithSpike

CodeProject.comで公開 のコードを使用しました。 POP3を使用する場合、POP3は私が見つけた優れたソリューションの1つです。

1
Eldila

ExchangeサーバーがPOPまたはIMAPをサポートするように構成されている場合、それは簡単な方法です。

別のオプションはWebDAVアクセスです。 library が利用可能です。これが最良の選択肢かもしれません。

COMオブジェクトを使用してExchangeにアクセスするオプションがあると思いますが、それがどれほど簡単かはわかりません。

それはすべて、管理者があなたにアクセス権を与えてくれるかどうかによって異なります。

0
Denis Troller

MAPIを使用してメールボックスにアクセスし、必要な情報を取得できる必要があります。残念ながら、私が知っている唯一の.NET MAPIライブラリ(MAPI33)はメンテナンスされていないようです。これは、以前は.NETを介してMAPIにアクセスするための優れた方法でしたが、現在その有効性について話すことはできません。どこで入手できるかについての詳細はこちらにあります: MAPI33.dllのダウンロード場所?

0
Chris Hynes

Redemptionを使用して最終的に動作するソリューションを得たので、これらの質問を見てください...

0
Paul Rowland

1つのオプションは、Outlookを使用することです。 Exchangeサーバーにアクセスし、インターフェイスとして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);
        }
0
duncane