MS Exchange e-postasını C # dilinde okuyun


91

Bir MS Exchange Sunucusundaki (şirketim dahilinde) belirli bir posta kutusundan e-postayı izleme ve okuma yeteneğine ihtiyacım var. Ayrıca gönderenin e-posta adresini, konusunu, mesaj gövdesini okuyabilmem ve varsa bir eki indirebilmem gerekiyor.

Bunu C # (veya VB.NET) kullanarak yapmanın en iyi yolu nedir?


4
Microsoft, o zamandan beri Exchange 2007 SP1 ve v2010 için Exchange Web Hizmetleri Yönetilen API'sini yayınladı; bu, Outlook'a ihtiyaç duymadan posta kutunuza programatik olarak girmenize olanak tanır. Blogumda bu yaklaşımı tartışan iki makale var: - C #: Exchange Web Hizmetlerini Kullanarak Tüm E-postaları Exchange'den Alma
ΩmegaMan

Exchange Web Hizmetleri Yönetilen API 1.0 SDK, Exchange Server 2007 SP1 ve üzeri için Exchange'i programlı olarak güncellemek için Microsoft Tarafından Önerilen yöntemdir. msdn.microsoft.com/en-us/library/dd633710(EXCHG.80).aspx
jlo

Yanıtlar:


90

Bu bir karmaşa. Bir .NET birlikte çalışma DLL'si aracılığıyla MAPI veya CDO , Microsoft tarafından resmi olarak desteklenmemektedir - iyi çalışıyor gibi görünecek, ancak farklı bellek modellerinden dolayı bellek sızıntılarıyla ilgili sorunlar var. CDOEX'i kullanabilirsiniz, ancak bu yalnızca Exchange sunucusunda çalışır, uzaktan değil; Faydasız. Outlook ile birlikte çalışabilirsiniz, ancak şimdi Outlook'a bir bağımlılık yaptınız; aşırı yükleme. Son olarak, Exchange 2003'ün WebDAV desteğini kullanabilirsiniz , ancak WebDAV karmaşıktır, .NET'in yerleşik desteği zayıftır ve (yaralanmaya hakaret eklemek için) Exchange 2007, WebDAV desteğini neredeyse tamamen keser.

Bir erkek ne yapmalı? AfterLogic'in IMAP bileşenini kullanmayı bıraktım aracılığıyla Exchange 2003 iletişim kullanmayı bıraktım ve bu çok iyi sonuç verdi. (Normalde ücretsiz veya açık kaynaklı kitaplıklar ararım, ancak tüm .NET kitaplıklarını istiyor buldum - özellikle 2003'ün IMAP uygulamasının bazı tuhaflıkları söz konusu olduğunda - ve bu yeterince ucuzdu ve ilkinde işe yaradı deneyin. Dışarıda başkalarının da olduğunu biliyorum.)

Ancak kuruluşunuz Exchange 2007 üzerindeyse, şanslısınız. Exchange 2007 , sonunda Exchange sunucusuyla birleşik, dilden bağımsız bir etkileşim yolu sağlayan SOAP tabanlı bir Web hizmeti arabirimiyle birlikte gelir . 2007+ 'yi bir gereklilik haline getirebiliyorsanız, bu kesinlikle doğru yoldur. (Ne yazık ki benim için şirketimin bir "ama 2003 bozulmadı" politikası var.)

Hem Exchange 2003 hem de 2007'yi köprülemeniz gerekiyorsa, IMAP veya POP3 kesinlikle en iyi yoldur.


21
SOAP tabanlı web hizmeti, erişimi basitleştirmek için Microsoft tarafından paketlendi - artık Exchange Web Hizmetleri Yönetilen API 1.0 SDK'sının kullanılması önerilir: msdn.microsoft.com/en-us/library/dd633710(EXCHG.80).aspx
jlo

4
Microsoft şey ile çalışamaz duruma üzere tasarladım sanki bulunuyor ancak Outlook
Chris S

67

Um,

Burada biraz geç kalmış olabilirim ama bu, EWS'nin anlamı değil mi?

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

Postayı bir posta kutusundan almak için yaklaşık 6 satır kod alır:

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

5
"EWS Yönetilen API, Microsoft Exchange Server 2007 Service Pack 1 (SP1) ve Microsoft Exchange'in sonraki sürümleriyle iletişim kuran uygulamaların uygulanmasını basitleştirir"
Chris S

2
Bunun aslında bir yıllık mesaj için bir necrobump olduğunu anlayın, ancak bu kod beni yaklaşık beş dakika içinde benzer bir proje için hazırlayıp çalıştırdı. İlk seferinde mükemmel çalıştı. Gerçekten, seçilen cevap IMO'dan daha çağdaş / kapsamlı bir çözüm ... başka birinin referansına dikkat çekiyor.
David W

2
Bunu çalıştırmaya dikkat edin. NuGet paketini "Microsoft Exchange WebServices" kurmanız gerekiyor
John M

