ExchangeService.FindFolders not returning any folders - c#

I have a function which loops through a number of defined folders in a mailbox. Each of the folders contains another folder called "Complete". The below code finds this "Complete" folder and gets its FolderId.
When run, the code works fine then after a while FindFoldersResults findFolderProcessed = service.FindFolders(folder.Id, new SearchFilter.IsEqualTo(FolderSchema.DisplayName, "Complete"), view); returns no folders. Stepping through the code, everything seems like it should work, but findFolderProcessed.Folders is empty.
Why would it work for a number of folders then stop?
ServicePointManager.ServerCertificateValidationCallback =
((sender, certificate, chain, sslPolicyErrors) => true);
ExchangeService service = new ExchangeService(ExchangeVersion.Exchange2010_SP2);
service.Credentials = new NetworkCredential("xxx", "xxx", "xxx");
service.AutodiscoverUrl("xxx#xxx.com");
service.Url = new Uri("https://xxx/ews/exchange.asmx");
FolderView view = new FolderView(int.MaxValue);
view.PropertySet = new PropertySet(BasePropertySet.IdOnly);
view.PropertySet.Add(FolderSchema.DisplayName);
view.Traversal = FolderTraversal.Deep;
SearchFilter[] parameters = new SearchFilter[3];
parameters[0] = new SearchFilter.IsEqualTo(FolderSchema.DisplayName, "x1");
parameters[1] = new SearchFilter.IsEqualTo(FolderSchema.DisplayName, "x2");
parameters[2] = new SearchFilter.IsEqualTo(FolderSchema.DisplayName, "x3");
SearchFilter.SearchFilterCollection filterCollection = new SearchFilter.SearchFilterCollection(LogicalOperator.Or, parameters);
FindFoldersResults findFolder = service.FindFolders(new FolderId(WellKnownFolderName.Inbox, new Mailbox("xxx#xxx.com")), filterCollection, view);
foreach (Folder folder in findFolder.Folders)
{
//FindFoldersResults tempResults = service.FindFolders(folder.Id, view);
FindFoldersResults findFolderProcessed = service.FindFolders(folder.Id, new SearchFilter.IsEqualTo(FolderSchema.DisplayName, "Complete"), view);
FolderId ProcessedFolderID = findFolderProcessed.Folders[0].Id;
//Other Processing
}
EDIT: Example Folder structure
x1
-> Complete
x2
-> Complete
x3
-> Complete
...
xn
-> Complete
There are around 50 folders, structured the exact same way.

So the issue was that service.FindFolders was returning duplicate folders and the loop was trying to process the folders twice. So it processed the folders correctly the first time around, but on the second go it was causing this issue.
I don't know why it would be returning duplicates, but to fix it I simply deduped findFolder by using the below code in place of foreach (Folder folder in findFolder.Folders):
var folderCollection = findFolder.Folders.GroupBy(x => x.DisplayName).Select(g => g.First());
foreach (Folder folder in folderCollection)
If anyone knows why the folders would have been duplicated in the initial service.FindFolders call, feel free to comment below.

Related

How do I check if folder and sub folder exist in Outlook using EWS Web Service & C#

