C #으로 MS Exchange 이메일 읽기


91

MS Exchange Server (회사 내부)의 특정 사서함에서 전자 메일을 모니터링하고 읽을 수있는 기능이 필요합니다. 또한 보낸 사람의 전자 메일 주소, 제목, 메시지 본문을 읽고 첨부 파일 (있는 경우)을 다운로드 할 수 있어야합니다.

C # (또는 VB.NET)을 사용하여이를 수행하는 가장 좋은 방법은 무엇입니까?


4
Microsoft는 이후 Outlook 없이도 사서함에 프로그래밍 방식으로 액세스 할 수있는 Exchange 2007 SP1 및 v2010 용 Exchange 웹 서비스 관리 API를 출시했습니다. 이 접근 방식에 대해 설명하는 두 개의 기사가 블로그에 있습니다.- C # : Exchange 웹 서비스를 사용하여 Exchange에서 모든 이메일 받기
ΩmegaMan

Exchange Web Services Managed API 1.0 SDK는 Exchange Server 2007 SP1 이상에 대해 프로그래밍 방식으로 Exchange를 업데이트하기위한 Microsoft 권장 방법입니다. msdn.microsoft.com/en-us/library/dd633710(EXCHG.80).aspx
jlo

답변:


90

엉망입니다. .NET interop DLL을 통한 MAPI 또는 CDO는 공식적으로 Microsoft에서 지원 하지 않습니다. 제대로 작동하는 것처럼 보이지만 메모리 모델이 다르기 때문에 메모리 누수 문제가 있습니다. CDOEX를 사용할 수 있지만 원격이 아닌 Exchange 서버 자체에서만 작동합니다. 쓸모없는. Outlook과 상호 운용 할 수 있지만 이제 Outlook에 대한 종속성을 만들었습니다. 지나침. 마지막으로 Exchange 2003의 WebDAV 지원을 사용할 수 있지만 WebDAV는 복잡하고 .NET은 기본 제공 지원이 부족하며 (부상을 더하기 위해) Exchange 2007 WebDAV 지원을 거의 완전히 중단 합니다.

할 사람은 무엇입니까? 결국 AfterLogic의 IMAP 구성 요소 를 사용하여 IMAP 을 통해 Exchange 2003 서버와 통신하게되었고, 결국 매우 잘 작동했습니다. (일반적으로 무료 또는 오픈 소스 라이브러리를 찾아 보지만, 특히 2003 년 IMAP 구현의 일부 단점에 관해서는 .NET 라이브러리가 모두 필요하다는 것을 알았습니다.이 라이브러리는 충분히 저렴하고 첫 번째 다른 사람이 있다는 것을 알고 있습니다.)

그러나 조직이 Exchange 2007을 사용하는 경우 운이 좋습니다. Exchange 2007에는 최종적으로 Exchange 서버와 상호 작용하는 언어 독립적 인 통합 방식을 제공 하는 SOAP 기반 웹 서비스 인터페이스가 함께 제공됩니다 . 2007+를 요구 사항으로 만들 수 있다면 이것이 확실히 갈 길입니다. (나에게 안타깝게도 우리 회사는 "2003 년은 깨지지 않았습니다"라는 정책을 가지고 있습니다.)

Exchange 2003과 2007을 모두 연결해야하는 경우 IMAP 또는 POP3를 사용하는 것이 좋습니다.


21
SOAP 기반 웹 서비스는 액세스를 단순화하기 위해 Microsoft에 의해 래핑되었습니다. 이제 Exchange Web Services Managed API 1.0 SDK를 사용하는 것이 좋습니다. msdn.microsoft.com/en-us/library/dd633710(EXCHG.80).aspx
jlo

4
마치 Microsoft가 Outlook 이외의 다른 제품과 작동하지 않도록 설계 한 것과 거의 같습니다
Chris S

67

음,

나는 여기에 너무 늦었을 수도 있지만 이것이 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 );
}

5
"EWS 관리 API는 Microsoft Exchange Server 2007 SP1 (서비스 팩 1) 및 이후 버전의 Microsoft Exchange와 통신하는 응용 프로그램의 구현을 단순화합니다."
Chris S

2
이것은 본질적으로 몇 년 된 메시지에 대한 괴사이지만이 코드를 사용하면 약 5 분 만에 비슷한 프로젝트를 실행할 수 있습니다. 처음부터 완벽하게 작동했습니다. 선택한 답변 IMO보다 훨씬 현대적이고 포괄적 인 솔루션입니다.
David W

