I have done the following in the code below but still getting a ServiceObjectPropertyException. I am obviously loading the property as advised here too . Please can anyone help point out what I am doing wrongly
this.ExchangeService = new ExchangeService(ExchangeVersion.Exchange2013);
this.ExchangeService.Credentials = new WebCredentials(mailBox, password);
this.ExchangeService.Url = new Uri("https://mail.xxxxxxxxxxx.com/EWS/Exchange.asmx");
PropertySet itemProperty = new PropertySet();
itemProperty.RequestedBodyType = BodyType.Text;
SearchFilter searchFilter = new SearchFilter.SearchFilterCollection(LogicalOperator.And, new SearchFilter.IsEqualTo(EmailMessageSchema.IsRead, false));
ItemView view = new ItemView(999);
view.PropertySet = itemProperty;
List<ExchangeMailResponse> emails = new List<ExchangeMailResponse>();
FindItemsResults<Item> emailMessage = this.ExchangeService.FindItems(WellKnownFolderName.Inbox, searchFilter, view);
foreach (Item mail in emailMessage)
{
ExchangeMailResponse email = new ExchangeMailResponse();
mail.Load(itemProperty);
email.Message = mail.Body.Text;
}
With the propertyset your trying to use because you haven't used the BasepropertySet overload and you haven't added any properties your only telling exchange to return the IdOnly. So at a basic level you need to at least add the Body property eg
itemProperty.Add(ItemSchema.Body);
However you won't be able to use that propertyset in the FindItems Operations so i would suggest you change your code something like
SearchFilter searchFilter = new SearchFilter.SearchFilterCollection(LogicalOperator.And, new SearchFilter.IsEqualTo(EmailMessageSchema.IsRead, false));
PropertySet FindItemPropertySet = new PropertySet(BasePropertySet.IdOnly);
ItemView view = new ItemView(999);
view.PropertySet = FindItemPropertySet;
PropertySet GetItemsPropertySet = new PropertySet(BasePropertySet.FirstClassProperties);
GetItemsPropertySet.RequestedBodyType = BodyType.Text;
FindItemsResults<Item> emailMessages = null;
do
{
emailMessages = service.FindItems(WellKnownFolderName.Inbox, searchFilter, view);
if (emailMessages.Items.Count > 0)
{
service.LoadPropertiesForItems(emailMessages.Items, GetItemsPropertySet);
foreach (Item Item in emailMessages.Items)
{
Console.WriteLine(Item.Body.Text);
}
}
} while (emailMessages.MoreAvailable);
Cheers
Glen
Related
Does anyone have examples of how to delete a user's SharePoint calendar link in Outlook/Exchange via EWS Managed API? I am able to successfully find the Calendar link item, however the item.Delete(DeleteMode.HardDelete) executes without actually removing the calendar link. Any help or guidance would be appreciated.
Edited to include code:
//Will target a specific user mailbox with parameter mbMailboxname
static Dictionary<string, Folder> GetSharedCalendarFolders(ExchangeService service, String mbMailboxname)
{
Dictionary<String, Folder> rtList = new System.Collections.Generic.Dictionary<string, Folder>();
DateTime startDate = new DateTime(2018, 8, 1);
DateTime endDate = new DateTime(2018, 8, 31);
CalendarView calView = new CalendarView(startDate, endDate);
Mailbox mb = new Mailbox(mbMailboxname);
FolderId rfRootFolderid = new FolderId(WellKnownFolderName.Root, mb);
FolderView fvFolderView = new FolderView(1000);
SearchFilter sfSearchFilter = new SearchFilter.IsEqualTo(FolderSchema.DisplayName, "Common Views");
FindFoldersResults ffoldres = service.FindFolders(rfRootFolderid, sfSearchFilter, fvFolderView);
if (ffoldres.Folders.Count == 1)
{
PropertySet psPropset = new PropertySet(BasePropertySet.FirstClassProperties);
ExtendedPropertyDefinition PidTagWlinkAddressBookEID = new ExtendedPropertyDefinition(0x6854, MapiPropertyType.Binary);
ExtendedPropertyDefinition PidTagWlinkGroupName = new ExtendedPropertyDefinition(0x6851, MapiPropertyType.String);
psPropset.Add(PidTagWlinkAddressBookEID);
ItemView iv = new ItemView(1000);
iv.PropertySet = psPropset;
iv.Traversal = ItemTraversal.Associated;
SearchFilter cntSearch = new SearchFilter.IsEqualTo(PidTagWlinkGroupName, "Other Calendars");
FindItemsResults<Item> fiResults = ffoldres.Folders[0].FindItems(cntSearch, iv);
foreach (Item itItem in fiResults.Items)
{
Microsoft.Exchange.WebServices.Data.Item foundItem = itItem;
if (foundItem.Subject.ToString().Trim().Contains("Company Group Calendar"))
{
Console.WriteLine("Deleting calendar..");
//Executing the delete command here does not delete the calendar
foundItem.Delete(DeleteMode.MoveToDeletedItems);
}
}
}
return rtList;
}
is it possible to retrieve only items with a certain flag status by using a SearchFilter?
For example, to retrieve all unread items, the search filter below is used:
SearchFilter sf = new SearchFilter.SearchFilterCollection(LogicalOperator.And, new SearchFilter.IsEqualTo(EmailMessageSchema.IsRead, false));
Is there an equivalent way to retrieve all items that don't have a completed flag assigned?
Thanks
You can do it using the pidTagFlagstatus extended property https://msdn.microsoft.com/en-us/library/office/cc842307.aspx eg if the value is 2 then is flagged if the value is 1 its complete eg
String MailboxToAccess = "user#domain.com";
ExtendedPropertyDefinition PR_FLAG_STATUS = new ExtendedPropertyDefinition(0x1090, MapiPropertyType.Integer);
ExtendedPropertyDefinition FlagRequest = new ExtendedPropertyDefinition(DefaultExtendedPropertySet.Common, 0x8530, MapiPropertyType.String);
SearchFilter sfSearchFilter = new SearchFilter.IsEqualTo(PR_FLAG_STATUS, 2);
PropertySet fiFindItemPropset = new PropertySet(BasePropertySet.FirstClassProperties);
fiFindItemPropset.Add(FlagRequest);
FolderId FolderToAccess = new FolderId(WellKnownFolderName.Inbox, MailboxToAccess);
ItemView ivItemView = new ItemView(1000);
ivItemView.PropertySet = fiFindItemPropset;
FindItemsResults<Item> FindItemResults = null;
do
{
FindItemResults = service.FindItems(FolderToAccess, sfSearchFilter, ivItemView);
foreach (Item itItem in FindItemResults.Items)
{
Console.WriteLine(itItem.Subject);
Object FlagValue = null;
if (itItem.TryGetProperty(FlagRequest, out FlagValue))
{
Console.WriteLine("Flag : " + FlagValue);
}
}
ivItemView.Offset += FindItemResults.Items.Count;
} while (FindItemResults.MoreAvailable);
I've got the following code:
private void ListCalendarFolders(ref List<EBCalendar> items, int offset)
{
var pageSize = 100;
var view = new FolderView(pageSize, offset, OffsetBasePoint.Beginning);
view.PropertySet = new PropertySet(BasePropertySet.FirstClassProperties);
view.PropertySet.Add(FolderSchema.DisplayName);
view.PropertySet.Add(FolderSchema.EffectiveRights);
view.Traversal = FolderTraversal.Deep;
FindFoldersResults findFolderResults = service.FindFolders(WellKnownFolderName.MsgFolderRoot, view);
foreach (Folder myFolder in findFolderResults.Folders)
{
if (myFolder is CalendarFolder)
{
var folder = myFolder as CalendarFolder;
items.Add(EBCalendar.FromEWSFolder(folder));
}
}
if (findFolderResults.MoreAvailable)
{
offset = offset + pageSize;
ListCalendarFolders(ref items, offset);
}
}
Where service is an ExchangeService instance. Unfortunately, it still lists folders that have been deleted, and it doesn't list shared calendars.
How can I get it to list all the shared calendars, and how can I get it to not include the folders that have been deleted?
By Shared Calendars do you mean the calendars under the other calendars node in Outlook ?
If so these Items are NavLinks that are stored in the Common Views folder in a Mailbox which is under the NonIPMSubtree (root) see http://msdn.microsoft.com/en-us/library/ee157359(v=exchg.80).aspx. You can use EWS to get the NavLinks from a Mailbox and use the PidTagWlinkAddressBookEID extended property to get the X500 address of the Mailbox these Links refer to and then use Resolve Name to resolve that to a SMTP Address. Then all you need to do is Bind to that folder eg
static Dictionary<string, Folder> GetSharedCalendarFolders(ExchangeService service, String mbMailboxname)
{
Dictionary<String, Folder> rtList = new System.Collections.Generic.Dictionary<string, Folder>();
FolderId rfRootFolderid = new FolderId(WellKnownFolderName.Root, mbMailboxname);
FolderView fvFolderView = new FolderView(1000);
SearchFilter sfSearchFilter = new SearchFilter.IsEqualTo(FolderSchema.DisplayName, "Common Views");
FindFoldersResults ffoldres = service.FindFolders(rfRootFolderid, sfSearchFilter, fvFolderView);
if (ffoldres.Folders.Count == 1)
{
PropertySet psPropset = new PropertySet(BasePropertySet.FirstClassProperties);
ExtendedPropertyDefinition PidTagWlinkAddressBookEID = new ExtendedPropertyDefinition(0x6854, MapiPropertyType.Binary);
ExtendedPropertyDefinition PidTagWlinkGroupName = new ExtendedPropertyDefinition(0x6851, MapiPropertyType.String);
psPropset.Add(PidTagWlinkAddressBookEID);
ItemView iv = new ItemView(1000);
iv.PropertySet = psPropset;
iv.Traversal = ItemTraversal.Associated;
SearchFilter cntSearch = new SearchFilter.IsEqualTo(PidTagWlinkGroupName, "Other Calendars");
// Can also find this using PidTagWlinkType = wblSharedFolder
FindItemsResults<Item> fiResults = ffoldres.Folders[0].FindItems(cntSearch, iv);
foreach (Item itItem in fiResults.Items)
{
try
{
object GroupName = null;
object WlinkAddressBookEID = null;
// This property will only be there in Outlook 2010 and beyond
//https://msdn.microsoft.com/en-us/library/ee220131(v=exchg.80).aspx#Appendix_A_30
if (itItem.TryGetProperty(PidTagWlinkAddressBookEID, out WlinkAddressBookEID))
{
byte[] ssStoreID = (byte[])WlinkAddressBookEID;
int leLegDnStart = 0;
// Can also extract the DN by getting the 28th(or 30th?) byte to the second to last byte
//https://msdn.microsoft.com/en-us/library/ee237564(v=exchg.80).aspx
//https://msdn.microsoft.com/en-us/library/hh354838(v=exchg.80).aspx
String lnLegDN = "";
for (int ssArraynum = (ssStoreID.Length - 2); ssArraynum != 0; ssArraynum--)
{
if (ssStoreID[ssArraynum] == 0)
{
leLegDnStart = ssArraynum;
lnLegDN = System.Text.ASCIIEncoding.ASCII.GetString(ssStoreID, leLegDnStart + 1, (ssStoreID.Length - (leLegDnStart + 2)));
ssArraynum = 1;
}
}
NameResolutionCollection ncCol = service.ResolveName(lnLegDN, ResolveNameSearchLocation.DirectoryOnly, false);
if (ncCol.Count > 0)
{
FolderId SharedCalendarId = new FolderId(WellKnownFolderName.Calendar, ncCol[0].Mailbox.Address);
Folder SharedCalendaFolder = Folder.Bind(service, SharedCalendarId);
rtList.Add(ncCol[0].Mailbox.Address, SharedCalendaFolder);
}
}
}
catch (Exception exception)
{
Console.WriteLine(exception.Message);
}
}
}
return rtList;
}
Cheers
Glen
You need to specify a searchfilter.
this is described here, though im not sure which Schema is the correct one, my guess would be Archieved.
So you would do something like this:
SearchFilter searchFilter = new SearchFilter.IsEqualTo(FolderSchema.Archieved, false);
FindFoldersResults findFolderResults = service.FindFolders(WellKnownFolderName.MsgFolderRoot,searchFilter, view);
Glen post is perfect but binding folder gives error. However i solved this. Instead of this line:
Folder SharedCalendaFolder = Folder.Bind(service, SharedCalendarId);
use the following line for shared folder binding
CalendarFolder calendar = CalendarFolder.Bind(service, new FolderId(WellKnownFolderName.Calendar, OwnerEmailAddress), new PropertySet());
Here OwnerEmailAddress is Email Address of Owner or you can write ncCol[0].Mailbox.Address if using Glen's code.
I need to get all the emails that have a specific category name, how would I do this?
Right now I have this:
var col = new List<SearchFilter>();
col.Add(new SearchFilter.ContainsSubstring(ItemSchema.Categories, "Processed"));
var filter = new SearchFilter.SearchFilterCollection(LogicalOperator.Or, col.ToArray());
FindItemsResults<Item> findResults = service.FindItems(
WellKnownFolderName.Inbox,
filter,
new ItemView(10)
);
But that gives me a Microsoft.Exchange.WebServices.Data.ServiceResponseException that says {"The Contains filter can only be used for string properties."}
How would I do it?
AFAIK as of Exchange 2010, category is a multi value field so it does not work with search filters. However, you can search categories using AQS. The following code should do the trick.
ExchangeService service = GetService();
var iv = new ItemView(1000);
string aqs = "System.Category:Processed";
FindItemsResults<Item> searchResult = null;
do
{
searchResult = service.FindItems(WellKnownFolderName.Inbox, aqs, iv);
foreach (var item in searchResult.Items)
{
Console.WriteLine(item.Subject);
}
iv.Offset += searchResult.Items.Count;
} while (searchResult.MoreAvailable == true);
I use the following code, to find all messages, which do NOT have set the category "Processed" and which have been received after a given date.
SearchFilter sf = new SearchFilter.SearchFilterCollection(LogicalOperator.And,
new SearchFilter.Not(new SearchFilter.IsEqualTo(EmailMessageSchema.Categories, "Processed")),
new SearchFilter.IsGreaterThan(EmailMessageSchema.DateTimeReceived, minDate));
ExchangeService service = this.GetService();
FolderId folderID = GetPublicFolderID(service, "My Address Book");
ContactsFolder folder = ContactsFolder.Bind(service, folderID);
int folderCount = folder.TotalCount;
var guid = DefaultExtendedPropertySet.PublicStrings;
var epdCP = new ExtendedPropertyDefinition(guid, "CustomProp", MapiPropertyType.Boolean);
var epdAccount = new ExtendedPropertyDefinition(guid, "Account", MapiPropertyType.String);
var epdCID = new ExtendedPropertyDefinition(guid, "CustomerID", MapiPropertyType.Integer);
var view = new ItemView(folderCount);
view.PropertySet = new PropertySet(BasePropertySet.FirstClassProperties);
view.PropertySet.Add(epdCP);
view.PropertySet.Add(epdAccount);
view.PropertySet.Add(epdCID);
var contacts = service.FindItems(folderID, view);
foreach (Contact contact in contacts)
{
bool CP;
string Account;
int CID;
contact.GetLoadedPropertyDefinitions();
contact.TryGetProperty(epdCP, out CP);
contact.TryGetProperty(epdAccuont, out Account);
contact.TryGetProperty(epdCID, out CID);
Console.WriteLine(String.Format("{0, -20} - {1} - {2}"
, contact.DisplayName
, contact.EmailAddresses[EmailAddressKey.EmailAddress1]
, CP
, Account
, CID
));
}
Goal is to get the Contact information out of a Public Address Book so I can sync it with another program we have.
For each Contact in the Public Address Book, this prints out DisplayName, EmailAddress and my Custom Property. No issues there.
The problem I have is I can't seem to get the right incantation to pull certain properties. CustomerID and Account are two examples that I can't seem to get to pull/print. They aren't "Custom", in as much as I haven't created them.
How can I get CustomerID and Account out of a contact via EWS?
The GUID isn't needed for the Account and CustomerID.. and the name needs to be the Unique ID:
var guid = DefaultExtendedPropertySet.PublicStrings;
var epdAccount = new ExtendedPropertyDefinition(0x3A00, MapiPropertyType.String);
var epdCID = new ExtendedPropertyDefinition(0x3A4A, MapiPropertyType.String);
var epdCP = new ExtendedPropertyDefinition(guid, "CustomBln", MapiPropertyType.Boolean);
var epdCI = new ExtendedPropertyDefinition(guid, "CustomInt", MapiPropertyType.Integer);
Now if only I can figure out why MapiPropertyType.Integer isn't mapping correctly.... Custom Boolean pulls properly, but Custom Integers aren't.
edit: Found that double works, where Integer doesn't.
var epdCI = new ExtendedPropertyDefinition(guid, "CustomInt", MapiPropertyType.Double);
Edited Example:
ExchangeService service = this.GetService();
FolderId folderID = GetPublicFolderID(service, "My Address Book");
ContactsFolder folder = ContactsFolder.Bind(service, folderID);
int folderCount = folder.TotalCount;
var guid = DefaultExtendedPropertySet.PublicStrings;
var epdAccount = new ExtendedPropertyDefinition(0x3A00, MapiPropertyType.String);
var epdCID = new ExtendedPropertyDefinition(0x3A4A, MapiPropertyType.String);
var epdCBLN = new ExtendedPropertyDefinition(guid, "CustomBln", MapiPropertyType.Boolean);
var epdCDBL = new ExtendedPropertyDefinition(guid, "CustomDbl", MapiPropertyType.Double);
var view = new ItemView(folderCount);
view.PropertySet = new PropertySet(BasePropertySet.FirstClassProperties);
view.PropertySet.Add(epdAccount);
view.PropertySet.Add(epdCID);
view.PropertySet.Add(epdCBLN);
view.PropertySet.Add(epdCDBL);
//var searchOrFilterCollection = new List<SearchFilter>();
//searchOrFilterCollection.Add(new SearchFilter.IsEqualTo(epdCBLN, true));
//searchOrFilterCollection.Add(new SearchFilter.IsEqualTo(epdAccount, "user"));
//var filter = new SearchFilter.SearchFilterCollection(LogicalOperator.And, searchOrFilterCollection);
var filter = new SearchFilter.IsEqualTo(epdAccount, "user");
var contacts = service.FindItems(folderID, filter, view);
foreach (Contact contact in contacts)
{
string Account;
int CID;
bool CBLN;
double CDBL;
contact.GetLoadedPropertyDefinitions();
contact.TryGetProperty(epdAccuont, out Account);
contact.TryGetProperty(epdCID, out CID);
contact.TryGetProperty(epdCBLN, out CBLN);
contact.TryGetProperty(epdCDBL, out CDBL);
Console.WriteLine(String.Format("{0, -20} - {1} - {2} - {3} - {4}"
, contact.DisplayName
, contact.EmailAddresses[EmailAddressKey.EmailAddress1]
, Account
, CID
, CBLN
, CDBL
));
}