2012-10-02 26 views
5

Estoy intentando obtener el número de correos electrónicos no leídos de Exchange para usuarios específicos.EWS obtiene el recuento de correos electrónicos no leídos de todas las carpetas

soy capaz de obtener el número de correos electrónicos de la bandeja de entrada de este modo:

SearchFilter sf = new SearchFilter.SearchFilterCollection(LogicalOperator.And, new SearchFilter.IsEqualTo(EmailMessageSchema.IsRead, false)); 
ItemView view = new ItemView(int.MaxValue); 
FindItemsResults<Item> findResults = service.FindItems(WellKnownFolderName.Inbox, sf, view); 
int unreadCount = 0; 
foreach (EmailMessage i in findResults) 
    { 
     unreadCount++; 
    } 
label1.Text = unreadCount.ToString(); 

Esto funciona muy bien.
también soy capaz de obtener todas las subcarpetas es la bandeja de entrada:

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

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

El problema es que no soy capaz de combinar estos dos juntos.
Sé que puedo hacer un ciclo foreach anidado, pero me gustaría evitar eso.

Encontré esta pregunta: Exchange Web Services (EWS) FindItems within All Folders, pero se requiere al menos usar Outlook 2010 para crear la carpeta AllItems.

Sé que puedo crear SearchFilterCollection, pero ¿cómo agregarle reglas para que busque correos electrónicos no leídos en Inbox y en todas las subcarpetas?

EDIT:

Esto lo que he tratado de hacer hasta ahora:

private int getEmailCount() 
{ 
    int unreadCount = 0; 

    FolderView viewFolders = new FolderView(int.MaxValue) { Traversal = FolderTraversal.Deep, PropertySet = new PropertySet(BasePropertySet.IdOnly) }; 
    ItemView viewEmails = new ItemView(int.MaxValue) { PropertySet = new PropertySet(BasePropertySet.IdOnly) }; 
    SearchFilter unreadFilter = new SearchFilter.SearchFilterCollection(LogicalOperator.And, new SearchFilter.IsEqualTo(EmailMessageSchema.IsRead, false)); 

    FindItemsResults<Item> findResults = service.FindItems(WellKnownFolderName.Inbox, unreadFilter, viewEmails); 
    unreadCount += findResults.Count(); 

    FindFoldersResults inboxFolders = service.FindFolders(WellKnownFolderName.Inbox, viewFolders); 

    foreach (Folder folder in inboxFolders.Folders) 
    { 
     findResults = service.FindItems(folder.Id, unreadFilter, viewEmails); 
     unreadCount += findResults.Count(); 
    } 

    return unreadCount; 
    } 

Básicamente esto funciona, pero cuando he creado varias subcarpetas que empezó a funcionar muy lento.
¿En lugar de múltiples consultas puedo hacer una para obtener los mismos resultados?

Respuesta

4

He buscado un poco y creó esta función:

public void getEmailCount(Action<int> callback) 
    { 
     int unreadCount = 0; 

     FolderView viewFolders = new FolderView(int.MaxValue) { Traversal = FolderTraversal.Deep, PropertySet = new PropertySet(BasePropertySet.IdOnly) }; 
     ItemView viewEmails = new ItemView(int.MaxValue) { PropertySet = new PropertySet(BasePropertySet.IdOnly) }; 
     SearchFilter unreadFilter = new SearchFilter.SearchFilterCollection(LogicalOperator.And, new SearchFilter.IsEqualTo(EmailMessageSchema.IsRead, false)); 
     SearchFilter folderFilter = new SearchFilter.SearchFilterCollection(LogicalOperator.And, new SearchFilter.IsEqualTo(FolderSchema.DisplayName, "AllItems")); 

     FindFoldersResults inboxFolders = service.FindFolders(WellKnownFolderName.Root, folderFilter, viewFolders); 

     if (inboxFolders.Count() == 0)//if we don't have AllItems folder 
     { 
      //search all items in Inbox and subfolders 
      FindItemsResults<Item> findResults = service.FindItems(WellKnownFolderName.Inbox, unreadFilter, viewEmails); 
      unreadCount += findResults.Count(); 

      inboxFolders = service.FindFolders(WellKnownFolderName.Inbox, viewFolders); 
      foreach (Folder folder in inboxFolders.Folders) 
      { 
       findResults = service.FindItems(folder.Id, unreadFilter, viewEmails); 
       unreadCount += findResults.Count(); 
      } 
     } 
     else //AllItems is avilable 
     { 
      foreach (Folder folder in inboxFolders.Folders) 
      { 
       FindItemsResults<Item> findResults = service.FindItems(folder.Id, unreadFilter, viewEmails); 
       unreadCount += findResults.Count(); 
      } 
     } 

     callback(unreadCount); 
    } 

Básicamente se comprueba si tenemos AllItems carpeta de algunos asientos.
Si YES hacemos una consulta simple que devuelve todos los mensajes no leídos.
Si NO, seguimos todas las carpetas dentro de Inbox. Esto es más lento y depende de cuántas carpetas y niveles tengamos.

las correcciones y mejoras son bienvenidos :)

+0

código genial, pero incluye la carpeta de elementos eliminados al utilizar AllItems, lo que puede no ser ideal en todos los casos. – Zone12

+0

