2010-02-20 4 views
8

Je crée un addon pour Outlook 2007 qui lit un élément de courrier lorsqu'il est reçu, puis le réécrit. L'extension fonctionne très bien et réécrit le courrier pour les éléments qui n'ont pas de règle Outlook qui les déplace dans un autre dossier. S'il y a une règle, c'est toujours correct dans environ 50% des cas. L'autre 50% du temps, la règle déplace l'article de courrier avant la fin de mon addon. Je reçois l'erreur suivante:VSTO: traiter le courrier en utilisant newmailex avant que les règles d'Outlook ne déplacent le courrier

"The operation cannot be performed because the object has been deleted."

J'utilise événement NewMailEx pour appeler ma fonction de réécriture:

private void ThisAddIn_Startup(object sender, System.EventArgs e) 
{ 
    this.Application.NewMailEx += new Outlook.ApplicationEvents_11_NewMailExEventHandler(olApp_NewMail); 
} 

Dans Outlook 2007, NewMailEx donne un ENTRYID pour le courrier. Ce ENTRYID est utilisé d'abord pour savoir quel objet de messagerie à utiliser:

Outlook.NameSpace outlookNS = this.Application.GetNamespace("MAPI"); 
Outlook.MAPIFolder mFolder = this.Application.Session.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderInbox); 
Outlook.MailItem mail; 
try 
{ 
    mail = (Outlook.MailItem)outlookNS.GetItemFromID(entryIDCollection, Type.Missing); 
} 
catch (Exception e) { Debug.WriteLine("exception with non-mail item " + entryIDCollection + ": " + e.ToString()); return; } 

