2011-09-28 106 views
7

收件箱文件夾的所有子文件夾,我有以下收件箱文件夾結構:查找使用EWS

Inbox 
--ABC 
----ABC 2 
----ABC 3 
--XYZ 
----XYZ 2 
--123 
----123 A 
----123 B 
----123 C 

我使用Exchange Web服務和下面的代碼找到收件箱文件夾的子文件夾:

ExchangeService service = new ExchangeService(ExchangeVersion.Exchange2010); 

service.AutodiscoverUrl("[email protected]"); 
Mailbox mb = new Mailbox("[email protected]"); 

FindFoldersResults findResults = service.FindFolders(
    WellKnownFolderName.Inbox, 
    new FolderView(int.MaxValue)); 

foreach (Folder folder in findResults.Folders) 
{ 
    Console.WriteLine(folder.DisplayName); 
} 

這部分工作,因爲它返回ABC,XYZ和123文件夾;不幸的是,它不會返回這些文件夾(ABC 2,ABC 3,XYZ 2,123 A,123 B,123 C)中的每個文件夾。

此外,文件夾中可能有多個子文件夾級別。

我該如何編寫此代碼,以便它將返回所有子文件夾,而不管它們可能嵌套的深度如何?

回答

12

您可以告訴EWS在搜索文件夾時進行深度遍歷。您可以使用FolderView.Traversal屬性來執行此操作。然後,您的代碼將改爲類似如下的內容:

FindFoldersResults findResults = service.FindFolders(
    WellKnownFolderName.Inbox, 
    new FolderView(int.MaxValue) { Traversal = FolderTraversal.Deep }); 
1

您可以將網頁請求和從服務器獲取整個文件夾層次結構在短短的幾個電話。正如Jacob所說,關鍵是FolderView.Traversal財產。

例如,對於具有約1,300個文件夾的Exchange郵箱,下面的代碼僅發出2個請求。只要您停留在服務器限制或低於服務器限制的範圍內,就可以將頁面大小設置爲任何您喜歡的內容。

僅供參考:Exchange Online(Office365)在響應中上限爲1,000項。我還沒有測試過,因此在查詢內部部署Exchange Server時,我無法說出任何類似的限制。

using Microsoft.VisualBasic; 
using System; 
using System.Collections; 
using System.Collections.Generic; 
using System.Data; 
using System.Diagnostics; 
using Exchange = Microsoft.Exchange.WebServices.Data; 

static internal class Main 
{ 
    public static void Main() 
    { 
    Exchange.ExchangeService oService = default(Exchange.ExchangeService); 
    Dictionary<string, User> oUsers = default(Dictionary<string, User>); 

    oUsers = new Dictionary<string, User>(); 
    oUsers.Add("User1", new User("[email protected]", "Some-Fancy-Password1")); 
    oUsers.Add("User2", new User("[email protected]", "Some-Fancy-Password2")); 

    oUsers.ToList.ForEach((KeyValuePair<string, User> Credential) => { File.Delete(LOG_FILE_PATH.ToFormat(Credential.Key)); }); 

    oUsers.ToList.ForEach((KeyValuePair<string, User> Credential) => 
    { 
     LogFileName = Credential.Key; 

     Console.WriteLine("Getting message counts for mailbox [{0}]...", LogFileName); 
     Console.WriteLine(); 

     oService = Service.ConnectToService(Credential.Value); 

     GetAllFolders(oService, LOG_FILE_PATH.ToFormat(Credential.Key)); 

     Console.Clear(); 
    }); 

    Console.WriteLine(); 
    Console.Write("Press any key to exit..."); 
    Console.ReadKey(); 
    } 

    private static void GetAllFolders(Exchange.ExchangeService Service, string LogFilePath) 
    { 
    Exchange.ExtendedPropertyDefinition oIsHidden = default(Exchange.ExtendedPropertyDefinition); 
    List<Exchange.Folder> oFolders = default(List<Exchange.Folder>); 
    Exchange.FindFoldersResults oResults = default(Exchange.FindFoldersResults); 
    bool lHasMore = false; 
    Exchange.Folder oChild = default(Exchange.Folder); 
    Exchange.FolderView oView = default(Exchange.FolderView); 

    short nPageSize = 0; 
    short nOffSet = 0; 

    List<string> oPaths = default(List<string>); 
    List<string> oPath = default(List<string>); 

    oIsHidden = new Exchange.ExtendedPropertyDefinition(0x10f4, Exchange.MapiPropertyType.Boolean); 
    nPageSize = 1000; 
    oFolders = new List<Exchange.Folder>(); 
    lHasMore = true; 
    nOffSet = 0; 

    while (lHasMore) { 
     oView = new Exchange.FolderView(nPageSize, nOffSet, Exchange.OffsetBasePoint.Beginning); 
     oView.PropertySet = new Exchange.PropertySet(Exchange.BasePropertySet.IdOnly); 
     oView.PropertySet.Add(oIsHidden); 
     oView.PropertySet.Add(Exchange.FolderSchema.ParentFolderId); 
     oView.PropertySet.Add(Exchange.FolderSchema.DisplayName); 
     oView.PropertySet.Add(Exchange.FolderSchema.FolderClass); 
     oView.PropertySet.Add(Exchange.FolderSchema.TotalCount); 
     oView.Traversal = Exchange.FolderTraversal.Deep; 

     oResults = Service.FindFolders(Exchange.WellKnownFolderName.MsgFolderRoot, oView); 
     oFolders.AddRange(oResults.Folders); 

     lHasMore = oResults.MoreAvailable; 

     if (lHasMore) { 
     nOffSet += nPageSize; 
     } 
    } 

    oFolders.RemoveAll(Folder => Folder.ExtendedProperties(0).Value == true); 
    oFolders.RemoveAll(Folder => Folder.FolderClass != "IPF.Note"); 

    oPaths = new List<string>(); 

    oFolders.ForEach(Folder => 
    { 
     oChild = Folder; 
     oPath = new List<string>(); 

     do { 
     oPath.Add(oChild.DisplayName); 
     oChild = oFolders.SingleOrDefault(Parent => Parent.Id.UniqueId == oChild.ParentFolderId.UniqueId); 
     } while (oChild != null); 

     oPath.Reverse(); 
     oPaths.Add("{0}{1}{2}".ToFormat(Strings.Join(oPath.ToArray, DELIMITER), Constants.vbTab, Folder.TotalCount)); 
    }); 

    oPaths.RemoveAll(Path => Path.StartsWith("Sync Issues")); 

    File.WriteAllText(LogFilePath, Strings.Join(oPaths.ToArray, Constants.vbCrLf)); 
    } 