2
이 실행에 대한 참고. NuGet 패키지 "Microsoft Exchange WebServices"를 설치해야합니다
John M

4
이것은 첫 번째 시도에서 나를 위해 일했습니다. 이것은 새로 받아 들여진 대답이어야합니다.
kroe761

에서 내 사서함과는 별도로 이메일 주소를 사용해야하는지 알 수 있습니까? service.autodiscoverurl을 입력해야합니다. service.credentials맞습니까?
gymcode

19
  1. 현재 선호되는 (Exchange 2013 및 2016) API는 EWS 입니다. 순전히 HTTP 기반이며 모든 언어에서 액세스 할 수 있지만 .NetJava 특정 라이브러리가 있습니다.

    당신이 사용할 수있는 EWSEditor 를 하여 API를 .

  2. 확장 된 MAPI . Outlook에서 사용하는 기본 API입니다. MSEMSRPC (Exchange 2013에서 더 이상 지원하지 않음) 또는 RPC-over-HTTP (Exchange 2007 이상) 또는 MAPI-over-HTTP (Exchange 2013 이상)를 사용하여 Exchange와 통신 할 수 있는 Exchange MAPI 공급자를 사용하게됩니다.

    API 자체는 관리되지 않는 C ++ 또는 Delphi 에서만 액세스 할 수 있습니다 . Redemption (모든 언어)을 사용할 수도 있습니다. RDO 개체 제품군은 확장 MAPI 래퍼입니다. 확장 MAPI를 사용하려면 Outlook 또는 독립 실행 형 (Exchange) 버전의 MAPI (확장 지원시, 유니 코드 PST 및 MSG 파일을 지원하지 않으며 Exchange 2016에 액세스 할 수 없음)를 설치해야합니다. 서비스에서 확장 MAPI를 사용할 수 있습니다.

    OutlookSpy 또는 MFCMAPI를 사용하여 API를 사용할 수 있습니다. .

  3. Outlook 개체 모델 -Exchange와 관련이 없지만 코드가 실행되는 컴퓨터의 Outlook에서 사용할 수있는 모든 데이터에 액세스 할 수 있습니다. 서비스에서 사용할 수 없습니다.

  4. Exchange Active Sync . Microsoft는 더 이상이 프로토콜에 중요한 리소스를 투자하지 않습니다.

  5. Outlook은 CDO 1.21 라이브러리 (확장 MAPI를 포함)를 설치하는 데 사용되었지만 Microsoft에서 더 이상 사용하지 않으며 더 이상 업데이트를받지 않습니다.

  6. MAPI33이라는 타사 .Net MAPI 래퍼가 있었지만 더 이상 개발되거나 지원되지 않습니다.

  7. WebDAV-더 이상 사용되지 않습니다.

  8. CDOEX (Collaborative Data Objects for Exchange)-더 이상 사용되지 않습니다.

  9. Exchange OLE DB 공급자 (EXOLEDB)-더 이상 사용되지 않습니다.


EwsEditor가 github로 이동했습니다 : github.com/dseph/EwsEditor
Opmet

10

다음은 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; }
    }
}

1
참고 : WebDAV 지원은 Exchange Server 2010에서 중단되므로 대신 EWS를 사용하십시오.
바나나에있는 우리의 남자는


0

Exchange 서버가 POP 또는 IMAP을 지원하도록 구성되어있는 경우 쉬운 방법입니다.

또 다른 옵션은 WebDAV 액세스입니다. 이를위한 라이브러리가 있습니다. 이것이 최선의 선택 일 수 있습니다.

COM 개체를 사용하여 Exchange에 액세스하는 옵션이 있다고 생각하지만 얼마나 쉬운 지 잘 모르겠습니다.

그것은 모두 관리자가 정확히 무엇에 대한 액세스 권한을 제공 할 것인지에 달려 있습니다.


0

MAPI를 사용하여 사서함에 액세스하고 필요한 정보를 얻을 수 있어야합니다. 불행히도 내가 아는 유일한 .NET MAPI 라이브러리 (MAPI33)는 유지되지 않는 것 같습니다. 이것은 .NET을 통해 MAPI에 액세스하는 좋은 방법 이었지만 지금은 그 효과에 대해 말할 수 없습니다. 여기에서 얻을 수있는 위치에 대한 자세한 정보가 있습니다. MAPI33.dll의 다운로드 위치?



0

한 가지 옵션은 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);
        }

1
Exchange 2003에 액세스하기 위해 Win2003에서 Windows 서비스를 사용하려면? Server win2003에 Outlook 2003 또는 2007을 설치해야합니까?
Kiquenet 2010
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.