Je pensais que je pouvais prendre ce ENTRYID (que le code ci-dessus fonctionne), et itérer tous mes dossiers (sur l'échange ainsi que sur mon ordinateur) à la recherche du même identifiant mail. Lorsque j'effectue enfin une itération à l'endroit où se trouve le mail, l'identifiant EntryID du mail déplacé est très différent de l'identifiant entryIDCollection. Peut-être que je vais à ce sujet dans le mauvais sens. Est-ce que quelqu'un sait comment empêcher l'événement de se propager jusqu'à ce que j'ai fini, ou comment traquer l'email déplacé?

Voici mon code pour parcourir les dossiers au cas où quelqu'un est curieux:

 try 
     { 
      mail.Subject = new_subj; 
      mail.Body = ""; 
      mail.HTMLBody = text; 
      mail.ClearConversationIndex(); 
      mail.Save(); 
     } 
     catch (Exception ex) 
     { 
      //It wasn't caught in time, so we need to find the mail: 
      ArrayList unreadFolders = new ArrayList(); 
      foreach (Outlook.Folder f in outlookNS.Folders) unreadFolders.Add(f); 

      while (unreadFolders.Count > 0) 
      { 
       Outlook.Folder currentFolder = unreadFolders[0] as Outlook.Folder; 
       Debug.WriteLine("reading folder: " + currentFolder.Name); 
       unreadFolders.RemoveAt(0); 


       foreach (Outlook.Folder f in currentFolder.Folders) unreadFolders.Add(f); 

       try 
       { 
        Outlook.Items items = currentFolder.Items.Restrict("[UnRead] = true"); 
        for (int itemNum = 1; itemNum <= items.Count; itemNum++) 
        { 
         if (!(items[itemNum] is Outlook.MailItem)) continue; 
         Outlook.MailItem m = items[itemNum]; 
         if (m.EntryID == entryIDCollection) 
         { 
          m.Subject = new_subj; 
          m.Body = ""; 
          m.HTMLBody = text; 

          m.ClearConversationIndex(); 
          m.Save(); 
          return; 
         } 

        } 
       } 
       catch (Exception exc) { } 
      } 

     } 

Répondre

5

Untested Idée: Si vous obtenez de manière fiable l'événement NewMailEx, marquez le courrier avec une propriété de l'utilisateur ou le kilométrage avec un GUID puis utilisez la recherche pour cela.

Cela peut ne pas fonctionner car vous ne pourrez peut-être pas entrer avant que la règle ne déplace le courrier.

Lorsque vous avez travaillé sur les modifications EntryId lorsque l'élément est déplacé.

Autre façon dont vous avez besoin de regarder les accessoires MAPI pour obtenir le PR_SEARCH_KEY qui dosent changement lorsque le courrier est déplacé.

+1

Super, ça l'a fait! Je l'ai fait saisir le PR_SEARCH_KEY juste quand le message est entré. J'ai également saisi le corps et le sujet. Puis j'ai modifié le sujet et le corps. Lorsque j'essaie de mettre à jour le corps/le sujet, et qu'il échoue, je le fais ensuite rechercher dans les dossiers et trouver le courrier correspondant. Bien que PR_SEARCH_KEY ne soit pas unique si l'article de courrier est copié (les deux copies peuvent partager le même PR_SEARCH_KEY), c'est très bien, parce que quand il arrive, je n'ai encore fait aucune copie. J'ai essayé de voter, mais je suis trop nouveau pour voter :(Je posterai mon code ci-dessous (à court de caractères de commentaire) – mdiehl13

5

La réponse de 76mel a bien fonctionné! Je posterai mon code résultant juste au cas où d'autres veulent faire quelque chose de similaire (je suis nouveau et pas sûr au sujet des règles de l'affichage beaucoup de code, désolé si elle est contre les règles):

private string getPRSearchKey(Outlook.MailItem m) 
{ 
    return m.PropertyAccessor.BinaryToString(m.PropertyAccessor.GetProperty("http://schemas.microsoft.com/mapi/proptag/0x300B0102")); 
} 

private void olApp_NewMail(string entryIDCollection) 
{ 
    Outlook.NameSpace outlookNS = this.Application.GetNamespace("MAPI"); 
    Outlook.MAPIFolder mFolder = this.Application.Session.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderInbox); 
    Outlook.MailItem mail; 

    string pr_search_key; 
    string old_subj; 
    string old_body; 
    try 
    { 
     mail = (Outlook.MailItem)outlookNS.GetItemFromID(entryIDCollection, Type.Missing); 
     pr_search_key = getPRSearchKey(mail); 
     //save the pr_search_key, subject, and body before the mailItem gets moved 
     // then we can work on it without worrying about them disappearing 
     old_subj = mail.Subject; 
     old_body = mail.Body; 
    } 
    catch (Exception e) { Debug.WriteLine("exception with non-mail item " + entryIDCollection + ": " + e.ToString()); return; } 

    // 
    // ... do stuff with the mail's body and subject 
    // 

    try 
    { 
     mail.Subject = new_subj; 
     mail.Body = ""; 
     mail.HTMLBody = text; 

     mail.ClearConversationIndex(); 
     mail.Save(); 
    } 
    catch (Exception ex) 
    { 
     //It wasn't caught in time, so we need to find the mail: 
     ArrayList unreadFolders = new ArrayList(); 
     foreach (Outlook.Folder f in outlookNS.Folders) unreadFolders.Add(f); 

     while (unreadFolders.Count > 0) 
     { 
      Outlook.Folder currentFolder = unreadFolders[unreadFolders.Count-1] as Outlook.Folder; 
      Debug.WriteLine("reading folder: " + currentFolder.Name); 
      unreadFolders.RemoveAt(unreadFolders.Count - 1); 


      foreach (Outlook.Folder f in currentFolder.Folders) unreadFolders.Add(f); 

      try 
      { 
       Outlook.Items items = currentFolder.Items.Restrict("[UnRead] = true"); 
       for (int itemNum = 1; itemNum <= items.Count; itemNum++) 
       { 
        if (!(items[itemNum] is Outlook.MailItem)) continue; 
        Outlook.MailItem m = items[itemNum]; 
        if (getPRSearchKey(m) == pr_search_key) 
        { 
         m.Subject = new_subj; 
         m.Body = ""; 
         m.HTMLBody = text; 

         m.ClearConversationIndex(); //don't think this works 
         m.Save(); 
         return; 
        } 

       } 
      } 
      catch (Exception exc) { } 
     } 

    } 
} 

BTW, Quelque chose que je vais probablement changer, c'est que je passerai l'interrogation de certains dossiers pour l'accélérer (Journal, Articles supprimés, Courrier indésirable, Brouillons, Flux RSS, Microsoft à la maison, Tâches, Notes, Contacts, Calendrier, Éléments envoyés, Boîte d'envoi).

+0

Aussi, parfois quand je reçois le newmailex le courrier a déjà été déplacé J'ai modifié ma première instruction catch de sorte que si pr_search_key == "", récupère tous les éléments de mail non lus, et vérifie si je les ai encore modifiés ... c'est gentil. Un autre problème que j'ai vu est que quand mon ordinateur sort du sommeil, tous les nouveaux emails reçus n'envoient pas un newmailex, et donc tous ceux-ci sont manqués. Très ennuyeux – mdiehl13

+0

Cette réponse est assez ancienne, mais utilisez-vous toujours cela? http://schemas.microsoft.com/mapi/proptag/0x300B0102 ne semble plus fonctionner. – Jimmy

+0

Non, désolé. J'ai arrêté de l'utiliser il y a quelques années lorsque j'ai changé d'entreprise. Désolé je ne peux pas aider – mdiehl13

Questions connexes