2010-02-20 16 views
8

Tôi đang tạo một addon cho Outlook 2007 đọc một mục thư khi nó được nhận, và sau đó viết lại nó. Addon hoạt động tốt và viết lại thư cho các mục không có quy tắc Outlook di chuyển chúng vào thư mục khác. Nếu có một quy tắc, nó vẫn còn tốt khoảng 50% thời gian. 50% thời gian khác, quy tắc di chuyển mục thư trước khi tiện ích của tôi kết thúc. Tôi nhận được lỗi sau:VSTO: xử lý thư bằng cách sử dụng newmailex trước khi quy tắc triển vọng di chuyển thư

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

Tôi đang sử dụng sự kiện NewMailEx để gọi chức năng viết lại tôi:

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

Trong Outlook 2007, NewMailEx đưa ra một entryID cho mail. entryID này được sử dụng lần đầu tiên để tìm ra những đối tượng mail để sử dụng:

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

Tôi nghĩ rằng tôi có thể mất entryID này (mà đoạn mã trên hoạt động), và lặp qua tất cả các thư mục của tôi (về ngoại cũng như trên máy tính của tôi) đang tìm kiếm cùng một id thư. Khi tôi cuối cùng lặp lại vị trí của thư, EntryID của thư đã chuyển rất khác với entryIDCollection.

Có thể tôi đang nói về điều này một cách sai lầm. Có ai biết làm thế nào để ngăn chặn các sự kiện tuyên truyền cho đến khi tôi làm xong, hoặc làm thế nào để theo dõi các email di chuyển?

Đây là mã của tôi để vượt qua các thư mục trong trường hợp bất cứ ai là tò mò:

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

     } 

Trả lời

5

chưa được kiểm tra Idea: Nếu bạn đang tin cậy nhận được sự kiện NewMailEx, đánh dấu Mail với thuộc tính người dùng hoặc mileage với một GUID và sau đó sử dụng Tìm kiếm cho điều đó.

Điều này có thể không hoạt động khi bạn không thể vào được trước khi Quy tắc di chuyển thư.

Khi bạn đã thực hiện các thay đổi EntryId, mục đó được di chuyển.

Cách khác bạn cần phải xem xét các đạo cụ MAPI để nhận được PR_SEARCH_KEY rằng thay đổi liều lượng khi thư được di chuyển xung quanh.

+1

Tuyệt vời, điều đó đã xảy ra! Tôi đã có nó lấy PR_SEARCH_KEY ngay khi thông điệp đến. Tôi cũng nắm lấy cơ thể và chủ đề. Rồi tôi chỉnh sửa chủ đề và cơ thể. Khi tôi thử và cập nhật nội dung/chủ đề, và nó không thành công, sau đó tôi tìm kiếm nó qua các thư mục và tìm thư phù hợp. Mặc dù PR_SEARCH_KEY không phải là duy nhất NẾU mục thư được sao chép (cả hai bản sao có thể chia sẻ cùng một PR_SEARCH_KEY), điều đó hoàn toàn ổn, bởi vì khi nó xuất hiện, tôi chưa tạo bất kỳ bản sao nào. Tôi đã cố gắng bỏ phiếu này, nhưng tôi quá mới để bỏ phiếu: (Tôi sẽ đăng mã của tôi dưới đây (chạy ra khỏi các ký tự bình luận) – mdiehl13

5

Câu trả lời của 76mel hoạt động tốt! Tôi gửi bài mã kết quả của tôi chỉ trong trường hợp người khác muốn làm điều gì đó tương tự (Tôi mới và không chắc chắn về các quy tắc của đăng rất nhiều mã, do đó xin lỗi nếu đó là chống lại các quy tắc):

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, cái gì đó mà tôi có thể thay đổi là tôi sẽ bỏ qua truy vấn một số thư mục để tăng tốc một chút (Tạp chí, Mục đã xóa, Thư rác, Thư nháp, Nguồn cấp RSS, Microsoft ở Nhà, Công việc, Ghi chú, Danh bạ, Lịch, Mục đã gửi, Hộp thư đi).

+0

Ngoài ra, đôi khi tôi nhận được newmailex thư đã được di chuyển (tìm thấy điều này Tôi đã sửa đổi câu lệnh bắt đầu của mình sao cho nếu pr_search_key == "", lấy tất cả các thư chưa đọc, và xem liệu tôi có sửa đổi chúng chưa ... kind've annoying. Một vấn đề khác mà tôi đã thấy là khi máy tính của tôi thoát ra khỏi giấc ngủ, bất kỳ email mới nào nhận được cũng không gửi một thư mới, và vì vậy tất cả những email này đều bị bỏ qua. Rất khó chịu – mdiehl13

+0

Câu trả lời này khá cũ, nhưng bạn vẫn đang sử dụng câu trả lời này? http://schemas.microsoft.com/mapi/proptag/0x300B0102 dường như không hoạt động nữa. – Jimmy

+0

Không, xin lỗi. Tôi đã ngừng sử dụng cách đây nhiều năm khi tôi thay đổi công ty. Xin lỗi tôi không thể giúp – mdiehl13