    private static string LogFileName; 
    private const string LOG_FILE_PATH = "D:\\Emails\\Remote{0}.txt"; 
    private const string DELIMITER = "\\"; 
} 

internal class Service 
{ 
    public static Exchange.ExchangeService ConnectToService(User User) 
    { 
    return Service.ConnectToService(User, null); 
    } 

    public static Exchange.ExchangeService ConnectToService(User User, Exchange.ITraceListener Listener) 
    { 
    Exchange.ExchangeService oService = default(Exchange.ExchangeService); 

    oService = new Exchange.ExchangeService(Exchange.ExchangeVersion.Exchange2013_SP1); 
    oService.Credentials = new NetworkCredential(User.EmailAddress, User.Password); 
    oService.AutodiscoverUrl(User.EmailAddress, RedirectionUrlValidationCallback); 

    if (Listener != null) { 
     oService.TraceListener = Listener; 
     oService.TraceEnabled = true; 
     oService.TraceFlags = Exchange.TraceFlags.All; 
    } 

    return oService; 
    } 

    private static bool RedirectionUrlValidationCallback(string RedirectionUrl) 
    { 
    var _with1 = new Uri(RedirectionUrl); 
    return _with1.Scheme.ToLower == "https"; 
    } 
} 

internal class User 
{ 
    public User(string EmailAddress) 
    { 
    _EmailAddress = EmailAddress; 
    _Password = new SecureString(); 
    } 

    public User(string EmailAddress, string Password) 
    { 
    _EmailAddress = EmailAddress; 
    _Password = new SecureString(); 

    Password.ToList.ForEach((char Chr) => { this.Password.AppendChar(Chr); }); 

    Password.MakeReadOnly(); 
    } 

    public static User GetUser() 
    { 
    User functionReturnValue = null; 
    string sEmailAddress = null; 
    ConsoleKeyInfo oUserInput = default(ConsoleKeyInfo); 

    Console.Write("Enter email address: "); 
    sEmailAddress = Console.ReadLine; 
    Console.Write("Enter password: "); 

    functionReturnValue = new User(sEmailAddress); 

    while (true) { 
     oUserInput = Console.ReadKey(true); 

     if (oUserInput.Key == ConsoleKey.Enter) { 
     break; // TODO: might not be correct. Was : Exit While 

     } else if (oUserInput.Key == ConsoleKey.Escape) { 
     functionReturnValue.Password.Clear(); 

     } else if (oUserInput.Key == ConsoleKey.Backspace) { 
     if (functionReturnValue.Password.Length != 0) { 
      functionReturnValue.Password.RemoveAt(functionReturnValue.Password.Length - 1); 
     } 

     } else { 
     functionReturnValue.Password.AppendChar(oUserInput.KeyChar); 
     Console.Write("*"); 

     } 
    } 

    if (functionReturnValue.Password.Length == 0) { 
     functionReturnValue = null; 
    } else { 
     functionReturnValue.Password.MakeReadOnly(); 
     Console.WriteLine(); 
    } 
    return functionReturnValue; 
    } 

    public string EmailAddress { get; } 

    public SecureString Password { get; } 
} 

internal class TraceListener : Exchange.ITraceListener 
{ 

    public void Trace(string TraceType, string TraceMessage) 
    { 
    File.AppendAllText("{0}.txt".ToFormat(Path.Combine("D:\\Emails\\TraceOutput", Guid.NewGuid.ToString("D"))), TraceMessage); 
    } 
} 

//======================================================= 
//Service provided by Telerik (www.telerik.com) 
//Conversion powered by NRefactory. 
//Twitter: @telerik 
//Facebook: facebook.com/telerik 
//======================================================= 
+1

Downvoted,因爲這是一個C#的問題。 – garfbradaz

+0

@garfbradaz:感謝你這麼說。我不同意這種說法,值得一提的是,翻譯現在已經很簡單 - 但這完全是另一個問題。因此,如果我編輯並轉換爲C#,那麼將在您的視圖中修復哪些內容? – InteXX

+2

@garfbradaz - 如果我翻譯成C#併發布了一個修改,那麼是否可以恢復投票? – InteXX