For example, how do I know how many email items in inbox folder?
FindItemsResults findResults = service.FindItems(
WellKnownFolderName.Inbox,
new ItemView(10,0));
The above code only lists first 10 items, how to know how many items in inbox folder, so that I can calculate how many pages with 10 items in one page.
Maybe Folder.TotalCount Property?
Related
I am writing a C# application where I want to loop through the 500 most recent emails in a given folder. The reason is because getting all the emails takes a long time using the below lines:
MAPIFolder folder = outlookApp.GetNamespace("MAPI").GetDefaultFolder(OlDefaultFolders.olFolderInbox);
List<MailItem> items = folder.Items.OfType<MailItem>().ToList();
However, I know that what I am searching for each time is always going to be a recent email, so there's no need to get an entire year's worth of emails each time (over 8000, and I get less emails than the average employee at my job).
So, is there a way to only retrieve a certain amount of emails from a folder with Microsoft.Office.Interop.Outlook? Thanks in advance.
Iterating over all items in the folder is not really a good idea:
List<MailItem> items = folder.Items.OfType<MailItem>().ToList();
Instead, you need to use the Find/FindNext or Restrict methods of the Items class. They allow getting only items that correspond to your conditions. Read more about these methods in the following articles:
How To: Use Find and FindNext methods to retrieve Outlook mail items from a folder (C#, VB.NET)
How To: Use Restrict method to retrieve Outlook mail items from a folder
Instead of getting recent 500 emails you may retrieve emails for a day, few days, week and etc. So, you can process items in bunch. For example:
criteria = "[ReceivedTime] > '" _
& Format$("6/12/20 3:30PM","General Date") & "'"
You may find the Filtering Items Using a Date-time Comparison article helpful.
I want to be able to apply a SearchFilter based off the Item Id when I find all items in a selection of folders.
I can easily get all items and then using linq apply a where clause like
(w => !uniqueItemIdList.Contains(w.Id.UniqueId))
But the issue is this would be after it's pulled 1000's of mail items instead of during the original find of the items.
My goal is to pull all emails copy them to a db then afterwards to only pull emails that I haven't already copied by excluding emails with matching unique ids.
So far everything indicates that this isn't possible and that I could only search on individual fields like FolderId = "..." or subject that contains "...", with no mention of a list or exclusion.
Any help would be much appreciated.
ItemId isn't a searchable property so what you trying to do with a SearchFilter won't work. SyncFolderItems https://msdn.microsoft.com/en-us/library/office/aa563967(v=exchg.150).aspx does allow an exclusion list based on ItemId (but I would think for a large number of items this wont scale) an easier solution would be just use a SearchFilter based on Item Creation Date.
The task is to move multiple items from one folder to another without using any loops (which basically move 1 item at a time and then repeat the process again and again). In fact, I am talking about C# equivalent of choosing multiple items in folder in Outlook and moving them elsewhere. Is there a way of doing this, or am I stuck with loops anyway here? Thanks in advance.
Yes you can move items without using a loop using EWS API.The do while loop used here is to loop through the pages as the ItemView has a pagesize of 100. You can change this logic as you wish. But I haven't looped through the findResults which is a set of emails.
Here I am assuming that the folder 'Test' is under the root folder. If the folder is a subfolder under Inbox change it to WellKnownFolderName.Inbox
List<SearchFilter> searchFilterCollection = new List<SearchFilter>();
searchFilterCollection.Add(new SearchFilter.IsEqualTo(EmailMessageSchema.IsRead, false));
SearchFilter searchFilter = new SearchFilter.SearchFilterCollection(LogicalOperator.And, searchFilterCollection);
ItemView view = new ItemView(100);
view.PropertySet = new PropertySet(BasePropertySet.IdOnly, ItemSchema.Subject);
view.Traversal = ItemTraversal.Shallow;
FindItemsResults<Item> findResults;
do
{
findResults = service.FindItems(new FolderId(WellKnownFolderName.Inbox, new Mailbox(user)), searchFilter, view);
var itemIds = from item in findResults
select item.Id;
service.MoveItems(itemIds,
(Folder.Bind(service, WellKnownFolderName.MsgFolderRoot)
.FindFolders(new SearchFilter.IsEqualTo(FolderSchema.DisplayName, "Test"), new FolderView(1))
.FirstOrDefault(x => x.DisplayName == "Test")).Id);
view.Offset = Convert.ToInt32(findResults.NextPageOffset);
} while (findResults.MoreAvailable);
While it would occasionally be nice to be able to move a bunch of messages at once, the simple answer is you can't.
The EWS API does not provide a method for moving a list of messages all at once, only a method for moving an individual message to a different folder. As such you are stuck with looping through your messages and moving them individually.
Which, incidentally, is how Outlook seems to do it... so in that regard you're at least fulfilling that requirement :)
I think you need a loop like foreach, while to iterate through the collection of your selected mail items.
The Outlook object model doesn't provide any method for moving multiple items at once. Use the Move method of the MailItem class for moving items in the loop.
On the Extended MAPI level (C++ or Delphi only), IMAPIFolder::CopyMessages(MESSAGE_MOVE ) takes a list of entry ids and thus allows to move or copy multiple messages in a single call.
Outlook Object Model however only allows to copy or move one message at a time. If using Redemption (I am its author - any language) is an option, it exposes RDOFolder.Items.MoveMultiple / CopyMultiple methods that take a list of ";" or CR/LF separated entry ids or an array of entry id or items.
I have a problem of iterating lists, and lists and lists, they are nested means each list cell contains another list:
here is the problem:
my excel file which contains paths of pages, i need to add more cells under
these cells:
**admin/myPage.asp**
*add--> admin/myPage1.asp
add--> admin/myPage2.asp
add--> admin/myPage3.asp*
**admin/Dir/myPage.asp**
*add--> admin/Dir/myPage1.asp
add--> admin/Dir/myPage2.asp
add--> admin/Dir/myPage3.asp*
i searched this page: admin/myPage.asp, used htmlAgilityPack, found all links,
pages, redirects on this page,
pages found:
*admin/myPage1.asp
admin/myPage2.asp
admin/myPage3.asp*
need to note them under this page in excel,
then these pages also to be searched for further links:
pages found:
*admin/myPage1.asp
admin/myPage2.asp
admin/myPage3.asp*
if more links found then note them also
then search those pages,
until no further page found.
i am stuck here:
in nested lists how to iterate each list and
then found new list, then iterate this new list,
then find other list then iterate this list,
then come back to previous lists which have items pending.
how to do it in c#
background:
i have a list of paths, like this, "admin/start.asp", in excel, there are hundreds
of like this, i get them in list, and then loop over each path, each path
has page in it, on each page i have to extract all paths using HtmlAgilityPack,
and then the paths from this page are searched and get more paths from these pages,
until no more paths found in these pages, i have to keep on searching, but i have to
record them also in excel. any body have idea:
Thanks
You can try something like this:
var allListItems = new List(firstList);
for (int listItemIndex = 0; listItemIndex < allListItems.Count; listItemIndex++)
{
allListItems.AddRange(allListItems[listItemIndex].Items);
}
foreach (var listItem in allListItems)
{
//do something
}
With firstList being the list you start from.
This will basically do a breadth search by adding all the nested lists to allListItems and iterating through them. This works because allListItems.Count is recalculated for each iteration.
Afterwards you can just iterate through all the items and do whatever you want.
I am having an issue where I am trying to find at least one contact inside any of the outlook folders. I have a recursive function that iterates thru the items inside a folder and if the item is of type contact then we add it to a list. However, this code runs extremely slow when folders have a large number of records say 4000 items.
Is there any way just to get contacts or is there a way to make this code more efficient?
foreach (var item in folderBase.Items)
{
if (returnFirst && result.Count > 0)
break;
if ((item is Outlook.ContactItem))
{
result.Add((Outlook.ContactItem)item);
}
}
Firstly, storing 4000 live Outlook objects in a list is a bad idea: you will run out of RPC channels in case of online Exchange store at item 255. Store the entry ids and use them to call Namespace.GetItemFromID() when you actuqlly need it; then release it as soon as you are done.
Secondly, use MAPIFolder.GetTable - it will let you retrieve values from multiple items without actually opening them; perfect in your case. Try something like the following (VB script):
set Folder = Application.ActiveExplorer.CurrentFolder
set Table = Folder.GetTable("[MessageClass] = 'IPM.Contact' ")
Table.Columns.Add("EntryID")
while not Table.EndOfTable
set Row = Table.GetNextRow()
vEntryId = Row.Item(1)
Debug.Print vEntryId
wend
You need to use the Find/FindNext or Restrict methods of the Items class instead.
Read more about these methods and see the sample code in the following articles:
How To: Use Restrict method in Outlook to get calendar items
How To: Retrieve Outlook calendar items using Find and FindNext methods
You can use the MessageClass property of Outlook items to get the contact items only.