I am searching for an article that describes the configuration for certificate based authentication with EWS.
I need the correct settings for Exchange 2007, 2010 and 2013.
Thanks
I am searching for an article that describes the configuration for certificate based authentication with EWS.
I need the correct settings for Exchange 2007, 2010 and 2013.
Thanks
We are using impersonation to access mailboxes hosted in Office 365 using EWS but the app will only return available timeslots when the availabilityOptions.MinimumSuggestionQuality = SuggestionQuality.Poor. I've tried adjusting the availabilityOptions.GoodSuggestionThreshold to no avail. Beyond assigning the "ApplicationImpersonation" role to the account being used to access mailboxes, are there any other permissions, licenses, or attributes that need to be set in order to use EWS to query for free/busy time? The code snippet is below.
---
//Returns a list of TimeSuggestions for the specified user(email) and date.
string MyUser = "o365test109@contoso.com";
//LB Note: Pulled impersonation information from https://msdn.microsoft.com/en-us/library/office/dn722379(v=exchg.150).aspx#sectionSection1
service.Credentials = new NetworkCredential("acns_calendarapptest@contoso.com", "acns_calendarapptestpw");
service.Url = new Uri("https://outlook.office365.com/EWS/Exchange.asmx");
//Changing MyUser to an invalid user (0365idontexist@contoso.com) or a valid user (o365test100) that the app doesn't
//have impersonation rights to will throw an error stating as much
service.ImpersonatedUserId = new ImpersonatedUserId(ConnectingIdType.PrincipalName, MyUser);
List<TimeSuggestion> suggestions = new List<TimeSuggestion>();
//---------------------------------------------------------------------------------------------
//LB Note: I pulled this example from https://msdn.microsoft.com/en-us/library/office/dn643673(v=exchg.150).aspx
List<AttendeeInfo> attendees = new List<AttendeeInfo>();
attendees.Add(new AttendeeInfo()
{
SmtpAddress = MyUser,
AttendeeType = MeetingAttendeeType.Organizer
});
// Specify options to request free/busy information and suggested meeting times.
AvailabilityOptions availabilityOptions = new AvailabilityOptions();
availabilityOptions.GoodSuggestionThreshold = 10;
availabilityOptions.MaximumNonWorkHoursSuggestionsPerDay = 1;
availabilityOptions.MaximumSuggestionsPerDay = 30;
availabilityOptions.MeetingDuration = 60;
// LB Note: Setting this to "Poor" was the only way I could get results to show. Not sure what's going on here.
availabilityOptions.
//Returns a list of TimeSuggestions for the specified user(email) and date.
string MyUser = "o365test109@contoso.com";
//LB Note: Pulled impersonation information from https://msdn.microsoft.com/en-us/library/office/dn722379(v=exchg.150).aspx#sectionSection1
service.Credentials = new NetworkCredential("acns_calendarapptest@contoso.com", "acns_calendarapptestpw");
service.Url = new Uri("https://outlook.office365.com/EWS/Exchange.asmx");
//Changing MyUser to an invalid user (0365idontexist@contoso.com) or a valid user (o365test100) that the app doesn't
//have impersonation rights to will throw an error stating as much
service.ImpersonatedUserId = new ImpersonatedUserId(ConnectingIdType.PrincipalName, MyUser);
List<TimeSuggestion> suggestions = new List<TimeSuggestion>();
//---------------------------------------------------------------------------------------------
//LB Note: I pulled this example from https://msdn.microsoft.com/en-us/library/office/dn643673(v=exchg.150).aspx
List<AttendeeInfo> attendees = new List<AttendeeInfo>();
attendees.Add(new AttendeeInfo()
{
SmtpAddress = MyUser,
AttendeeType = MeetingAttendeeType.Organizer
});
// Specify options to request free/busy information and suggested meeting times.
AvailabilityOptions availabilityOptions = new AvailabilityOptions();
availabilityOptions.GoodSuggestionThreshold = 10;
availabilityOptions.MaximumNonWorkHoursSuggestionsPerDay = 1;
availabilityOptions.MaximumSuggestionsPerDay = 30;
availabilityOptions.MeetingDuration = 60;
// LB Note: Setting this to "Poor" was the only way I could get results to show. Not sure what's going on here.
availabilityOptions.MinimumSuggestionQuality = SuggestionQuality.Poor;
availabilityOptions.DetailedSuggestionsWindow = new TimeWindow(Convert.ToDateTime("4/1/2015"), Convert.ToDateTime("4/2/2015"));
availabilityOptions.RequestedFreeBusyView = FreeBusyViewType.FreeBusy;
// Return free/busy information and a set of suggested meeting times.
// This method results in a GetUserAvailabilityRequest call to EWS.
GetUserAvailabilityResults results = service.GetUserAvailability(attendees,
availabilityOptions.DetailedSuggestionsWindow,
AvailabilityData.FreeBusyAndSuggestions,
availabilityOptions);
= SuggestionQuality.Poor;
availabilityOptions.DetailedSuggestionsWindow = new TimeWindow(Convert.ToDateTime("4/1/2015"), Convert.ToDateTime("4/2/2015"));
availabilityOptions.RequestedFreeBusyView = FreeBusyViewType.FreeBusy;
// Return free/busy information and a set of suggested meeting times.
// This method results in a GetUserAvailabilityRequest call to EWS.
GetUserAvailabilityResults results = service.GetUserAvailability(attendees,
availabilityOptions.DetailedSuggestionsWindow,
AvailabilityData.FreeBusyAndSuggestions,
availabilityOptions);
What Im trying to achive is to be able to create a Folder with Extended Properties using EWS and then be able to read these properties from inside Outlook.
Ive verified that it works to add & retrieve extended properties on Folders using EWS, i.e.
var f = new Folder(_svc);
f.DisplayName = "Testing";
f.SetExtendedProperty(EPD.ItqAction, 1);
f.Save(WellKnownFolderName.MsgFolderRoot);
then loading it as following,
PropertySet propset = new PropertySet(PropertySet.IdOnly);or even using SearchFilder.IsEqual()
but these Properties does not appear in OutlookSpy nor MFCAPI, and can't seem to be accessable from Outlook VSTO.
I've tried
myFolder.PropertyAccessor.GetProperty(EPD.ItAction.ToMapiString());
ToMapiString creates a "http://schemas.microsoft.com/mapi/{GUID}/attr-name" string
But this results in a COMException.
Ive heard that named Properties are not supported by Outlook, what is the alternative type definition? And that one should create a Hidden Item in the folder for properties. But haven't been able to find any details on how to create a hidden item (only Hidden folders w/ attribute 0x10f4).
Here is code snippet which i prepared base on
https://willcode4foodblog.wordpress.com/2012/04/13/understanding-sharing-invitation-requests-ews-managed-api-1-2-part-1/
and
https://willcode4foodblog.wordpress.com/2012/04/14/understanding-sharing-invitation-requests-ews-managed-api-1-2-part-2/
i made little changes to the code and getting the error message "The sharing message is not supported."
public void ShareCalendar(Calendar calendar)
{
ExchangeService service = new ExchangeService(ExchangeVersion.Exchange2013);
service.Credentials = new NetworkCredential("user1", "password", "domain");
service.Url = new Uri("https://sampleUrl/ews/exchange.asmx");
try
{
// Bind to the folder
//Folder folderStoreInfo;
//folderStoreInfo = Folder.Bind(service, calendar.ExchangeId);
//string EwsID = folderStoreInfo.Id.UniqueId;
string EwsID = calendar.FolderExchangeId;
// The value of folderidHex will be what we need to use for the FolderId in the xml file
AutodiscoverService autoDiscover = new AutodiscoverService(ExchangeVersion.Exchange2013);
autoDiscover.Credentials = new NetworkCredential("user1", "password", "domain");
autoDiscover.RedirectionUrlValidationCallback = RedirectionUrlValidationCallback;
Dictionary<string, string> userSettings = GetUserSettings(autoDiscover);
string folderidHex = GetConvertedEWSIDinHex(service, EwsID, "user1@outlook.com");
string domainName = string.Empty;
string mailBoxServer = string.Empty;
string userName = string.Empty;
foreach (var item in userSettings)
{
switch (item.Key)
{
case "UserDN":
domainName = item.Value.ToString();
break;
case "InternalMailboxServer":
mailBoxServer = item.Value.ToString();
break;
case "UserDisplayName":
userName = item.Value.ToString();
break;
}
}
string entryId = GetIntiatorEntryID(domainName);
string mailboxId = GetInvitationMailboxId(mailBoxServer, domainName);
string sharedFilePath = CreateSharingMessageAttachment(folderidHex, userName, entryId, mailboxId, "user2@outlook.com", "calendar", calendar.FolderName);
// Create a new message
EmailMessage invitationRequest = new EmailMessage(service);
invitationRequest.Subject = "I'd like to share my calendar with you";
invitationRequest.Body = "Sent by Exchange Administrator on behalf of user";
//invitationRequest.Culture = "en-US";
invitationRequest.Sensitivity = Sensitivity.Normal;
// Set a sharing specific property on the message
invitationRequest.ItemClass = "IPM.Sharing"; /* Constant Required Value [MS-ProtocolSpec] */
byte[] byteEntryId = HexStringToByteArray(entryId);
// This is the Guid of the Sharing Provider in Exchange, and it's value does not change
Guid binSharingProviderGuid = new Guid("{AEF00600-0000-0000-C000-000000000046}");
// Even though I don't think setting this property is mandatory,
// it just seemed like the right thing to do and it works so I \
// ain't messin with it!
byte[] byteSharingProviderGuid = binSharingProviderGuid.ToByteArray();
string strPRBODYHTML = "<html dir=\"ltr\">\r\n<head>\r\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=iso-8859-1\">\r\n<meta name=\"GENERATOR\"
content=\"MSHTML 8.00.7601.17514\">\r\n<style id=\"owaParaStyle\">P {\r\n MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px \r\n}\r\n</style>\r\n</head>\r\n<body fPStyle=\"1\" ocsi=\"0\">\r\n<tt>\r\n<pre>SharedByUserDisplayName
(SharedByUserSmtpAddress) has invited you to view his or her Microsoft Exchange Calendar.\r\n\r\nFor instructions on how to view shared folders on Exchange, see the following article:\r\n\r\nhttp://go.microsoft.com/fwlink/?LinkId=57561\r\n\r\n*~*~*~*~*~*~*~*~*~*\r\n\r\n</pre>\r\n</tt>\r\n<div>\r\n<div
style=\"direction: ltr;font-family: Tahoma;color: #000000;font-size: 10pt;\">this is a test message</div>\r\n</div>\r\n</body>\r\n</html>\r\n";
string strBODY = @"
SharedByUserDisplayName (SharedByUserSmtpAddress) has invited you to view his or
her Microsoft Exchange Calendar.
For instructions on how to view shared folders on Exchange, see the
following article:
http://go.microsoft.com/fwlink/?LinkId=57561
*~*~*~*~*~*~*~*~*~*
test body
";
// Convert these to hex and binary equivelants to assign to their relevant
// extended properties
string hexPRBODYHTML = ConvertStringToHex(strPRBODYHTML);
byte[] binPRBODYHTML = HexStringToByteArray(hexPRBODYHTML);
Guid PropertySetSharing = Guid.Parse("00062040-0000-0000-C000-000000000046");//constant
Guid PropertySetInternetHeaders = Guid.Parse("00020386-0000-0000-C000-000000000046");//constant
ExtendedPropertyDefinition PidLidSharingProviderGuidProperty = new ExtendedPropertyDefinition(PropertySetSharing, 0x8A01, MapiPropertyType.CLSID);
ExtendedPropertyDefinition ConversationIdProperty = new ExtendedPropertyDefinition(0x3013, MapiPropertyType.Binary);
// Sharing Properties (in order of reference according to protocol examples in: [MS-OXSHARE])
// Additional Property Constraints
// [MS-OXSHARE] 2.2.5.2
ExtendedPropertyDefinition PidTagMessageClass = new ExtendedPropertyDefinition(0x001A, MapiPropertyType.String);
// [MS-OXSHARE] 2.2.5.1
//ExtendedPropertyDefinition PidNameContentClass = new ExtendedPropertyDefinition(DefaultExtendedPropertySet.InternetHeaders, "Content-Class", MapiPropertyType.String);
ExtendedPropertyDefinition PidNameContentClass = new ExtendedPropertyDefinition(PropertySetInternetHeaders, "Content-class", MapiPropertyType.String);
// Common Message Object Properties
// [MS-OXSHARE] 2.2.1
ExtendedPropertyDefinition PidTagNormalizedSubject = new ExtendedPropertyDefinition(0x0E1D, MapiPropertyType.String);
// The PidTagSubjectPrefix is a zero-length string, so I do not set it
// ExtendedPropertyDefinition PidTagSubjectPrefix = new ExtendedPropertyDefinition(0x003D, MapiPropertyType.String);
// Sharing Object Message Properties
// [MS-OXSHARE] 2.2.2.12
ExtendedPropertyDefinition PidLidSharingProviderGuid = new ExtendedPropertyDefinition(PropertySetSharing, 0x8A01, MapiPropertyType.Binary);
// [MS-OXSHARE] 2.2.2.13
ExtendedPropertyDefinition PidNameXSharingProviderGuid = new ExtendedPropertyDefinition(PropertySetInternetHeaders, "X-Sharing-Provider-GUID", MapiPropertyType.String);
// [MS-OXSHARE] 2.2.2.14
ExtendedPropertyDefinition PidLidSharingProviderName = new ExtendedPropertyDefinition(PropertySetSharing, 0x8A02, MapiPropertyType.String);
// [MS-OXSHARE] 2.2.2.15
ExtendedPropertyDefinition PidNameXSharingProviderName = new ExtendedPropertyDefinition(PropertySetInternetHeaders, "X-Sharing-Provider-Name", MapiPropertyType.String);
// [MS-OXSHARE] 2.2.2.16
ExtendedPropertyDefinition PidLidSharingProviderUrl = new ExtendedPropertyDefinition(PropertySetSharing, 0x8A03, MapiPropertyType.String);
// [MS-OXSHARE] 2.2.2.17
ExtendedPropertyDefinition PidNameXSharingProviderUrl = new ExtendedPropertyDefinition(PropertySetInternetHeaders, "X-Sharing-Provider-URL", MapiPropertyType.String);
// [MS-OXSHARE] 2.2.2.5
ExtendedPropertyDefinition PidLidSharingFlavor = new ExtendedPropertyDefinition(PropertySetSharing, 0x8A18, MapiPropertyType.Integer);
// [MS-OXSHARE] 2.2.2.6
ExtendedPropertyDefinition PidNameXSharingFlavor = new ExtendedPropertyDefinition(PropertySetInternetHeaders, "X-Sharing-Flavor", MapiPropertyType.String);
// [MS-OXSHARE] 2.2.2.1
ExtendedPropertyDefinition PidLidSharingCapabilities = new ExtendedPropertyDefinition(PropertySetSharing, 0x8A17, MapiPropertyType.Integer);
// [MS-OXSHARE] 2.2.2.2
ExtendedPropertyDefinition PidNameXSharingCapabilities = new ExtendedPropertyDefinition(PropertySetInternetHeaders, "X-Sharing-Capabilities", MapiPropertyType.String);
// Sections 2.3 and 2.4 are also zero-length strings, so I won't set those either
// [MS-OXSHARE] 2.2.2.3
// ExtendedPropertyDefinition PidLidSharingConfigurationUrl = new //ExtendedPropertyDefinition(PropertySetSharing, 0x8A24, MapiPropertyType.String);
// [MS-OXSHARE] 2.2.2.4
//ExtendedPropertyDefinition PidNameXSharingConfigUrl = new //ExtendedPropertyDefinition(DefaultExtendedPropertySet.InternetHeaders, "X-Sharing-Config-Url", MapiPropertyType.String);
// [MS-OXSHARE] 2.2.2.10
ExtendedPropertyDefinition PidLidSharingLocalType = new ExtendedPropertyDefinition(PropertySetSharing, 0x8A14, MapiPropertyType.String);
// [MS-OXSHARE] 2.2.2.11
ExtendedPropertyDefinition PidNameXSharingLocalType = new ExtendedPropertyDefinition(PropertySetInternetHeaders, "X-Sharing-Local-Type", MapiPropertyType.String);
// [MS-OXSHARE] 2.2.2.7
ExtendedPropertyDefinition PidLidSharingInitiatorEntryId = new ExtendedPropertyDefinition(PropertySetSharing, 0x8A09, MapiPropertyType.Binary);
// [MS-OXSHARE] 2.2.2.8
ExtendedPropertyDefinition PidLidSharingInitiatorName = new ExtendedPropertyDefinition(PropertySetSharing, 0x8A07, MapiPropertyType.String);
// [MS-OXSHARE] 2.2.2.9
ExtendedPropertyDefinition PidLidSharingInitiatorSMTP = new ExtendedPropertyDefinition(PropertySetSharing, 0x8A08, MapiPropertyType.String);
// [MS-OXSHARE] 2.2.3.1
ExtendedPropertyDefinition PidLidSharingRemoteName = new ExtendedPropertyDefinition(PropertySetSharing, 0x8A05, MapiPropertyType.String);
// [MS-OXSHARE] 2.2.3.2
ExtendedPropertyDefinition PidNameXSharingRemoteName = new ExtendedPropertyDefinition(PropertySetInternetHeaders, "X-Sharing-Remote-Name", MapiPropertyType.String);
// [MS-OXSHARE] 2.2.3.5
ExtendedPropertyDefinition PidLidSharingRemoteType = new ExtendedPropertyDefinition(PropertySetSharing, 0x8A1D, MapiPropertyType.String);
// [MS-OXSHARE] 2.2.3.6
ExtendedPropertyDefinition PidNameXSharingRemoteType = new ExtendedPropertyDefinition(PropertySetInternetHeaders, "X-Sharing-Remote-Type", MapiPropertyType.String);
// [MS-OXSHARE] 2.2.3.7
ExtendedPropertyDefinition PidLidSharingRemoteUid = new ExtendedPropertyDefinition(PropertySetSharing, 0x8A06, MapiPropertyType.String);
// [MS-OXSHARE] 2.2.3.8
ExtendedPropertyDefinition PidNameXSharingRemoteUid = new ExtendedPropertyDefinition(PropertySetInternetHeaders, "X-Sharing-Remote-Uid", MapiPropertyType.String);
// [MS-OXSHARE] 2.2.3.3
ExtendedPropertyDefinition PidLidSharingRemoteStoreUid = new ExtendedPropertyDefinition(PropertySetSharing, 0x8A48, MapiPropertyType.String);
// [MS-OXSHARE] 2.2.3.4
ExtendedPropertyDefinition PidNameXSharingRemoteStoreUid = new ExtendedPropertyDefinition(PropertySetInternetHeaders, "X-Sharing-Remote-Store-Uid", MapiPropertyType.String);
//From troubleshooting I noticed I was missing
ExtendedPropertyDefinition PidTagPriority = new ExtendedPropertyDefinition(0x0026, MapiPropertyType.Integer);
ExtendedPropertyDefinition PidTagSensitivity = new ExtendedPropertyDefinition(0x0036, MapiPropertyType.Integer);
ExtendedPropertyDefinition PR_BODY_HTML = new ExtendedPropertyDefinition(0x1013, MapiPropertyType.Binary); //PR_BOD
ExtendedPropertyDefinition PR_BODY = new ExtendedPropertyDefinition(0x1000, MapiPropertyType.String);
ExtendedPropertyDefinition RecipientReassignmentProhibited = new ExtendedPropertyDefinition(0x002b, MapiPropertyType.Boolean);
// Section 2.2.1
invitationRequest.SetExtendedProperty(PidTagNormalizedSubject, "I'd like to share my calendar with you"); /* Constant Required Value [MS-OXSHARE] 2.2.1 */
//invitationRequest.SetExtendedProperty(PidTagSubjectPrefix, String.Empty); /* Constant Required Value [MS-OXSHARE] 2.2.1 */
// Section 2.2.2
invitationRequest.SetExtendedProperty(PidLidSharingCapabilities, 0x40220); /* value for Special Folders */
invitationRequest.SetExtendedProperty(PidNameXSharingCapabilities, "40220"); /* Test representation of SharingCapabilities value */
//invitationRequest.SetExtendedProperty(PidLidSharingConfigurationUrl, String.Empty); /* Zero-Length String [MS-OXSHARE] 2.2.2.3 */
//invitationRequest.SetExtendedProperty(PidNameXSharingConfigUrl, String.Empty); /* Zero-Length String [MS-OXSHARE] 2.2.2.4 */
invitationRequest.SetExtendedProperty(PidLidSharingFlavor, 0x20310); /* Indicates Invitation for a special folder [MS-OXSHARE] 2.2.2.5 */
invitationRequest.SetExtendedProperty(PidNameXSharingFlavor, "20310"); /* Text representation of SharingFlavor value [MS-OXSHARE] 2.2.2.6 */
invitationRequest.SetExtendedProperty(PidLidSharingInitiatorEntryId, byteEntryId); /* Value from the Initiator/EntryId value in the Sharing Message attachment .xml document */
invitationRequest.SetExtendedProperty(PidLidSharingInitiatorSMTP, "user1@outlook.com"); /* Value from Initiator/Smtp Address in the Sharing message attachment .xml document */
invitationRequest.SetExtendedProperty(PidLidSharingInitiatorName, "User1"); /* Value from Initiator/Name Address in the Sharing message attachment .xml document */
invitationRequest.SetExtendedProperty(PidLidSharingLocalType, "IPF.Appointment"); /* MUST be set to PidTagContainerClass of folder to be shared */
invitationRequest.SetExtendedProperty(PidNameXSharingLocalType, "IPF.Appointment"); /* MUST be set to same value as PidLidSharingLocalType */
invitationRequest.SetExtendedProperty(PidLidSharingProviderGuid, byteSharingProviderGuid); /* Constant Required Value [MS-OXSHARE] 2.2.2.12 */
invitationRequest.SetExtendedProperty(PidNameXSharingProviderGuid, "AEF0060000000000C000000000000046"); /* Constant Required Value [MS-OXSHARE] 2.2.2.13 */
invitationRequest.SetExtendedProperty(PidLidSharingProviderName, "Microsoft Exchange"); /* Constant Required Value [MS-OXSHARE] 2.2.2.14 */
invitationRequest.SetExtendedProperty(PidNameXSharingProviderName, "Microsoft Exchange"); /* Constant Required Value [MS-OXSHARE] 2.2.2.15] */
invitationRequest.SetExtendedProperty(PidLidSharingProviderUrl, "http://www.microsoft.com/exchange"); /* Constant Required Value [MS-OXSHARE] 2.2.2.16 */
invitationRequest.SetExtendedProperty(PidNameXSharingProviderUrl, "http://www.microsoft.com/exchange"); /* Constant Required Value [MS-OXSHARE] 2.2.2.17 */
// Section 2.2.3
invitationRequest.SetExtendedProperty(PidLidSharingRemoteName, calendar.FolderName); /* MUST be set to PidTagDisplayName of the folder being shared */
invitationRequest.SetExtendedProperty(PidNameXSharingRemoteName, calendar.FolderName); /* MUST be set to same value as PidLidSharingRemoteName */
invitationRequest.SetExtendedProperty(PidLidSharingRemoteStoreUid, mailboxId); /* Must be set to PidTagStoreEntryId of the folder being shared */
invitationRequest.SetExtendedProperty(PidNameXSharingRemoteStoreUid, mailboxId); /* MUST be set to same value as PidLidSharingRemoteStoreUid */
invitationRequest.SetExtendedProperty(PidLidSharingRemoteType, "IPF.Appointment"); /* Constant Required Value [MS-OXSHARE] 2.2.3.5 */
invitationRequest.SetExtendedProperty(PidNameXSharingRemoteType, "IPF.Appointment"); /* Constant Required Value [MS-OXSHARE] 2.2.3.6 */
invitationRequest.SetExtendedProperty(PidLidSharingRemoteUid, folderidHex); /* MUST be set to PidTagEntryId of folder being shared */
invitationRequest.SetExtendedProperty(PidNameXSharingRemoteUid, folderidHex); /* Must be set to same value as PidLidSharingRemoteUid */
// Section 2.2.5
invitationRequest.SetExtendedProperty(PidNameContentClass, "Sharing"); /* Constant Required Value [MS-ProtocolSpec] */
invitationRequest.SetExtendedProperty(PidTagMessageClass, "IPM.Sharing"); /* Constant Required Value [MS-ProtocolSpec] */
// ********* ADDITIONAL MAPPED PROPERTIES IM FINDING AS I TROUBLESHOOT ********************** //
invitationRequest.SetExtendedProperty(PidTagPriority, 0); /* From troubleshooting I'm just trying to match up values that were missing */
invitationRequest.SetExtendedProperty(PidTagSensitivity, 0); /* From troubleshooting as well */
invitationRequest.SetExtendedProperty(PR_BODY_HTML, binPRBODYHTML); /* From troubleshooting OWA error pointing to serializing HTML failing */
invitationRequest.SetExtendedProperty(PR_BODY, strBODY);
invitationRequest.SetExtendedProperty(RecipientReassignmentProhibited, true); /* Because it seemed like a good idea */
// Add a file attachment by using a stream
// We need to do the following in order to prevent 3 extra bytes from being prepended to the attachment
string sharMetadata = File.ReadAllText(sharedFilePath, Encoding.ASCII);
byte[] fileContents;
UTF8Encoding encoding = new System.Text.UTF8Encoding();
fileContents = encoding.GetBytes(sharMetadata);
//fileContents = File.ReadAllBytes(sharedFilePath);
//// fileContents is a Stream object that represents the content of the file to attach.
invitationRequest.Attachments.AddFileAttachment("sharing_metadata.xml", fileContents);
////invitationRequest.Attachments.AddFileAttachment(sharedFilePath);
//// This is where we set those "special" headers and other pertinent
//// information I noted in Part 1 of this series...
//Attachment thisAttachment = invitationRequest.Attachments[0];
//thisAttachment.ContentType = "application/x-sharing-metadata-xml";
//thisAttachment.Name = "sharing_metadata.xml";
//thisAttachment.IsInline = false;
// Add recipient info and send message
invitationRequest.ToRecipients.Add(new EmailAddress() { Address = "user2@outlook.com" });
invitationRequest.SendAndSaveCopy();
// I always end my methods by returning the EWS
// impersonated user to null to clean up
service.ImpersonatedUserId = null;
}
catch (Exception ex)
{
}
}
public String GetConvertedEWSIDinHex(ExchangeService esb, String sID, String strSMTPAdd)
{
// Create a request to convert identifiers.
AlternateId objAltID = new AlternateId();
objAltID.Format = IdFormat.EwsId;
objAltID.Mailbox = strSMTPAdd;
objAltID.UniqueId = sID;
//Convert PR_ENTRYID identifier format to an EWS identifier.
AlternateIdBase objAltIDBase = esb.ConvertId(objAltID, IdFormat.HexEntryId);
AlternateId objAltIDResp = (AlternateId)objAltIDBase;
return objAltIDResp.UniqueId.ToString();
}
public String GetInvitationMailboxId(string mailBoxServer, string domainName)
{
ExchangeService service = new ExchangeService(ExchangeVersion.Exchange2013);
service.ImpersonatedUserId = new ImpersonatedUserId(ConnectingIdType.SmtpAddress, "user1@outlook.com");
// Generate The Store Entry Id for the impersonated user
StringBuilder MailboxIDPointer = new StringBuilder();
string fqdn = mailBoxServer;
string legacyDN = domainName;
MailboxIDPointer.Append("00000000"); /* Flags */
MailboxIDPointer.Append("38A1BB1005E5101AA1BB08002B2A56C2"); /* ProviderUID */
MailboxIDPointer.Append("00"); /* Version */
MailboxIDPointer.Append("00"); /* Flag */
MailboxIDPointer.Append("454D534D44422E444C4C00000000"); /* DLLFileName */
MailboxIDPointer.Append("00000000"); /* Wrapped Flags */
MailboxIDPointer.Append("1B55FA20AA6611CD9BC800AA002FC45A"); /* WrappedProvider UID (Mailbox Store Object) */
MailboxIDPointer.Append("0C000000"); /* Wrapped Type (Mailbox Store) */
MailboxIDPointer.Append(ConvertStringToHex(fqdn)); /* ServerShortname (FQDN) */
MailboxIDPointer.Append("00"); /* termination bit */
MailboxIDPointer.Append(ConvertStringToHex(legacyDN)); /* Returns the userDN of the impersonated user */
MailboxIDPointer.Append("00"); /* terminator bit */
service.ImpersonatedUserId = null;
return MailboxIDPointer.ToString();
}
static bool RedirectionUrlValidationCallback(String redirectionUrl)
{
bool redirectionValidated = false;
if (redirectionUrl.Equals("https://SampleUrl/autodiscover/autodiscover.xml"))
{
redirectionValidated = true;
}
return redirectionValidated;
}
public String GetIntiatorEntryID(string domainName)
{
String result = String.Empty;
//// Bind to EWS
//ExchangeService service = ExchangeConnection.ExchangeService();
//service.ImpersonatedUserId =
//new ImpersonatedUserId(ConnectingIdType.SmtpAddress, "user1@outlook.com");
//// Get LegacyDN Using the function above this one
string sharedByLegacyDN = domainName;
// A conversion function from earlier
string legacyDNinHex = ConvertStringToHex(sharedByLegacyDN);
StringBuilder addBookEntryId = new StringBuilder();
addBookEntryId.Append("00000000"); /* Flags */
addBookEntryId.Append("DCA740C8C042101AB4B908002B2FE182"); /* ProviderUID */
addBookEntryId.Append("01000000"); /* Version */
addBookEntryId.Append("00000000"); /* Type - 00 00 00 00 = Local Mail User */
addBookEntryId.Append(legacyDNinHex); /* Returns the userDN of the impersonated user */
addBookEntryId.Append("00"); /* terminator bit */
result = addBookEntryId.ToString();
//service.ImpersonatedUserId = null;
return result;
}
public string ConvertStringToHex(string input)
{
// Take our input and break it into an array
char[] arrInput = input.ToCharArray();
String result = String.Empty;
// For each set of characters
foreach (char element in arrInput)
{
if (String.IsNullOrEmpty(result))
{
result = String.Format("{0:X2}", Convert.ToUInt16(element)).ToString();
}
else
{
result += String.Format("{0:X2}", Convert.ToUInt16(element)).ToString();
}
}
return result.ToString();
}
public Dictionary<string, string> GetUserSettings(AutodiscoverService autodiscoverService)
{
GetUserSettingsResponse userresponse = autodiscoverService.GetUserSettings(
"user1@outlook.com",
UserSettingName.UserDisplayName,
UserSettingName.InternalMailboxServerDN,
UserSettingName.UserDN
);
Dictionary<string, string> myUserSettings = new Dictionary<string, string>();
foreach (KeyValuePair<UserSettingName, Object> usersetting in userresponse.Settings)
{
if (usersetting.Key.ToString() == "InternalMailboxServerDN")
{
int lastIndexOfEqual = usersetting.Value.ToString().LastIndexOf("=");
string subString = usersetting.Value.ToString().Substring(lastIndexOfEqual + 1);
string value = subString;
myUserSettings.Add("InternalMailboxServer", value.ToString());
}
if (usersetting.Key.ToString() == "UserDisplayName")
{
string[] arrResult = usersetting.Value.ToString().Split('.');
myUserSettings.Add("UserDisplayName", arrResult[0].ToString());
}
if (usersetting.Key.ToString() == "UserDN")
{
string[] arrResult = usersetting.Value.ToString().Split('.');
myUserSettings.Add("UserDN", arrResult[0].ToString());
}
}
return myUserSettings;
}
private static byte[] HexStringToByteArray(string input)
{
byte[] Bytes;
int ByteLength;
string HexValue = "\x0\x1\x2\x3\x4\x5\x6\x7\x8\x9|||||||\xA\xB\xC\xD\xE\xF";
ByteLength = input.Length / 2;
Bytes = new byte[ByteLength];
for (int x = 0, i = 0; i < input.Length; i += 2, x += 1)
{
Bytes[x] = (byte)(HexValue[Char.ToUpper(input[i + 0]) - '0'] << 4);
Bytes[x] |= (byte)(HexValue[Char.ToUpper(input[i + 1]) - '0']);
}
return Bytes;
}
Howdy All -
Can anyone point me as to how you can search a single or multiple mailboxes for a specific email by sender or subject to find out if the email was read?
I have scoured the net and can not find anything related to this for O365 or even Exchange 2013.
Thx!
Domran
Hi,
I'm using EWS Managed API 2.2 with Visual Basic 2013. I'm trying to import EML file to user mailbox using EMailMessage Save method, and it works great, but received date in Outlook is set to today's date. I'd like it to be date found in EML file.
Can anyone point me as to how to do that?
Thanks
Denis
Hi everybody,
I am using EWS Managed API 2.2 to get Autodiscover settings. But it is giving me 'Microsoft.Exchange.WebServices.Data.AutodiscoverLocalException'. The message is "The Autodiscover service couldn't be located." The stack trace is:
at Microsoft.Exchange.WebServices.Autodiscover.AutodiscoverService.InternalGetLegacyUserSettings[TSettings](String emailAddress, List`1 redirectionEmailAddresses, Int32& currentHop) at Microsoft.Exchange.WebServices.Autodiscover.AutodiscoverService.GetLegacyUserSettings[TSettings](String emailAddress) at Microsoft.Exchange.WebServices.Autodiscover.AutodiscoverService.InternalGetLegacyUserSettings(String emailAddress, List`1 requestedSettings) at Microsoft.Exchange.WebServices.Autodiscover.AutodiscoverService.GetUserSettings(String userSmtpAddress, UserSettingName[] userSettingNames) at Microsoft.Exchange.WebServices.Data.ExchangeService.GetAutodiscoverUrl(String emailAddress, ExchangeVersion requestedServerVersion, AutodiscoverRedirectionUrlValidationCallback validateRedirectionUrlCallback) at Microsoft.Exchange.WebServices.Data.ExchangeService.AutodiscoverUrl(String emailAddress, AutodiscoverRedirectionUrlValidationCallback validateRedirectionUrlCallback) at Microsoft.Exchange.WebServices.Data.ExchangeService.AutodiscoverUrl(String emailAddress) at ConsoleApplication1.Program.Main(String[] args) in c:\Users\pse\Documents\Visual Studio 2013\Projects\ConsoleApplication1\ConsoleApplication1\Program.cs:line 92 at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args) at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args) at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly() at System.Threading.ThreadHelper.ThreadStart_Context(Object state) at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) at System.Threading.ThreadHelper.ThreadStart()
The code that I am using is:
static void Main(string[] args) { ExchangeService exchangeService = new ExchangeService(ExchangeVersion.Exchange2013_SP1); exchangeService.Credentials = new NetworkCredential("mailboxName", "Password", "domainName"); exchangeService.TraceEnabled = true; exchangeService.TraceFlags = TraceFlags.All; exchangeService.AutodiscoverUrl("mailboxName@domainName"); }
I am using Exchange Server 2013 with Cumulative Update 7. Kindly help me.
Thanks & regards,
Talib Hussain
Hello again.
I am trying to figure out a good way to make sure that I have an accurate representation of a folder locally.
I have two tools at my disposal.
Pulling Subscription and StreamingSubscription.
If I do a pull every 1 minute - I am fine as it catches everything since the last time I did a pull. The downside is that 1 minute is not always acceptable latency.
If I rely on Streaming Subscription - when it works it is great. But if my internet connection is not reliable, I am afraid I may loose updates. There are a few scenarios where both sides "think" the connection is fine but that may not be the case. If there is a disconnect for say 5 minutes, in which the server sent the notifications to the client, then the connection timed out at the client side. The client can open the subscription again, even with the same subscription id, but the updates that the server "thinks" were sent, are lost.
What does it leave me with. I was thinking of a hybrid approach.
1) have a pulling subscription which is called every 5 minutes (or less)
2) have a streaming subscription. Because when I finally get an update, I cannot be sure that it contains all the notifications, so to be on the safe side, wake up the thread that was waiting for the next pull in the 5 minute window and have it do a pull. Do the same when the client side the detect a disconnect or a expiration of the streaming subscription.
The down side of that approach is that on every streaming event, the notifications in hand are ignored, and a full pull is initiated.
On the other hand, I don't see a way to ensure that the data in a streaming notification is complete.
Any thoughts?
Thanks,
Erez
Hi,
I noticed that on a Streaming subscription, the client side receives a "keep alive" envelope (0 notifications with status OK) roughly every 45 seconds (see below). Is this standard behavior?
Thanks,
Erez
<Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/">Hello!
I want to convert body from us-ascii to utf-8, if any know how can i do it plaese give hint.
I tried change Body.CharsetName, but in Exchange 2010 it is read-only property.
How can I move an email from a users main mailbox to a shared mailbox using apps for office. I know I can do this manually but i am creating an for owa/outlook that would be a button to move the item. I have tried using ews but can only find the commands to move emails inside the users mailbox
for example :
'<?xml version="1.0" encoding="utf-8"?>' +Can I create a xml that would would do this? Is there a way to do it using the EWS service reference. I do not want to use import/export to do this.
Hi all,
apologies if this has been asked before but I couldn't find an answer.
If I run this in EMS it works perfectly
$size ='{0:N2}'-f ((get-mailboxdatabase $_.name -status).databasesize.ToMB()/1024)
However if I run it from PowerShell and I connect to Exchange I get "method invocation failed because....doesn't contain a method named "ToMB"
I would prefer it so it can be run from powershell so that I can add it to the task schedule and to also give it to the support team who may not have access to the exchange server to run it remotely.
TIA
Andy
I would like to use the full regex library for a transport rule; do I need to create a new transport agent to do this? If so, how do I accomplish this? Has anyone already done this?
Thanks in advance for any and all help
Jerry
Jerry Becker
Is there any way we can pull data from Message trace which is over 90 days on Office365. Its for reporting purposes.
Thanks
Harshita
Hi everybody,
Can we force EWS to return an error code, even if it is fine? E.g., send one GetItem and tell it to return a "corrupt" answer so it is actually accessible.
Thanks & regards,
Talib Hussain
EWS API 2.2; Exchange 2010 SP3
$service = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService([Microsoft.Exchange.WebServices.Data.ExchangeVersion]::Exchange2010_SP2)
$service.Credentials = new-object Microsoft.Exchange.WebServices.Data.WebCredentials("ktu","****","adaxes")
$service.AutodiscoverUrl("ktu@carexel.com")
$message = New-Object Microsoft.Exchange.WebServices.Data.EmailMessage -ArgumentList $service
$message.Subject = "This Message has been Created by EWS"
$message.From = "ktutesting@carexel.com"
$message.ToRecipients.Add('EwsTestingTo@LetsExchange.com')
$message.Body = "This is Test Message By Sunil Chauhan From EWS Client"
$message.Save()
===============================================
Try to save an email by using the above cmdlets, get error:
SendAndSaveCopy : Exception calling "SendAndSaveCopy" with "0" argument(s): "The request failed. The underlying connect
ion was closed: An unexpected error occurred on a send."
At line:1 char:22
+ $mail.SendAndSaveCopy <<<< ()
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : DotNetMethodException
I found a thread below, however it doesn't work in our scenario because we do use valid SSL certificate.
Thanks,
Kevin
_https://outlook.com/ews/Exchange.asmx shows _https://yyy.xxx.prod.outlook.com:444/EWS/Services.wsdl but going there returns 500.
_https://outlook.office365.com/ews/services.wsdl also ends with 500
Is it any way to get WSDL?
Hi,
I am writing a C#.NET to send emails using Exchange Web Services APIs. I could find that the code works perfectly when I give the correct user name and password. But, if I give a wrong password on first attempt, the Autodiscover seldom Succeeds.
Here is my sample code:
try { m_EWService = new ExchangeService(ExchangeVersion.Exchange2007_SP1); m_networkCredential = new NetworkCredential(); GetCredentials(sMailbox, out m_networkCredential); m_EWService.Credentials = m_networkCredential; m_EWService.AutodiscoverUrl(m_networkCredential.UserName, RedirectionCallback); } catch (Exception ex) { System.Console.WriteLine(ex.Message); ShowMessage(ex.HResult, ex.Message); }
Can someone throw some light into how to make it working after the login failure;public static void GetCredentials(string serverName, out NetworkCredential networkCredential) { CREDUI_INFO credui = new CREDUI_INFO(); credui.pszCaptionText = "Please enter the credentails for " + serverName; credui.pszMessageText = ""; credui.cbSize = Marshal.SizeOf(credui); uint authPackage = 0; IntPtr outCredBuffer = new IntPtr(); uint outCredSize; bool save = true; int result = CredUIPromptForWindowsCredentials(ref credui, 0, ref authPackage, IntPtr.Zero, 0, out outCredBuffer, out outCredSize, ref save, 0x1 /* Generic */); var usernameBuf = new StringBuilder(100); var passwordBuf = new StringBuilder(100); var domainBuf = new StringBuilder(100); int maxUserName = 100; int maxDomain = 100; int maxPassword = 100; if (result == 0) { if (CredUnPackAuthenticationBuffer(0, outCredBuffer, outCredSize, usernameBuf, ref maxUserName, domainBuf, ref maxDomain, passwordBuf, ref maxPassword)) { //clear the memory allocated by CredUIPromptForWindowsCredentials CoTaskMemFree(outCredBuffer); networkCredential = new NetworkCredential() { UserName = usernameBuf.ToString(), Password = passwordBuf.ToString(), Domain = domainBuf.ToString() }; return; } } networkCredential = null; }
In exchange server create some TransportRule. Like this:
New-TransportRule "Approval1" -HeaderContainsMessageHeader "X-Approval" -HeaderContainsWords "test1-Approval" -ModerateMessageByUsertest1@corp.com,test2@corp.com
New-TransportRule "Approval2" -HeaderContainsMessageHeader "X-Approval" -HeaderContainsWords "test2-Approval" -ModerateMessageByUsertest3@corp.com,test4@corp.com
When user send email , and test2 user approval this email , I want write some data (from,to,subject,body,sendtime,approvalUser,approvalResult) to sql server ,
In custom RoutingAgent class OnSubmittedMessage method,
if MapiMessageClass =IPM.Note.Microsoft.Approval.Reply.Approve this mail is approval mail, and MapiMessageClass= IPM.Note.Microsoft.Approval.Request.Recall or IPM.Note.Microsoft.Approval.Request.reject .
but I don’t The original message, The relationship between them was found.
Thanks all.
Anything is Possible!
Hi,
I am re-writing a C# application which will send out an email using EWS API. Earlier this feature was done using VB6 and CDO components.
Earlier, on connecting to the exchange server, a user credentials dialog will pop up and remembering the credentials is taken care by the (MAPI) system itself.
Is there a similar feature in EWS, which will take care of authenticating the connection/Autodiscover process?
/SanthoshJ