@ Zone12 - Acabo de verificar y, en mi caso, la carpeta 'AllItems' no incluye elementos eliminados. No digo que esto esté en todos los servidores, ya que no soy un experto en Exchange. Tal vez haya una configuración suave en Exchange, ¿qué elementos debería incluir la carpeta 'AllItems'? – Misiu

+0

¿Está obligado a crear instancias de '' SearchFilterCollection'' cuando coloca solo un '' SearchFilter'' en ellas? Esto parece excesivo. (Se aplica también a la pregunta original) – Chop

4
No

seguro de que es lo que estaba buscando, pero ... recibir correos electrónicos sin leer conteos ( bandeja de entrada/proyectos etc.):

int x = Folder.Bind(yourService, WellKnownFolderName.Inbox).UnreadCount; 
int y = Folder.Bind(yourService, WellKnownFolderName.Drafts).UnreadCount; 
return x + y; 

En este caso, el servicio se llama dos veces, pero las llamadas se emiten secuencialmente - no es lo suficientemente bueno.

Aunque, puede emitir ambas solicitudes al mismo tiempo y aumentar el tiempo de respuesta de su aplicación.

Ver this o cualquier tutorial que explica cómo crear una instancia de dos TPLtareas, los envía al programador tarea, esperar para ambos (WaitAll()) para completar y, al final, , recuperar sus resultados :)

Y, si desea obtener la cuenta de correo electrónico después de aplicar algunos filtros personalizados (no el filtro triviales 'no leído'), a continuación, asegúrese de que su ItemView objeto es ItemView (1), noItemView (int.MaxValue). A continuación, obtenga la cuenta total:

int n = findItemsResults.TotalCount; 

Ver el docs for TotalCount property.

De esta manera, la respuesta del servicio es bastante pequeña - contiene solo un elemento, pero (la respuesta) también lleva el recuento total ... Eso es lo que quiere, ¿no?

+1

Gracias por el código, lo comprobaré definitivamente :) – Misiu

0

Ejemplo de código para recuperar carpetas y sus recuentos. En este ejemplo, enumeramos todas las carpetas de primer nivel y las agregamos a una lista de carpetas de clase común, con un objeto NewMessageCount allí. La clave es la sección Folder.Bind (myService, folder.Id) .UnreadCount.

public List<Common.MailFolder> ListFolders() 
    { 
     try 
     { 
      List<Common.MailFolder> myFolders = new List<Common.MailFolder>(); 
      Common.MailFolder myFolder; 

      List<ExchangeFolder> myExchangeFolders = new List<ExchangeFolder>(); 

      FolderView myView = new FolderView(10); 
      myView.PropertySet = new PropertySet(BasePropertySet.FirstClassProperties, FolderSchema.DisplayName, FolderSchema.Id); 
      myView.Traversal = FolderTraversal.Shallow; 

      FindFoldersResults myResults = myService.FindFolders(WellKnownFolderName.MsgFolderRoot, myView); 

      foreach (Folder folder in myResults) 
      { 
       myFolder = new Common.ICE.MailFolder(); 
       myFolder.NewMessageCount = Folder.Bind(myService, folder.Id).UnreadCount; 
       myFolder.FolderId = folder.Id.ToString(); 
       myFolder.FolderName = folder.DisplayName; 
       myFolders.Add(myFolder); 
      } 

      return myFolders; 
     } 
     catch (Exception ex) 
     { 
      Logger.Log.Error("Exchange Helper - List Folders", ex, Utility.GetUserId()); 
      return null; 
     } 
    } 
1

Aquí está el código para obtener el recuento total no leído de un buzón.

  1. Encuentra todas las carpetas con recorrido profundo
  2. limitar el conjunto de propiedades de cada carpeta para la identificación, unreadcount, idioma (propósito forinformational)
  3. Algunas de las carpetas como calendarios, contactos no tienen esta propiedad para gestionar el caso

Limitaciones con este fragmento de código:

  1. Si el buzón contiene más de 1000 carpetas en Superior del almacén de información, entonces no va a obtener la completa recuento no leído total de
  2. Para manejar ese caso hacer finditems en un bucle hasta que no haya más artículos con misma lógica

Esto hace que solo una llamada Findfolders y trabajar en los resultados.

public static int GetTotalUnreadCount(ExchangeService ewsConnector) 
{ 
    int pagedView = 1000; 
    FolderView fv = new FolderView(pagedView) { Traversal = Microsoft.Exchange.WebServices.Data.FolderTraversal.Deep }; 
    fv.PropertySet = new PropertySet(BasePropertySet.IdOnly, FolderSchema.UnreadCount, FolderSchema.DisplayName); 

    FindFoldersResults findResults = ewsConnector.FindFolders(WellKnownFolderName.MsgFolderRoot, fv); 

    int totalUnreadCount = 0; 
    foreach (Folder f in findResults.Folders) 
    { 
     try 
     { 
      totalUnreadCount += f.UnreadCount; 
      Console.WriteLine("Folder [" + f.DisplayName + "] has [" + f.UnreadCount.ToString() + "] unread items."); 
     } 
     catch(Exception ex) 
     { 
      Console.WriteLine("Folder [" + f.DisplayName + "] does not have the unread property."); 
     } 
    } 

    Console.WriteLine("Mailbox has [" + totalUnreadCount.ToString() + "] unread items."); 

    return totalUnreadCount; 
} 
Cuestiones relacionadas