سؤال

أحتاج إلى القدرة على المراقبة وقراءة البريد الإلكتروني من صندوق بريد معين على خادم MS Exchange (داخلي لشركتي). أحتاج أيضًا إلى أن أكون قادرًا على قراءة عنوان البريد الإلكتروني للمرسل والموضوع وجسم الرسائل وتنزيل مرفق إن وجد.

ما هي أفضل طريقة للقيام بذلك باستخدام C# (أو vb.net)؟

هل كانت مفيدة؟

المحلول

هذه فوضى. MAPI أو CDO عبر .NET interop DLL هو غير مدعوم رسميا من قبل Microsoft-سيبدو أنه يعمل بشكل جيد ، ولكن هناك مشاكل في تسرب الذاكرة بسبب نماذج الذاكرة المختلفة. يمكنك استخدام CDOEX ، ولكن هذا يعمل فقط على خادم Exchange نفسه ، وليس عن بعد ؛ عديم الفائدة. يمكنك أن تتداخل مع Outlook ، لكنك الآن قد قمت بتقديم تبعية على Outlook ؛ المبالغة. أخيرًا ، يمكنك استخدام دعم WebDAV لعام 2003, ، لكن WebDav معقد ، .NET لديه دعم مدمج ضعيف لذلك ، (لإضافة إهانة للإصابة) Exchange 2007 يسقط تماما تقريبا دعم WebDAV.

ماذا يفعل الرجل؟ انتهى بي الأمر باستخدام مكون IMAP الخاص بـ Afterlogic للتواصل مع خادم Exchange 2003 عبر IMAP ، وانتهى الأمر بالعمل بشكل جيد للغاية. (عادةً ما أبحث عن مكتبات مجانية أو مفتوحة المصدر ، لكنني وجدت كل ما تريده. حاول. أعرف أن هناك آخرين هناك.)

إذا كانت مؤسستك في Exchange 2007 ، فأنت محظوظ. يأتي Exchange 2007 مع واجهة خدمة ويب قائمة على الصابون يوفر ذلك أخيرًا طريقة موحدة مستقلة عن اللغة للتفاعل مع خادم Exchange. إذا تمكنت من جعل 2007+ متطلبًا ، فهذا بالتأكيد هو السبيل للذهاب. (للأسف بالنسبة لي ، لدى شركتي سياسة "لكن 2003 ليست مكسورة".)

إذا كنت بحاجة إلى سد كل من Exchange 2003 و 2007 ، فإن IMAP أو POP3 هو بالتأكيد الطريق للذهاب.

نصائح أخرى

أم ،

قد أكون متأخراً قليلاً هنا ، لكن أليس هذا هو النقطة إلى 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 );
}
  1. واجهة برمجة تطبيقات المفضلة (Exchange 2013 و 2016) هي EWS. إنه يعتمد على HTTP بحتة ويمكن الوصول إليه من أي لغة ، ولكن هناك .شبكة و جافا مكتبات محددة.

    يمكنك استخدام ewseditor للعب مع API.

  2. موسي ميد. هذا هو واجهة برمجة التطبيقات الأصلية التي تستخدمها Outlook. انتهى الأمر باستخدام MSEMS Exchange MAPI Provider ، الذي يمكنه التحدث إلى Exchange باستخدام RPC (Exchange 2013 لم يعد يدعمه) أو RPC-Over-HTTP (Exchange 2007 أو أحدث) أو MAPI-Over-HTTP (Exchange 2013 وأحدث).

    لا يمكن الوصول إلى واجهة برمجة التطبيقات نفسها إلا من C ++ غير المدير أو دلفي. تستطيع ايضا استخذام الخلاص (أي لغة) - لها RDO عائلة الكائنات هي غلاف MAPI ممتد. لاستخدام MAPI الموسع ، تحتاج إلى تثبيت إما Outlook أو نسخة مستقلة (تبادل) من MAPI (بناءً على الدعم الممتد ، ولا يدعم ملفات Unicode PST و MSG ولا يمكنها الوصول إلى Exchange 2016). يمكن استخدام MAPI الممتد في الخدمة.

    يمكنك اللعب باستخدام API باستخدام Outlookspy أو MFCMAPI.

  3. نموذج كائن Outlook - لا تبادل محدد ، ولكنه يسمح بالوصول إلى جميع البيانات المتاحة في Outlook على الجهاز الذي يتم تشغيل الكود. لا يمكن استخدامها في الخدمة.

  4. برنامج Exchange ActiveSync. لم تعد Microsoft تستثمر أي موارد مهمة في هذا البروتوكول.

  5. Outlook المستخدمة لتثبيت مكتبة CDO 1.21 (تلتف MAPI الممتدة) ، ولكن تم إهمالها من قبل Microsoft ولم تعد تتلقى أي تحديثات.

  6. اعتاد أن يكون هناك غلاف .NET MAPI من طرف ثالث يسمى MAPI33 ، ولكن لم يعد يتم تطويره أو دعمه.

  7. WebDAV - انخفاض.

  8. كائنات البيانات التعاونية للتبادل (CDOEX) - تم إهمالها.

  9. Exchange Ole DB مزود (Exoledb) - تم إهماله.

فيما يلي بعض التعليمات البرمجية القديمة التي كنت أضعها حول 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; }
    }
}

لقد استخدمت الكود الذي كان نشرت على codeproject.com. إذا كنت ترغب في استخدام POP3 ، فهي واحدة من أفضل الحلول التي وجدتها.

إذا تم تكوين خادم Exchange الخاص بك لدعم POP أو IMAP ، فهذه طريقة سهلة للخروج.

خيار آخر هو الوصول إلى WebDav. هناك مكتبة متاح لذلك. قد يكون هذا أفضل خيار لك.

أعتقد أن هناك خيارات تستخدم كائنات COM للوصول إلى Exchange ، لكنني لست متأكدًا من مدى سهولة ذلك.

كل هذا يتوقف على ما يرغب المسؤول الخاص بك بالضبط لمنحك الوصول إلى ما أعتقد.

يجب أن تكون قادرًا على استخدام MAPI للوصول إلى صندوق البريد والحصول على المعلومات التي تحتاجها. لسوء الحظ ، يبدو أن مكتبة .NET MAPI (MAPI33) التي أعرف أنها غير محفوظة. كان هذا وسيلة رائعة للوصول إلى MAPI من خلال .NET ، لكن لا يمكنني التحدث إلى فعاليتها الآن. هناك المزيد من المعلومات حول المكان الذي يمكنك الحصول عليه هنا: تنزيل موقع mapi33.dll؟

حصلت على حل يعمل في النهاية باستخدام الفداء ، وإلقاء نظرة على هذه الأسئلة ...

خيار واحد هو استخدام Outlook. لدينا تطبيق Mail Manager الذي يصل إلى خادم 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);
        }
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top