I am trying to find the unique ID of a subfolder of the Inbox folder of a shared mail, named "Processed". When using WellKnownFolderName.Root and a deep traversal, I find alot of different folders. But using the WellKnownFolderName.Inbox shows me 0 folders, as if there is 0 subfolders of the Inbox folder, which is not true.
ExchangeService Service = new ExchangeService(ExchangeVersion.Exchange2013_SP1);
Service.UseDefaultCredentials = false;
Service.Credentials = new WebCredentials("xxxx", "xxxx");
Mailbox ProdSupportMailbox = new Mailbox("xxxx");
Service.AutodiscoverUrl("xxxx");
FolderView view = new FolderView(100);
view.PropertySet = new PropertySet(BasePropertySet.IdOnly);
view.PropertySet.Add(FolderSchema.DisplayName);
view.Traversal = FolderTraversal.Deep;
FindFoldersResults findFolderResults = Service.FindFolders(WellKnownFolderName.Inbox, view);
// Find specific folder
foreach(Folder f in findFolderResults)
{
if (f.DisplayName == "Processed")
Console.WriteLine(f.Id);
// etc
Related
I am trying to find the unique id of a folder in Outlook.
For some reason I keep getting an error with the AutoDiscoverUrl method, but I have no idea why. I have tried all the possible solutions on StackOverflow.
I am trying to run it in a commandline program using C#, and have commented/documented the code. I have used others' example on how to do this, but it doesn't work.
static void Main(string[] args)
{
// Set server binding
ExchangeService service = new ExchangeService(ExchangeVersion.Exchange2013_SP1);
service.UseDefaultCredentials = true;
// Set Credentials
service.Credentials = new WebCredentials("xxxx", "xxxxx", "xxxx");
service.UseDefaultCredentials = true;
service.Url = new Uri("https://outlook.office365.com/EWS/Exchange.asmx");
// Set the URL
service.AutodiscoverUrl("xxxx", Callback);
// Error Tracing
service.TraceEnabled = true;
// Redirect callback
// Set View
FolderView view = new FolderView(100);
view.PropertySet = new PropertySet(BasePropertySet.IdOnly);
view.PropertySet.Add(FolderSchema.DisplayName);
view.Traversal = FolderTraversal.Deep;
FindFoldersResults findFolderResults = service.FindFolders(WellKnownFolderName.Root, view);
// Find specific folder
foreach (Folder f in findFolderResults)
{
// Show FolderId of the folder "test"
if (f.DisplayName == "test")
{
Console.WriteLine(f.Id);
}
}
}
private static bool Callback(string redirectionUrl)
{
bool result = false;
var redirectionUri = new Uri(redirectionUrl);
if (redirectionUri.Scheme == "https")
{
result = true;
}
return result;
}
You could find the unique id of the folder using the below code:
ExchangeService Service = new ExchangeService(ExchangeVersion.Exchange2013_SP1);
Service.UseDefaultCredentials = false;
Service.Credentials = new WebCredentials("yourUserID", "yourPassword");
Mailbox ProdSupportMailbox = new Mailbox("ProdSupport#company.com");
Service.AutodiscoverUrl("ProdSupport#company.com");
FolderView view = new FolderView(100);
view.PropertySet = new PropertySet(BasePropertySet.IdOnly);
view.PropertySet.Add(FolderSchema.DisplayName);
view.Traversal = FolderTraversal.Deep;
FindFoldersResults findFolderResults = server.FindFolders(WellKnownFolderName.Root, view);
// find specific folder
foreach(Folder f in findFolderResults)
{
// show folderId of the folder "Test"
if (f.DisplayName == "Test")
{
Console.WriteLine(f.Id);
}
}
For more information, please refer to these links:
Exchange Web Service FolderId for a not well known folder name
Microsoft Exchange Web Services reading my local Outlook folders INSTEAD of another address
I'm trying to retrieve emails from multiple folders including Inbox, Sent, and some custom folders. I'm first filtering the folders so I can loop over them, calling FindItems to return their contents. The code below works without searchFilter4 (line 10), but with it I get this unhelpful error:
'Microsoft.Exchange.WebServices.Data.ServiceResponseException' in Microsoft.Exchange.WebServices.dll
My code:
// Folder name filter for Inbox, Completed, Inprogress, and Sent folders:
SearchFilter searchFilter1 = new SearchFilter.IsEqualTo(FolderSchema.DisplayName, "Inbox");
SearchFilter searchFilter2 = new SearchFilter.IsEqualTo(FolderSchema.DisplayName, "Completed");
SearchFilter searchFilter3 = new SearchFilter.IsEqualTo(FolderSchema.DisplayName, "In Progress");
SearchFilter searchFilter4 = new SearchFilter.IsEqualTo(, WellKnownFolderName.SentItems);
SearchFilter.SearchFilterCollection searchFilterCollection = new SearchFilter.SearchFilterCollection(LogicalOperator.Or);
searchFilterCollection.Add(searchFilter1);
searchFilterCollection.Add(searchFilter2);
searchFilterCollection.Add(searchFilter3);
searchFilterCollection.Add(searchFilter4);
// Find folders:
FindFoldersResults findResults = service.FindFolders(
WellKnownFolderName.MsgFolderRoot, searchFilterCollection,
new FolderView(int.MaxValue) { Traversal = FolderTraversal.Deep }
);
I figured it out while writing my question...
All I needed to do was add the folder to my findeResults after calling FindFolders with this line:
findResults.Folders.Add(Folder.Bind(service, WellKnownFolderName.SentItems));
My new code:
// Folder name filter for Inbox, Completed, Inprogress, and Sent folders:
SearchFilter searchFilter1 = new SearchFilter.IsEqualTo(FolderSchema.DisplayName, "Inbox");
SearchFilter searchFilter2 = new SearchFilter.IsEqualTo(FolderSchema.DisplayName, "Completed");
SearchFilter searchFilter3 = new SearchFilter.IsEqualTo(FolderSchema.DisplayName, "In Progress");
SearchFilter.SearchFilterCollection searchFilterCollection = new SearchFilter.SearchFilterCollection(LogicalOperator.Or);
searchFilterCollection.Add(searchFilter1);
searchFilterCollection.Add(searchFilter2);
searchFilterCollection.Add(searchFilter3);
// Find folders:
FindFoldersResults findResults = service.FindFolders(
WellKnownFolderName.MsgFolderRoot, searchFilterCollection,
new FolderView(int.MaxValue) { Traversal = FolderTraversal.Deep }
);
// Add SentItems to the findResults:
findResults.Folders.Add(Folder.Bind(service, WellKnownFolderName.SentItems));
Here is my code for obtaining some calendar items (appointments) from EWS. But this throws an exception all the time.
The Exception:-
The property can not be used with this type of restriction.
private void GetChangedAppointmentInformation(Appointment appointment)
{
try
{
// Save appointment details into local variables
id = appointment.Id.ToString();
body = appointment.Body;
duration = appointment.Duration;
end = appointment.End;
bookingKey = appointment.Subject;
subject = appointment.Subject;
location = appointment.Location;
ItemView view = new ItemView(1000);
// Create a search filter that filters email based on the existence of the extended property.
SearchFilter eq = new SearchFilter.IsEqualTo(AppointmentSchema.ICalUid, appointment.ICalUid);
// Search the Calendar with the defined view and search filter. This results in a FindItem operation call to EWS.
FindItemsResults<Item> findResults = service.FindItems(WellKnownFolderName.Calendar, eq, view);
}
catch (Exception ex)
{
Console.WriteLine("Error: " + ex.Message);
}
}
Can you please advise me on this? I tried MSDN and several other online resources, I'm still trying to figure that out.
The error is telling you that the strongly typed property you're trying to use can't be used in a restriction. The best workaround for this is to use the equivalent Extended Property instead eg to search based on a existing appointment something like
Appointment newAppointment = new Appointment(service);
newAppointment.Subject = "Test Subject";
newAppointment.Start = new DateTime(2012, 03, 27, 17, 00, 0);
newAppointment.StartTimeZone = TimeZoneInfo.Local;
newAppointment.EndTimeZone = TimeZoneInfo.Local;
newAppointment.End = newAppointment.Start.AddMinutes(30);
newAppointment.Save();
newAppointment.Body = new MessageBody(Microsoft.Exchange.WebServices.Data.BodyType.Text, "test");
newAppointment.RequiredAttendees.Add("attendee#domain.com");
newAppointment.Update(ConflictResolutionMode.AlwaysOverwrite ,SendInvitationsOrCancellationsMode.SendOnlyToAll);
ExtendedPropertyDefinition CleanGlobalObjectId = new ExtendedPropertyDefinition(DefaultExtendedPropertySet.Meeting, 0x23, MapiPropertyType.Binary);
PropertySet psPropSet = new PropertySet(BasePropertySet.FirstClassProperties);
psPropSet.Add(CleanGlobalObjectId);
newAppointment.Load(psPropSet);
object CalIdVal = null;
newAppointment.TryGetProperty(CleanGlobalObjectId, out CalIdVal);
Folder AtndCalendar = Folder.Bind(service, new FolderId(WellKnownFolderName.Calendar,"attendee#domain.com"));
SearchFilter sfSearchFilter = new SearchFilter.IsEqualTo(CleanGlobalObjectId, Convert.ToBase64String((Byte[])CalIdVal));
ItemView ivItemView = new ItemView(1);
FindItemsResults<Item> fiResults = AtndCalendar.FindItems(sfSearchFilter, ivItemView);
if (fiResults.Items.Count > 0) {
//do whatever
}
Should work okay
Cheers
Glen
I want to select the user "test" so I can create a contact into his mailbox.
My actual problem is that it will create Contacts into my user "c-sharp".
"c-sharp" has full access on "test" mailbox
I changed the IP and the contact infos users are also only for testing.
ExchangeService service = new ExchangeService(ExchangeVersion.Exchange2013);
service.TraceEnabled = true;
service.TraceFlags = TraceFlags.All;
service.EnableScpLookup = false;
service.Credentials = new WebCredentials("c-sharp", "c-sharp", "domain");
service.UseDefaultCredentials = false;
IgnoreBadCertificates();
service.Url = new Uri("https://192.000.000.000/EWS/Exchange.asmx");
Contact contact = new Contact(service);
// Specify the name and how the contact should be filed.
contact.GivenName = "n.a.";
contact.FileAsMapping = FileAsMapping.SurnameCommaGivenName;
contact.DisplayName = "bau gmbh";
// Specify the company name.
contact.CompanyName = "bau";
// Specify the business, home, and car phone numbers.
contact.PhoneNumbers[PhoneNumberKey.BusinessPhone] = "00000 00000";
contact.PhoneNumbers[PhoneNumberKey.MobilePhone] = "n.a.";
contact.PhoneNumbers[PhoneNumberKey.BusinessFax] = "00000 00000";
// Specify two email addresses.
contact.EmailAddresses[EmailAddressKey.EmailAddress1] = new EmailAddress("e#mail.de");
//homepage
contact.BusinessHomePage = "n.a.";
// Specify the home address.
PhysicalAddressEntry paEntry1 = new PhysicalAddressEntry();
paEntry1.Street = "straße";
paEntry1.City = "stadt";
paEntry1.State = "D";
paEntry1.PostalCode = "88890";
paEntry1.CountryOrRegion = "Deutschland";
contact.PhysicalAddresses[PhysicalAddressKey.Home] = paEntry1;
contact.Save();
Already tried this:
service.ImpersonatedUserId = new ImpersonatedUserId(ConnectingIdType.PrincipalName, "test");
I tested it with "test" and "test#domain" and "test#domain.de"
And get back this error:
"Der Name des Identitätsprinzipals ist ungültig."
Own translation: "The name of the identity principal is unvailed"
You can use Impersonation like this
ExchangeUserData exchangeUserData = new ExchangeUserData();
exchangeUserData.Username = "c-sharp";
exchangeUserData.Password = "c-sharp"; // c-sharp's Password
ExchangeService service = Service.ConnectToServiceWithImpersonation(exchangeUserData, impersonatedUserPrincipal);
Contact contact = new Contact(service);
// Specify the name and how the contact should be filed.
contact.GivenName = "n.a.";
contact.FileAsMapping = FileAsMapping.SurnameCommaGivenName;
contact.DisplayName = "bau gmbh";
// Specify the company name.
contact.CompanyName = "bau";
// Specify the business, home, and car phone numbers.
contact.PhoneNumbers[PhoneNumberKey.BusinessPhone] = "00000 00000";
contact.PhoneNumbers[PhoneNumberKey.MobilePhone] = "n.a.";
contact.PhoneNumbers[PhoneNumberKey.BusinessFax] = "00000 00000";
// Specify two email addresses.
contact.EmailAddresses[EmailAddressKey.EmailAddress1] = new EmailAddress("e#mail.de");
//homepage
contact.BusinessHomePage = "n.a.";
// Specify the home address.
PhysicalAddressEntry paEntry1 = new PhysicalAddressEntry();
paEntry1.Street = "straße";
paEntry1.City = "stadt";
paEntry1.State = "D";
paEntry1.PostalCode = "88890";
paEntry1.CountryOrRegion = "Deutschland";
contact.PhysicalAddresses[PhysicalAddressKey.Home] = paEntry1;
contact.Save();
If your c-sharp user has the proper rights in Exchange, you should be able to do:
ExchangeService service = new ExchangeService(ExchangeVersion.Exchange2013);
service.Credentials = new WebCredentials("c-sharp", "c-sharp", "domain");
service.ImpersonatedUserId = new ImpersonatedUserId(ConnectingIdType.PrincipalName, "test");
If this doesn't work for you, please comment below or update your question (there's an "edit" link under it) with the exact behavior you are seeing including any error messages.
Problem sloved.
I found the bug... both of you are right just change:
service.ImpersonatedUserId = new ImpersonatedUserId(ConnectingIdType.PrincipalName, "test");
Into:
service.ImpersonatedUserId = new ImpersonatedUserId(ConnectingIdType.SmtpAddress, "test#domain.de");
Thats all ...
Great thanks to you
I need to loop through all unread messages in inbox and download first attachment for every email, my code works but only for first email, why ?
/* load all unread emails */
SearchFilter sf = new SearchFilter.SearchFilterCollection(LogicalOperator.And, new SearchFilter.IsEqualTo(EmailMessageSchema.IsRead, false));
FindItemsResults<Item> findResults = service.FindItems(WellKnownFolderName.Inbox, sf, new ItemView(1));
/* loop through emails */
foreach (EmailMessage item in findResults)
{
item.Load();
/* download attachment if any */
if (item.HasAttachments && item.Attachments[0] is FileAttachment)
{
Console.WriteLine(item.Attachments[0].Name);
FileAttachment fileAttachment = item.Attachments[0] as FileAttachment;
/* download attachment to folder */
fileAttachment.Load(downloadDir + fileAttachment.Name);
}
/* mark email as read */
item.IsRead = true;
item.Update(ConflictResolutionMode.AlwaysOverwrite);
}
Console.WriteLine("Done");
in my inbox it set the first email to read but the sript stops then and write "Done." to console window. Whats wrong ?
The problem is that you're only requesting a single item from Exchange.
FindItemsResults<Item> findResults = service.FindItems(
WellKnownFolderName.Inbox,
sf,
new ItemView(1));
The ItemView class constructor takes a page size as its parameter, which is defined as:
The maximum number of items the search operation returns.
So you're requesting a single item, which explains why your foreach completes after that one item.
To test this you can simply increase the pageSize to something more reasonable, like 100 or 1000.
But to fix it you should follow the idiomatic double-loop:
SearchFilter sf = new SearchFilter.SearchFilterCollection(LogicalOperator.And, new SearchFilter.IsEqualTo(EmailMessageSchema.IsRead, false));
FindItemsResults<Item> findResults;
ItemView view = new ItemView(100);
do {
findResults = service.FindItems(WellKnownFolderName.Inbox, sf, view);
foreach (var item in findResults.Items) {
// TODO: process the unread item as you already did
}
view.Offset = findResults.NextPageOffset;
}
while (findResults.MoreAvailable);
Here we continue retrieving more items from Exchange (in batches of 100) as long as it tells us there are more items available.
public void readMail()
{
ExchangeService service = new ExchangeService(ExchangeVersion.Exchange2010);
service.Credentials = new WebCredentials("uname", "password", "domain");
service.Url = new Uri("URL");
System.Net.ServicePointManager.ServerCertificateValidationCallback = ((sender, certificate, chain, sslPolicyErrors) => true);
SearchFilter searchFilter = new SearchFilter.SearchFilterCollection(LogicalOperator.And, new SearchFilter.IsEqualTo(EmailMessageSchema.IsRead, false));
FindItemsResults<Item> findResults = service.FindItems(WellKnownFolderName.Inbox, searchFilter, new ItemView(int.MaxValue));
foreach (EmailMessage item in findResults.Items)
{
item.Load();
if (item.HasAttachments)
{
foreach (var i in item.Attachments)
{
try
{
FileAttachment fileAttachment = i as FileAttachment;
fileAttachment.Load("C:\\Users\\xxxxx\\Desktop\\comstar\\Download\\test\\" + fileAttachment.Name);
}
catch(Exception e)
{
Console.Write(e);
}
}
}
//set mail as read
item.IsRead = true;
item.Update(ConflictResolutionMode.AutoResolve);
}
}