Potrzebuję możliwości monitorowania i odczytywania wiadomości e-mail z określonej skrzynki pocztowej na serwerze MS Exchange (wewnętrznym w mojej firmie). Muszę również mieć możliwość odczytania adresu e-mail nadawcy, tematu, treści wiadomości i pobrania załącznika, jeśli istnieje.
Jaki jest najlepszy sposób na zrobienie tego przy użyciu języka C # (lub VB.NET)?
c#
email
exchange-server
mapi
vajarov
źródło
źródło
Odpowiedzi:
To bałagan. Interfejs MAPI lub CDO za pośrednictwem biblioteki DLL międzyoperacyjnej .NET jest oficjalnie nieobsługiwany przez firmę Microsoft - wydaje się, że działa dobrze, ale występują problemy z wyciekami pamięci z powodu różnych modeli pamięci. Możesz użyć CDOEX, ale to działa tylko na samym serwerze Exchange, a nie zdalnie; nieprzydatny. Możesz współdziałać z Outlookiem, ale teraz właśnie uzależniłeś się od Outlooka; przesada. Wreszcie, możesz skorzystać z obsługi WebDAV w Exchange 2003 , ale WebDAV jest skomplikowany, .NET ma słabe wbudowane wsparcie dla niego i (aby dodać obrażenia do obrażeń) Exchange 2007 prawie całkowicie rezygnuje z obsługi WebDAV.
Co ma zrobić facet? Skończyło się na tym, że użyłem komponentu IMAP AfterLogic do komunikacji z moim serwerem Exchange 2003 za pośrednictwem protokołu IMAP i okazało się, że działa to bardzo dobrze. (Zwykle szukam darmowych lub otwartych bibliotek, ale znalazłem wszystkie potrzebne .NET - szczególnie jeśli chodzi o niektóre dziwactwa implementacji IMAP z 2003 roku - a ta była wystarczająco tania i działała na pierwszej spróbuj. Wiem, że są inni).
Jeśli jednak Twoja organizacja korzysta z programu Exchange 2007, masz szczęście. Exchange 2007 jest wyposażony w interfejs usługi WWW oparty na SOAP, który ostatecznie zapewnia ujednolicony, niezależny od języka sposób interakcji z serwerem Exchange. Jeśli możesz uczynić 2007+ wymaganiem, to zdecydowanie jest droga do zrobienia. (Niestety, moja firma stosuje zasadę „ale rok 2003 nie jest zepsuty”).
Jeśli potrzebujesz pomostu zarówno Exchange 2003, jak i 2007, IMAP lub POP3 jest zdecydowanie najlepszym rozwiązaniem.
źródło
Um,
Może się tu trochę za późno, ale czy to nie jest punkt dla EWS?
https://msdn.microsoft.com/en-us/library/dd633710(EXCHG.80).aspx
Potrzeba około 6 linii kodu, aby pobrać pocztę ze skrzynki pocztowej:
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 ); }
źródło
service.autodiscoverurl
, będę musiał wpisaćservice.credentials
, czy mam rację?Obecnie preferowanym (Exchange 2013 i 2016) API jest EWS . Jest oparty wyłącznie na protokole HTTP i można uzyskać do niego dostęp z dowolnego języka, ale istnieją biblioteki specyficzne dla .Net i Java .
Możesz użyć EWSEditor do zabawy z API.
Rozszerzony MAPI . To jest natywny interfejs API używany przez Outlooka. Kończy się przy użyciu
MSEMS
dostawcy Exchange MAPI, który może komunikować się z Exchange za pomocą RPC (Exchange 2013 już go nie obsługuje) lub RPC-over-HTTP (Exchange 2007 lub nowszy) lub MAPI-over-HTTP (Exchange 2013 i nowsze).Samo API jest dostępne tylko z niezarządzanego C ++ lub Delphi . Możesz także użyć Redemption (dowolny język) - jego rodzina obiektów RDO jest opakowaniem Extended MAPI. Aby korzystać z rozszerzonego interfejsu MAPI, należy zainstalować program Outlook lub samodzielną (Exchange) wersję interfejsu MAPI (przy rozszerzonej obsłudze, która nie obsługuje plików Unicode PST i MSG oraz nie ma dostępu do Exchange 2016). Rozszerzony interfejs MAPI może być używany w usłudze.
Możesz grać z API za pomocą OutlookSpy lub MFCMAPI .
Model obiektów programu Outlook - nie dotyczy Exchange, ale umożliwia dostęp do wszystkich danych dostępnych w programie Outlook na komputerze, na którym działa kod. Nie można używać w usłudze.
Exchange Active Sync . Firma Microsoft nie inwestuje już żadnych znaczących zasobów w ten protokół.
Outlook był używany do instalowania biblioteki CDO 1.21 (opakowuje rozszerzone MAPI), ale został wycofany przez firmę Microsoft i nie otrzymuje już żadnych aktualizacji.
Kiedyś istniało opakowanie .Net MAPI innej firmy o nazwie MAPI33, ale nie jest już rozwijane ani obsługiwane.
WebDAV - przestarzałe.
Collaborative Data Objects for Exchange (CDOEX) - przestarzałe.
Exchange OLE DB Provider (EXOLEDB) - przestarzałe.
źródło
Oto stary kod, który miałem do zrobienia w WebDAV. Myślę, że zostało napisane przeciwko Exchange 2003, ale już nie pamiętam. Możesz go pożyczyć, jeśli jest pomocny ...
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; } }
I model. Poczta:
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; } } }
źródło
Użyłem kodu, który został opublikowany na CodeProject.com . Jeśli chcesz korzystać z POP3, jest to jedno z lepszych rozwiązań, które znalazłem.
źródło
Jeśli serwer Exchange jest skonfigurowany do obsługi protokołu POP lub IMAP, jest to łatwe wyjście.
Inną opcją jest dostęp przez WebDAV. jest do tego dostępna biblioteka . To może być najlepsza opcja.
Myślę, że istnieją opcje wykorzystujące obiekty COM do uzyskiwania dostępu do Exchange, ale nie jestem pewien, jakie to łatwe.
Myślę, że wszystko zależy od tego, co dokładnie administrator zechce dać Ci dostęp.
źródło
Powinieneś być w stanie użyć MAPI, aby uzyskać dostęp do skrzynki pocztowej i uzyskać potrzebne informacje. Niestety, jedyna znana mi biblioteka .NET MAPI (MAPI33) wydaje się nie być konserwowana. Kiedyś był to świetny sposób na dostęp do MAPI przez .NET, ale nie mogę teraz mówić o jego skuteczności. Więcej informacji na temat tego, gdzie można ją pobrać, można znaleźć tutaj: Lokalizacja pobierania pliku MAPI33.dll?
źródło
Mam rozwiązanie działające w końcu za pomocą Redemption, spójrz na te pytania ...
Korzystanie z wykupu ...
Korzystanie z Redemption na 64-bitowej maszynie
źródło
Jedną z opcji jest użycie programu Outlook. Mamy aplikację do zarządzania pocztą, która uzyskuje dostęp do serwera wymiany i używa programu Outlook jako interfejsu. Jest brudny, ale działa.
Przykładowy 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); }
źródło