Baca email MS Exchange di C #

91

Saya memerlukan kemampuan untuk memantau dan membaca email dari kotak surat tertentu di MS Exchange Server (internal perusahaan saya). Saya juga harus bisa membaca alamat email pengirim, subjek, isi pesan dan mendownload lampiran, jika ada.

Apa cara terbaik untuk melakukan ini menggunakan C # (atau VB.NET)?

vajarov.dll
sumber
4
Microsoft telah merilis Exchange Web Services Managed API untuk Exchange 2007 SP1 dan v2010 yang memungkinkan seseorang untuk secara terprogram masuk ke kotak surat Anda tanpa memerlukan Outlook. Saya memiliki dua artikel di blog saya yang membahas pendekatan ini: - C #: Mendapatkan Semua Email Dari Exchange menggunakan Exchange Web Services
ΩmegaMan
Exchange Web Services Managed API 1.0 SDK adalah metode yang Disarankan Microsoft untuk memperbarui Exchange secara terprogram untuk Exchange Server 2007 SP1 dan yang lebih baru. msdn.microsoft.com/en-us/library/dd633710(EXCHG.80).aspx
jlo

Jawaban:

90

Ini berantakan. MAPI atau CDO melalui .NET interop DLL secara resmi tidak didukung oleh Microsoft - tampaknya akan berfungsi dengan baik, namun ada masalah dengan kebocoran memori karena model memorinya yang berbeda. Anda dapat menggunakan CDOEX, tetapi itu hanya berfungsi di server Exchange itu sendiri, tidak dari jarak jauh; tak berguna. Anda dapat melakukan interop dengan Outlook, tetapi sekarang Anda baru saja membuat ketergantungan pada Outlook; berlebihan. Terakhir, Anda dapat menggunakan dukungan WebDAV Exchange 2003 , tetapi WebDAV rumit, .NET memiliki dukungan bawaan yang buruk untuk itu, dan (untuk menambah penghinaan terhadap cedera) Exchange 2007 hampir sepenuhnya menjatuhkan dukungan WebDAV.

Apa yang harus dilakukan pria? Saya akhirnya menggunakan komponen IMAP AfterLogic untuk berkomunikasi dengan server Exchange 2003 saya melalui IMAP, dan ini akhirnya bekerja dengan sangat baik. (Saya biasanya mencari pustaka gratis atau sumber terbuka, tetapi saya menemukan semua yang .NET inginkan - terutama bila menyangkut beberapa kebiasaan implementasi IMAP tahun 2003 - dan yang satu ini cukup murah dan bekerja pada yang pertama. coba. Saya tahu ada orang lain di luar sana.)

Namun, jika organisasi Anda ada di Exchange 2007, Anda beruntung. Exchange 2007 hadir dengan antarmuka layanan Web berbasis SOAP yang akhirnya menyediakan cara bahasa-bahasa yang terpadu untuk berinteraksi dengan server Exchange. Jika Anda dapat menjadikan 2007+ sebagai persyaratan, ini pasti cara yang tepat. (Sayangnya bagi saya, perusahaan saya memiliki kebijakan "tetapi 2003 tidak rusak".)

Jika Anda perlu menjembatani Exchange 2003 dan 2007, IMAP atau POP3 jelas merupakan cara yang tepat.

Nicholas Piasecki
sumber
21
Layanan web berbasis SOAP dibungkus oleh Microsoft untuk menyederhanakan akses - sekarang praktik yang disarankan untuk menggunakan Exchange Web Services Managed API 1.0 SDK: msdn.microsoft.com/en-us/library/dd633710(EXCHG.80).aspx
jlo
4
Hampir seolah-olah Microsoft mendesainnya agar tidak dapat dioperasikan dengan apa pun kecuali Outlook
Chris S
67

Um,

Saya mungkin agak terlambat di sini, tetapi bukankah ini maksudnya EWS?

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