4
Bu benim için ilk denemede çalıştı. Kabul edilen yeni cevap bu olmalıdır.
kroe761

İçinde kendi posta kutum dışında bir e-posta adresi kullanacak olsaydım, service.autodiscoverurlgirmem gerekecek service.credentials, haklı mıyım?
2019

19
  1. Şu anda tercih edilen (Exchange 2013 ve 2016) API, EWS'dir . Tamamen HTTP tabanlıdır ve herhangi bir dilden erişilebilir, ancak .Net ve Java'ya özel kütüphaneler vardır.

    API ile oynamak için EWSEditor'ı kullanabilirsiniz .

  2. Genişletilmiş MAPI . Bu, Outlook tarafından kullanılan yerel API'dir. Bu kullanarak biter MSEMSRPC kullanarak Exchange konuşabilirsiniz Exchange MAPI sağlayıcısı (Exchange 2013 artık desteklemediği bunu) veya RPC-over-HTTP (Exchange 2007 veya daha yeni) veya MAPI-over-HTTP (Exchange 2013 ve daha yeni).

    API'nin kendisine yalnızca yönetilmeyen C ++ veya Delphi'den erişilebilir . Redemption'ı (herhangi bir dil) de kullanabilirsiniz - RDO nesne ailesi bir Genişletilmiş MAPI sarmalayıcısıdır. Genişletilmiş MAPI'yı kullanmak için, ya Outlook'u ya da MAPI'nin bağımsız (Exchange) sürümünü yüklemeniz gerekir (genişletilmiş destekte ve Unicode PST ve MSG dosyalarını desteklemez ve Exchange 2016'ya erişemez). Genişletilmiş MAPI bir hizmette kullanılabilir.

    OutlookSpy veya MFCMAPI kullanarak API ile oynayabilirsiniz .

  3. Outlook Nesne Modeli - Exchange'e özel değildir, ancak kodun çalıştığı makinede Outlook'ta bulunan tüm verilere erişime izin verir. Bir serviste kullanılamaz.

  4. Exchange Active Sync . Microsoft artık bu protokole önemli kaynaklar yatırmamaktadır.

  5. Outlook, CDO 1.21 kitaplığını yüklemek için kullanılır (Genişletilmiş MAPI'yi kapsar), ancak Microsoft tarafından kullanımdan kaldırılmış ve artık herhangi bir güncelleme almamaktadır.

  6. MAPI33 adında bir üçüncü taraf .Net MAPI sarmalayıcısı vardı, ancak artık geliştirilmiyor veya desteklenmiyor.

  7. WebDAV - kullanımdan kaldırıldı.

  8. Exchange için Ortak Veri Nesneleri (CDOEX) - kullanımdan kaldırıldı.

  9. Exchange OLE DB Sağlayıcısı (EXOLEDB) - kullanımdan kaldırıldı.


EwsEditor, github'a taşındı: github.com/dseph/EwsEditor
Opmet

10

İşte WebDAV yapmak için etrafta kurduğum bazı eski kodlar. Sanırım Exchange 2003'e karşı yazılmıştı, ama artık hatırlamıyorum. Yararlıysa ödünç almaktan çekinmeyin ...

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

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

1
NOT: WebDAV desteği Exchange Server 2010'dan bırakılır, bunun yerine EWS'yi kullanın.
Our Man in Bananas


0

Exchange sunucunuz POP veya IMAP'yi destekleyecek şekilde yapılandırılmışsa, bu kolay bir yoldur.

Diğer bir seçenek de WebDAV erişimidir. bir kütüphane var var. Bu en iyi seçeneğiniz olabilir.

Exchange'e erişmek için COM nesnelerini kullanma seçenekleri olduğunu düşünüyorum, ancak bunun ne kadar kolay olduğundan emin değilim.

Her şey, yöneticinizin size erişim izni vermek isteyip istemediğine bağlı.


0

Posta kutusuna erişmek ve ihtiyacınız olan bilgileri almak için MAPI'yi kullanabilmelisiniz. Ne yazık ki bildiğim tek .NET MAPI kitaplığı (MAPI33) bakımsız görünüyor. Bu eskiden MAPI'ye .NET aracılığıyla erişmenin harika bir yoluydu, ancak şu anda etkinliğinden bahsedemiyorum. Buradan nereden alabileceğiniz hakkında daha fazla bilgi var: MAPI33.dll için indirme konumu?



0

Seçeneklerden biri Outlook kullanmaktır. Bir değişim sunucusuna erişen ve arayüz olarak outlook kullanan bir posta yöneticisi uygulamamız var. Kirli ama işe yarıyor.

Örnek kod:

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

1
Exchange 2003'e erişmek için Win2003'te Windows Hizmetini kullanmak istersem ?? Win2003 Sunucusunda Outlook 2003 veya 2007'yi yüklemem gerekiyor mu?
Kiquenet
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.