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.
Related
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 );
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).
I'm currently working on a project where I need to get Information from shared contacts (name, mailadress, etc) to compare multiple shared folders and find duplicate entries.
I'm coding in Visual Studio 2015. The program is just a console Application that creates an excel sheet, where the duplicate contacts are marked.
The Exchange Server is 2010 SP1.
The contacts are shared via E-Mail.
I have no problem to get acces to my own contacts. But I can't get to the folders that are shared to me.
I tried to follow this Guide.
But unfortunately this line gives me a nullpointer exception.
NameResolutionCollection ncCol = service.ResolveName(lnLegDN, ResolveNameSearchLocation.DirectoryOnly, true);
if (ncCol.Count > 0)
And further on I don't really understand what this part is supposed to to anyways, so I can't really fix it. It's my first time working with the EWS Managed API.
After changing the code I am able to get acces to the contacts folder from another mailbox. But that is not the folder that is shared to me.
So my question is, how can I get a contactsfolder that is named "CheckForDuplicates" for example. Is there a way?
Here is the code I changed in the above example. I'm getting the name of the mail box owner and than look for their contacts. After that I call a routine that gets the needed information from all contacts within that folder.
foreach (Item itItem in fiResults.Items)
{
object WlinkStoreEntryId = null;
if (itItem.TryGetProperty(PidTagWlinkStoreEntryId, out WlinkStoreEntryId))
{
string lookup = itItem.Subject;
string[] lookupArr = lookup.Trim().Split(new Char[] {'-'});
NameResolutionCollection ncCol = service.ResolveName(lookupArr[0], ResolveNameSearchLocation.DirectoryOnly, true);
if (ncCol.Count > 0)
{
try
{
Console.WriteLine(itItem.Subject);
FolderId SharedContactsId = new FolderId(WellKnownFolderName.Contacts, ncCol[0].Mailbox.Address);
Folder SharedContactFolder = Folder.Bind(service, SharedContactsId);
rtList.Add(ncCol[0].Mailbox.Address, SharedContactFolder);
}
catch (Exception exception)
{
Console.WriteLine(exception.Message);
}
}
}
}
I found the solution.
And it's way easier than expected.
I realized that I should look for Folders in the WellKnownFolderName.Root and not in WellKnownFolderName.Contacts.
Because the WellKnownFolderName.Contacts is reserved for the Contacts-Folder. And not like I thought for all contactfolders.
FolderId sharedRootFolderid = new FolderId(WellKnownFolderName.Root, ncCol[0].Mailbox.Address);
FolderView sharedFolderView = new FolderView(1000);
sharedFolderView .PropertySet = new PropertySet(BasePropertySet.IdOnly);
sharedFolderView .PropertySet.Add(FolderSchema.DisplayName);
sharedFolderView .Traversal = FolderTraversal.Deep;
SearchFilter testSearchFilter = new SearchFilter.IsEqualTo(FolderSchema.DisplayName, "CheckForDuplicates");
FindFoldersResults sharedContacts = service.FindFolders(sharedRootFolderid , testSearchFilter, sharedFolderView);
And that's already it.
I currently want to download all email messages (regardless in which folder they're in) to my SQL Server database.
Now while I know how to search for email messages or subscribe to streaming notifications, I've yet to learn on how to synchronize all messages from EWS to my database.
var emailMessages = GetItems<MSEmailMessage>(WellKnownFolderName.MsgFolderRoot);
foreach (var emailMessage in emailMessages)
{
Debug.WriteLine(emailMessage.Subject);
}
private IList<T> GetItems<T>(WellKnownFolderName wellKnownFolderName) where T : Item
{
IList<T> result = new List<T>();
Folder folder = Folder.Bind(_exchangeService, wellKnownFolderName);
if (folder.TotalCount > 0)
{
ItemView view = new ItemView(folder.TotalCount);
FindItemsResults<Item> items = _exchangeService.FindItems(wellKnownFolderName, view);
foreach (var resultItem in items.OfType<T>())
{
result.Add(resultItem);
}
}
return result;
}
This returns 0 email messages (it even threw an exception before checking for the folder.TotalCount before initializing a new ItemView...).
While checking for WellKnownFolderName.Inbox returns the email messages from the inbox, it does not allow me to query for sub folders to synchronize the entirety of the messages.
What am I missing?
You can build up a list of folders to search for mail in. Then iterate through each folder and get all the emails in that folder.
In the code snippet below we can create a folderSearchFilter with FolderTraversal set to Deep which will scan all sub folders of the target folder. We can then apply this filter to the two main well-known folders Inbox and SentItems
Once you have a list of folders to index, then you can use your own code to retrieve all the mails from that folder.
var view = new FolderView(int.MaxValue)
{
PropertySet = new PropertySet(BasePropertySet.FirstClassProperties) { FolderSchema.DisplayName }
};
SearchFilter foldersearchFilter = new SearchFilter.IsGreaterThan(FolderSchema.TotalCount, 0);
view.Traversal = FolderTraversal.Deep;
List<Folder> searchFolders;
try
{
searchFolders = new List<Folder>
{
Folder.Bind(ExchangeService, WellKnownFolderName.Inbox),
Folder.Bind(ExchangeService, WellKnownFolderName.SentItems)
};
}
catch (ServiceResponseException e) {}
searchFolders.AddRange(ExchangeService.FindFolders(WellKnownFolderName.Inbox, foldersearchFilter, view).Folders);
searchFolders.AddRange(ExchangeService.FindFolders(WellKnownFolderName.SentItems, foldersearchFilter, view).Folders);
var results = new List<Item>();
foreach (var searchFolder in searchFolders)
{
//Get all emails in this folder
}
Right, the root folder likely has 0 messages in it. When you do FindItems in a folder, the results don't bubble up from subfolders. You need to iterate over every folder if you want to get to their messages.
I am getting my default inbox folder via inboxFolder = Globals.ThisAddIn.Application.Session.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderInbox
Elsewhere in my code, I begin doing a foreach loop to extract specific information I want from these MailItems
foreach (var item in this.inboxFolder.Items)
{
Outlook.MailItem mailItem = (Outlook.MailItem)item;
//.... doing stuff here
string SenderEmail = mailItem.SenderEmailAddress;
string SenderName = mailItem.SenderName;
string FolderLocation = mailItem.???; //how to retrieve folder location?
//.... more stuff here
}
For example: A user may have created a subfolder called 'Test' shown below.
Thank you for the pointer guys. However I was having some trouble implementing the same initially. Here is how I solved it, just in case if some one faces the same issue.
Outlook.MAPIFolder parentFolder = mailItemToDelete.Parent as Outlook.MAPIFolder;
string FolderLocation = parentFolder.FolderPath;
The Parent object is dynamic and hence was causing issue.
Do you mean folder path? Use MAPIFolder.FullFolderPath. Or MAPIFoldert.Name if you only need the name.
Also keep in mind that the value will be the same for all items in the folder, so there is no reason to evaluate it on each step of the loop.