web-dev-qa-db-fra.com

Lire le courrier électronique MS Exchange en C #

J'ai besoin de pouvoir surveiller et lire les courriers électroniques d'une boîte aux lettres particulière sur un serveur MS Exchange (interne à ma société). Je dois également pouvoir lire l'adresse électronique de l'expéditeur, le sujet, le corps du message et télécharger une pièce jointe, le cas échéant.

Quelle est la meilleure façon de faire cela en utilisant C # (ou Vb.net)?

88
vajarov

C'est le bordel. MAPI ou CDO via un interop .NET DLL est officiellement non pris en charge par Microsoft - cela semblera bien fonctionner, mais il existe des problèmes de fuites de mémoire en raison de leurs différences modèles de mémoire.Vous pouvez utiliser CDOEX, mais cela ne fonctionne que sur le serveur Exchange lui-même, pas à distance; inutile. Vous pouvez interopérer avec Outlook, mais vous venez maintenant de créer une dépendance sur Outlook; overkill. Enfin, vous pouvez utiliser - prise en charge de WebDAV par Exchange 20 , mais WebDAV est compliqué, la prise en charge intégrée de .NET est médiocre, et (pour ajouter une insulte à la blessure), Exchange 2007 tombe presque complètement support de WebDAV.

Qu'est-ce qu'un gars à faire? J'ai fini par utiliser composant IMAP d'AfterLogic pour communiquer avec mon serveur Exchange 2003 via IMAP, et cela a très bien fonctionné. (Je cherche généralement des bibliothèques libres ou à code source ouvert, mais j’ai trouvé toutes les bibliothèques .NET qui me manquaient - en particulier en ce qui concerne certaines des bizarreries de la mise en œuvre IMAP de 2003 - et celle-ci était assez peu coûteuse et a fonctionné pour la première fois. essayez, je sais qu’il y en a d’autres.)

Si votre organisation est sur Exchange 2007, vous avez de la chance. Exchange 2007 est fourni avec une interface de service Web basée sur SOAP qui fournit enfin une manière unifiée, indépendante de la langue, d’interagir avec le serveur Exchange. Si vous pouvez faire de 2007+ une exigence, c'est certainement la voie à suivre. (Malheureusement pour moi, mon entreprise a une politique "mais 2003 n'est pas cassé".)

Si vous avez besoin de créer un pont entre Exchange 2003 et 2007, utilisez IMAP ou POP3.

89
Nicholas Piasecki

Euh,

Je suis peut-être un peu trop en retard ici, mais n’est-ce pas là le but de l’EWS?

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

Prend environ 6 lignes de code pour obtenir le courrier d'une boîte aux lettres:

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 );
}
64
War
  1. L'API actuellement préférée (Exchange 2013 et 2016) est EWS . Il est purement basé sur HTTP et est accessible depuis n’importe quel langage, mais il existe des bibliothèques spécifiques à . Net et Java .

    Vous pouvez utiliser EWSEditor pour jouer avec l'API.

  2. MAPI étend . C'est l'API native utilisée par Outlook. Il finit par utiliser le fournisseur MAPI Exchange MSEMS, qui peut communiquer avec Exchange à l'aide de RPC (Exchange 2013 ne le prend plus en charge), RPC sur HTTP (Exchange 2007 ou version ultérieure) ou MAPI sur HTTP (Exchange 2013 et plus récent).

    L’API elle-même ne peut être accédée qu’à partir de C++ non géré ou de Delphi . Vous pouvez également utiliser rédemption (toute langue) - sa RDO la famille d'objets est un wrapper MAPI étendu. Pour utiliser Extended MAPI, vous devez installer Outlook ou la version version autonome (de Exchange) de MAPI (avec prise en charge étendue, et elle ne prend pas en charge Unicode PST et MSG fichiers et ne peuvent pas accéder à Exchange 2016) .Le MAPI étendu peut être utilisé dans un service.

    Vous pouvez jouer avec l'API en utilisant OutlookSpy ou MFCMAPI .

  3. Modèle d'objet Outlook - non spécifique à Exchange, mais il permet d'accéder à toutes les données disponibles dans Outlook sur la machine sur laquelle le code est exécuté. Ne peut pas être utilisé dans un service.

  4. Exchange Active Sync . Microsoft n'investit plus aucune ressource importante dans ce protocole.

  5. Outlook avait l'habitude d'installer la bibliothèque CDO 1.21 (il englobe Extended MAPI), mais il était obsolète par Microsoft et ne recevait plus aucune mise à jour.

  6. Il existait auparavant un wrapper MAPI .Net tiers appelé MAPI33, mais il n'est plus en cours de développement ni pris en charge.

  7. WebDAV - obsolète.

  8. CDOEX (Collaborative Data Objects for Exchange) - obsolète.

  9. Exchange OLE Fournisseur de base de données (EXOLEDB) - obsolète.

17

Voici quelques vieux codes que je disposais pour faire WebDAV. Je pense que cela a été écrit contre Exchange 2003, mais je ne m'en souviens plus. N'hésitez pas à l'emprunter si c'est utile ...

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

Et 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; }
    }
}
10
CodingWithSpike

J'ai utilisé du code qui était publié sur CodeProject.com . Si vous voulez utiliser POP3, c'est l'une des meilleures solutions que j'ai trouvées.

1
Eldila

Si votre serveur Exchange est configuré pour prendre en charge POP ou IMAP, la solution est simple.

Une autre option est l’accès WebDAV. il y a un bibliothèque disponible pour cela. Cela pourrait être votre meilleure option.

Je pense qu'il existe des options utilisant des objets COM pour accéder à Exchange, mais je ne sais pas à quel point c'est facile.

Tout dépend de ce que votre administrateur est disposé à vous donner exactement, je suppose.

0
Denis Troller

Vous devriez pouvoir utiliser MAPI pour accéder à la boîte aux lettres et obtenir les informations dont vous avez besoin. Malheureusement, la seule bibliothèque MAPI .NET (MAPI33) que je connaisse ne semble pas être maintenue. C'était un excellent moyen d'accéder à MAPI via .NET, mais je ne peux pas parler de son efficacité pour le moment. Il y a plus d'informations sur où vous pouvez l'obtenir ici: Emplacement du téléchargement pour MAPI33.dll?

0
Chris Hynes

J'ai finalement trouvé une solution qui utilise Redemption. Consultez ces questions ...

0
Paul Rowland

Une option consiste à utiliser Outlook. Nous avons une application de gestion de courrier qui accède à un serveur Exchange et utilise Outlook comme interface. C'est sale mais ça marche.

Exemple de code:

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