2010-02-20 17 views
8

Estoy creando un complemento para Outlook 2007 que lee un elemento de correo cuando se recibe y luego lo reescribe. El complemento funciona muy bien y reescribe el correo para los elementos que no tienen una regla de Outlook que los mueve a otra carpeta. Si hay una regla, todavía está bien aproximadamente el 50% del tiempo. El otro 50% de las veces, la regla mueve el elemento de correo antes de que termine mi complemento. Me sale el siguiente error:VSTO: procesar el correo utilizando newmailex antes de que las reglas de Outlook muevan el correo

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

estoy usando evento NewMailEx a llamar a mi función de reescritura:

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

En Outlook 2007, NewMailEx da una entryID para el correo. Este entryID se utiliza inicialmente para averiguar qué objeto de correo para utilizar:

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

pensé que podía tomar esta entryID (que funciona el código anterior), e iterar a través de todos mis carpetas (en el intercambio, así como en mi computadora) buscando la misma identificación de correo. Cuando finalmente repito hasta donde está el correo, el EntryID del correo movido es muy diferente al entryIDCollection.

Tal vez estoy haciendo esto de la manera incorrecta. ¿Alguien sabe cómo evitar que el evento se propague hasta que termine o cómo rastrear el correo electrónico movido?

Aquí está mi código para recorrer las carpetas por si alguien tiene curiosidad:

 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) { } 
      } 

     } 

Respuesta

5

Idea No comprobado: Si usted está recibiendo de manera fiable el Evento NewMailEx, marcan el correo con una propiedad de usuario o kilometraje con un GUID y luego usa Buscar para eso.

Esto puede no funcionar, ya que es posible que no pueda ingresar antes de que la Regla mueva el correo.

Como ha resuelto, EntryId cambia cuando se mueve el elemento.

Otra manera en que necesita ver los accesorios de MAPI para obtener PR_SEARCH_KEY que dosent cambia cuando se mueve el correo.

+1

Genial, ¡eso fue todo! Lo hice agarrar el PR_SEARCH_KEY a la derecha cuando llegó el mensaje. También agarré el cuerpo y el sujeto. Luego modifiqué el sujeto y el cuerpo. Cuando intento actualizar el cuerpo/asunto y falla, lo hago buscar entre las carpetas y encuentro el correo correspondiente. Aunque PR_SEARCH_KEY no es único SI se copia el elemento de correo (ambas copias pueden compartir el mismo PR_SEARCH_KEY), eso está perfectamente bien, porque cuando aparece, todavía no he hecho ninguna copia. Traté de votar esto, pero soy muy nuevo para votar :(Voy a publicar mi código a continuación (sin carácteres de comentarios) – mdiehl13

5

La respuesta de 76mel funcionó muy bien. Estoy publicar mi código resultante en caso de que otros quieren hacer algo similar (soy nuevo y no está seguro acerca de las reglas de la publicación de una gran cantidad de código, lo siento si es en contra de las reglas):

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) { } 
     } 

    } 
} 

por cierto, algo que probablemente cambiaré es omitir consultar ciertas carpetas para acelerarlo un poco (Diario, Elementos eliminados, Correo no deseado, Borradores, Fuentes RSS, Microsoft en el hogar, Tareas, Notas, Contactos, Calendario, Elementos enviados, Bandeja de salida).

+0

Además, a veces, cuando recibo el correo nuevo de Newmailex, ya se ha movido (encontré esto más tarde). Modifiqué mi primera instrucción catch de modo que si pr_search_key == "", tomo todos los elementos de correo no leídos, y veo si los he modificado todavía ... kind've molesto. Otro problema que he visto es que cuando mi computadora deja de funcionar, los correos electrónicos nuevos que se reciben no envían un newmailex, por lo que se pierden todos. Muy molesto – mdiehl13

+0

Esta respuesta es bastante antigua, pero ¿sigues usando esto? http://schemas.microsoft.com/mapi/proptag/0x300B0102 parece que ya no funciona. – Jimmy

+0

No, lo siento. Dejé de usar esto hace años cuando cambié de compañía. Lo siento, no puedo ayudar – mdiehl13

Cuestiones relacionadas