Butuh sekitar 6 baris kode untuk mengambil email dari kotak surat:

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 );
}
Perang
sumber
5
"EWS Managed API menyederhanakan implementasi aplikasi yang berkomunikasi dengan Microsoft Exchange Server 2007 Service Pack 1 (SP1) dan versi Microsoft Exchange yang lebih baru"
Chris S
2
Sadarilah bahwa ini pada dasarnya adalah necrobump untuk pesan lama, tetapi kode ini membuat saya aktif dan berjalan untuk proyek serupa dalam waktu sekitar lima menit. Bekerja dengan sempurna untuk pertama kalinya. Benar-benar solusi yang lebih kontemporer / komprehensif daripada jawaban yang dipilih IMO ... mencatat untuk referensi orang lain.
David W
2
Catatan untuk menjalankan ini. Anda perlu menginstal paket NuGet "Microsoft Exchange WebServices"
John M
4
Ini berhasil bagi saya pada percobaan pertama. Ini harus menjadi jawaban baru yang diterima.
kroe761
Bolehkah saya tahu jika saya menggunakan alamat email selain dari kotak surat saya sendiri di service.autodiscoverurl, saya harus memasukkan service.credentials, apakah saya benar?
gymcode
19
  1. API (Exchange 2013 dan 2016) yang saat ini disukai adalah EWS . Ini murni berbasis HTTP dan dapat diakses dari bahasa apa pun, tetapi ada pustaka khusus .Net dan Java .

    Anda dapat menggunakan EWSEditor untuk bermain dengan API.

  2. MAPI diperpanjang . Ini adalah API asli yang digunakan oleh Outlook. Ini akhirnya menggunakan MSEMSpenyedia Exchange MAPI, yang dapat berbicara dengan Exchange menggunakan RPC (Exchange 2013 tidak lagi mendukungnya) atau RPC-over-HTTP (Exchange 2007 atau yang lebih baru) atau MAPI-over-HTTP (Exchange 2013 dan yang lebih baru).

    API itu sendiri hanya dapat diakses dari C ++ atau Delphi yang tidak dikelola . Anda juga dapat menggunakan Penukaran (bahasa apa pun) - kelompok objek RDO -nya adalah pembungkus MAPI yang Diperluas. Untuk menggunakan Extended MAPI, Anda perlu menginstal Outlook atau versi mandiri (Exchange) MAPI (pada dukungan diperpanjang, dan tidak mendukung file Unicode PST dan MSG dan tidak dapat mengakses Exchange 2016). MAPI yang diperluas dapat digunakan dalam layanan.

    Anda dapat bermain dengan API menggunakan OutlookSpy atau MFCMAPI .

  3. Model Objek Outlook - tidak khusus Exchange, tetapi memungkinkan akses ke semua data yang tersedia di Outlook pada mesin tempat kode dijalankan. Tidak dapat digunakan dalam layanan.

  4. Exchange Active Sync . Microsoft tidak lagi menginvestasikan sumber daya yang signifikan ke dalam protokol ini.

  5. Outlook digunakan untuk menginstal pustaka CDO 1.21 (ini membungkus MAPI yang Diperluas), tetapi sudah usang oleh Microsoft dan tidak lagi menerima pembaruan apa pun.

  6. Dulu ada pembungkus MAPI .Net pihak ketiga yang disebut MAPI33, tetapi tidak lagi dikembangkan atau didukung.

  7. WebDAV - tidak digunakan lagi.

  8. Objek Data Kolaboratif untuk Exchange (CDOEX) - tidak digunakan lagi.

  9. Exchange OLE DB Provider (EXOLEDB) - tidak digunakan lagi.

Dmitry Streblechenko
sumber
EwsEditor telah pindah ke github: github.com/dseph/EwsEditor
Opmet
10

Berikut adalah beberapa kode lama yang telah saya berikan untuk melakukan WebDAV. Saya pikir itu ditulis melawan Exchange 2003, tapi saya tidak ingat lagi. Jangan ragu untuk meminjamnya jika membantu ...

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;
    }
}

Dan 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; }
    }
}
CodingWithSpike
sumber
1
CATATAN: Dukungan WebDAV dihapus dari Exchange Server 2010, gunakan EWS sebagai gantinya.
Our Man in Bananas
0

Jika server Exchange Anda dikonfigurasi untuk mendukung POP atau IMAP, itu jalan keluar yang mudah.

Pilihan lainnya adalah akses WebDAV. ada perpustakaan yang tersedia untuk itu. Ini mungkin pilihan terbaik Anda.

Saya pikir ada opsi menggunakan objek COM untuk mengakses Exchange, tapi saya tidak yakin betapa mudahnya itu.

Itu semua tergantung pada apa yang sebenarnya ingin diberikan administrator Anda kepada Anda.

Denis Troller
sumber
0

Anda harus dapat menggunakan MAPI untuk mengakses kotak surat dan mendapatkan informasi yang Anda butuhkan. Sayangnya satu-satunya pustaka .NET MAPI (MAPI33) yang saya ketahui tampaknya tidak terawat. Ini dulunya adalah cara terbaik untuk mengakses MAPI melalui .NET, tetapi saya tidak dapat menjelaskan keefektifannya sekarang. Ada informasi lebih lanjut tentang di mana Anda bisa mendapatkannya di sini: Unduh lokasi untuk MAPI33.dll?

Chris Hynes
sumber
0

Salah satu opsinya adalah menggunakan Outlook. Kami memiliki aplikasi pengelola email yang mengakses server pertukaran dan menggunakan pandangan sebagai antarmuka. Ini kotor tapi berhasil.

Kode contoh:

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);
        }
duncane
sumber
1
Jika saya ingin menggunakan Layanan Windows di Win2003 untuk akses ke Exchange 2003 ?? Saya perlu menginstal Outlook 2003 atau 2007 di Server win2003?
Kiquenet