I'm very new to C# development.
I'm trying to check and create a folder/ sub-folder exist in Outlook Mailbox using Exchange Web Service.
Folder Structure
MAIN_folder
Sub Folder-1
Sub Folder-2
Sub Folder-3
Implementation
public void checkFolderExistOrNot( String folder_name)
{
FolderView fv = new FolderView(100);
var findFoldersResults = exchangeService.FindFolders(
WellKnownFolderName.Inbox,
new SearchFilter.SearchFilterCollection(
LogicalOperator.Or,
new SearchFilter.ContainsSubstring(FolderSchema.DisplayName, folder_name)),
fv);
foreach (var folder in findFoldersResults)
{
if (folder is Folder)
{
if (folder.DisplayName == folder_name)
{
archiveFolderID = folder.Id;
}
}
}
//if archive folder not found create and assign the variable to the folderID
if (archiveFolderID == null)
{
Folder folder = new Folder(exchangeService);
folder.DisplayName = folder_name;
folder.Save(WellKnownFolderName.Inbox);
archiveFolderID = folder.Id;
}
}
checkFolderExistOrNot(MAIN_folder)
checkFolderExistOrNot(MAIN_folder.Sub Folder-1)
checkFolderExistOrNot(MAIN_folder.Sub Folder-2)
checkFolderExistOrNot(MAIN_folder.Sub Folder-3)
But this is only creating the Main folder under the inbox. It would be greatly appreciated if someone could help me to identify what is missing in my implementation.
Thanks in Advance.
The only way to tell if a folder exists is to search for it with your search because you don't specify the traversal in the Folderview it will always be shallow. If you specify a deep traversal in
FolderView fv = new FolderView(100);
fv.Traversal = FolderTraversal.Deep;
You should then be able to find the parent folder you want to create a new subfolder on. Your logic should work okay as long as you don't have any name clashes a different folder levels. Otherwise what I do is this Exchange Web Service FolderId for a folder created by user or Get to an Exchange folder by path using EWS
Have you given Microsoft Graph a look?
You can basically use it for anything in Microsoft 365. With you you can also achieve your goal.
You will need to create a GraphServiceClient and with it you can do the following to check if a folder exists:
string user = "emailAddressOfTheUser";
var parentFolderRequest = graphClient.Users[user].MailFolders.Inbox.ChildFolders
.Request()
.Filter($"startsWith(displayName, 'parentFolderName')");
var parentMailFolder = await parentFolderRequest.GetAsync(cancellationToken);
Once you have the parent folder you can get it's ID and once you know that you can search it for child folders:
var parentMailFolderID = parentMailFolder.First().Id;
var childFolderRequest = graphClient.Users[user].MailFolders[parentMailFolderID].ChildFolders
.Request()
.Filter($"startsWith(displayName, 'childFolderName')");
var childMailFolder = await parentFolderRequest.GetAsync(cancellationToken);
If the childMailFolder.Count > 0 then the folder exists, if not you create the child folder:
var childFolder = new MailFolder
{
DisplayName = "childFolderName",
IsHidden = false
};
await graphClient.Users[graphUser.Id]
.MailFolders[parentMailFolderID].ChildFolders
.Request()
.AddAsync(childFolder );

EWS Move Email to Nested Folder

For some reason when I attempt to produce the ID for a nested folder, I don't get any results in the console. Here is my code:
FolderView folderview = new FolderView(100);
folderview.PropertySet = new PropertySet(BasePropertySet.IdOnly);
folderview.PropertySet.Add(FolderSchema.DisplayName);
folderview.Traversal = FolderTraversal.Deep;
FindFoldersResults findFolderResults = service.FindFolders(WellKnownFolderName.Root, folderview);
foreach(Folder f in findFolderResults)
{
if(f.DisplayName == "DownloadedEmails")
{
Console.WriteLine(f.Id);
}
}
Am I doing anything wrong here? Here is the Mailbox Structure if it helps:
You either need to do the search recursively - find the top folder (Inbox), then find its child folder (DownloadedEmails) etc. - or (in your particular case), simply open the Inbox folder (it is a well known folder), then find its subfolder (DownloadedEmails).

Sharepoint return incorrect file version

