2010-02-20 11 views
8

Tworzę dodatek do programu Outlook 2007, który odczytuje element poczty po otrzymaniu, a następnie przepisuje go. Dodatek działa świetnie i przepisuje pocztę dla elementów, które nie mają reguły programu Outlook, która przenosi je do innego folderu. Jeśli istnieje zasada, nadal jest w porządku w 50% przypadków. Pozostałe 50% czasu, reguła przesuwa element poczty, zanim mój dodatek się skończy. Pojawia się następujący błąd:VSTO: przetwarzanie poczty za pomocą newmailex przed przeniesieniem reguł programu Outlook

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

Używam zdarzenie NewMailEx zadzwonić mojej funkcji przepisywanie:

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

W programie Outlook 2007 NewMailEx daje entryID dla poczty. Ten entryID służy początkowo, aby dowiedzieć się, który obiekt mail aby użyć:

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

Myślałem, że mogę wykorzystać tę entryID (co powyższy kod działa), a iterację wszystkich moich folderach (na wymianę, jak również na moim komputerze) szukając tego samego identyfikatora poczty. Kiedy w końcu przejdę do miejsca, w którym znajduje się poczta, adres EntryID przeniesionej poczty bardzo różni się od entryIDCollection.

Może idę o tym w niewłaściwy sposób. Czy ktokolwiek wie, jak zatrzymać rozprzestrzenianie się zdarzenia, dopóki nie skończę, lub jak wyśledzić przeniesiony e-mail?

Oto mój kod na przejeżdżające foldery w przypadku niczyich ciekawy:

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

     } 

Odpowiedz

5

Nietestowane Idea: Jeśli niezawodnie coraz NewMailEx wydarzenie, Mark Mail z właściwości użytkownika lub przebieg z GUID a następnie użyj Szukaj tego.

To może nie działać, ponieważ możesz nie być w stanie wejść, zanim reguła przeniesie pocztę.

Tak jak już określiłeś, EntryId zmienia się, gdy element jest przenoszony.

W inny sposób należy spojrzeć na rekwizyty MAPI, aby uzyskać PR_SEARCH_KEY, który zmienia się, gdy poczta jest przenoszona.

+1

Świetnie, udało się! Miałem to chwycić PR_SEARCH_KEY prawo, kiedy wiadomość wszedł. Ja też chwyciłem ciało i temat. Potem zmodyfikowałem temat i ciało. Kiedy próbuję zaktualizować ciało/obiekt i nie powiedzie się, będę musiał przeszukać foldery i znaleźć pasującą pocztę. Chociaż PR_SEARCH_KEY nie jest unikalne, jeśli element poczty jest kopiowany (obie kopie mogą współdzielić to samo PR_SEARCH_KEY), to jest zupełnie w porządku, ponieważ kiedy to nastąpi, nie utworzyłem jeszcze żadnych kopii. Próbowałem to zagłosować, ale jestem za nowy, by głosować :(opublikuję mój kod poniżej (kończą się znaki komentarza) – mdiehl13

5

Odpowiedź 76mella działała świetnie! Jestem delegowania mój wygenerowany kod na wypadek, inni chcą zrobić coś podobnego (jestem nowy i nie jestem pewien co do zasad delegowania dużo kodu, więc przepraszam, jeśli jest to niezgodne z zasadami):

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, coś, co prawdopodobnie zmienię, pomijam wysyłanie zapytań do niektórych folderów, aby je przyspieszyć (Dziennik, Usunięte elementy, Wiadomości-śmieci, Wersje robocze, Kanały RSS, Microsoft w domu, Zadania, Notatki, Kontakty, Kalendarz, Pozycje wysłane, Skrzynka nadawcza).

+0

Czasami, gdy dostaję nową pocztę, poczta już została przeniesiona (znalazłem to out później.) Zmodyfikowałem moje pierwsze oświadczenie catch tak, że jeśli pr_search_key == "", chwyć wszystkie nieprzeczytane wiadomości i zobacz czy je jeszcze zmodyfikowałem ... rodzaj denerwujące. Inną kwestią, którą widziałem jest to, że gdy mój komputer wychodzi z trybu uśpienia, wszystkie otrzymane nowe wiadomości e-mail nie wysyłają newmaileksu, a więc wszystkie te są pomijane. Bardzo irytujące – mdiehl13

+0

Ta odpowiedź jest dość stara, ale nadal używasz tego? http://schemas.microsoft.com/mapi/proptag/0x300B0102 wydaje się już nie działać. – Jimmy

+0

Nie, przepraszam. Przestałem używać tego lata temu, kiedy zmieniłem firmy. Przepraszam, nie mogę pomóc – mdiehl13