In Sharepoint i have file with several history versions. I want delete all file version history, but api retrun me that we have 0 versions of file. Why so?
CamlQuery query = new CamlQuery();
query.ViewXml = "<View Scope='RecursiveAll'><RowLimit>50</RowLimit></View>";
List<ListItem> items = new List<ListItem>();
do
{
ListItemCollection listItemCollection = lst.GetItems(query);
ctx.Load(listItemCollection);
ctx.ExecuteQuery();
items.AddRange(listItemCollection);
foreach (var item in items)
{
try
{
var file = ctx.Web.GetFileByServerRelativeUrl(item.FieldValues["FileRef"].ToString());
ctx.Load(file);
ctx.Load(file.Versions);
ctx.ExecuteQuery();
var file = ctx.Web.GetFileByServerRelativeUrl(item.FieldValues["FileRef"].ToString());
You're using GetFileByServerRelativeUrl but you're passing in the file name. Use ServerRelativeUrl and you should be ok.
strange... I think the code seems fine :). Maybe just one small thing and I am not sure that it will do the trick but I would first init some variable to file.Versions and then after execute work on this variable. Something like:
var versions = file.Versions;
ctx.Load(file);
ctx.Load(versions);
ctx.ExecuteQuery();
foreach (FileVersion fileVersion in versions)
{
// check
}
I know... probably not this.. but it's always worth to check :).
Also be sure that the account that is running this code has the needed permissions to get versions. You may always define the account with network credentials like:
ctx.Credentials = new NetworkCredential(_username, _password, _domain);

EWS query result wierdness

I've got a strange problem with EWS. I am writing a console app which queries my inbox for messages with a subject containing 'Ref:' which is absolutely fine, I get a connection no problem, run the query, get some results. but strangely it is only returning messages that are from internal senders, any messages sent from outside the exchange organisation do not appear in the results.
ultimately I am going to be using a service account to connect to various mailboxes and find various emails with certain references in the subject....
Does anyone have any idea what might be going on? I've gone over it and over it and can't find any reason why it's doing it.
It's Exchange 2010 SP2
ExchangeService exchService = new ExchangeService(ExchangeVersion.Exchange2010_SP2);
exchService.Url = new System.Uri("https://xxx.xxxxxxxxx.co.uk/EWS/Exchange.asmx");
exchService.UseDefaultCredentials = true;
var userMailbox = new Mailbox("xxxx#xxxx.co.uk");
var inboxFolder = new FolderId(WellKnownFolderName.Inbox, userMailbox);
String qString = "subject:\"Ref:\"";
ItemView view = new ItemView(20);
view.PropertySet = new PropertySet(ItemSchema.Id);
try
{
FindItemsResults<Item> results = exchService.FindItems(inboxFolder, qString, view);
if (results.Items.Count > 0)
{
foreach (Item item in results.Items)
{
Console.WriteLine(item.Id);
if (item is EmailMessage)
{
EmailMessage bindMessage = EmailMessage.Bind(exchService, item.Id.ToString());
String sender = bindMessage.Sender.Address.ToString();
String Body = bindMessage.Body.Text.ToString();
Console.WriteLine("Sender: " + sender);
}
}
}
}

How do i obtain the conversation history folder from office365?

I am using EWS and wish to obtain the conversation history folder from Office365 Exchange Online.
It was possible to achieve it by the method of judging the folder with DisplayName by the acquisition of the child folder from the root folder.
However, the user can change the name to this folder.
Is there a method that judges from ExtendedProperty to solve this problem?
Moreover, is there an another way?
-code sample-
Folder folder = Folder.Bind(this._exchange, WellKnownFolderName.Root);
//acquire the total number of cases including the subfolder.
FolderView view = new FolderView(1);
view.Traversal = FolderTraversal.Deep;
FindFoldersResults result = folder.FindFolders(view);
//acquire All folders.
view.PageSize = result.TotalCount;
result = folder.FindFolders(view);
FindFoldersResults folders = folder.FindFolders(view);
foreach (var f in folders.Folders)
{
//I want to judge the history folder of the conversation here excluding the DisplayName property.
}
Please anyone provide a good idea ,samples.
regards.
To check if folder contains items from some conversation you can use something like that:
var filter = new SearchFilter.IsEqualTo(EmailMessageSchema.ConversationId, convId);
var itemView = new ItemView();
foreach (var f in folders.Folders)
{
var findResult = f.FindItems(filter, itemView);
}
Filter should restrict find results only to items that has property ConversationId equal to conversation you are interested in.

Categories

Resources