From dd5bcf782bd27d84a19c099e2ed6020feed92963 Mon Sep 17 00:00:00 2001 From: The Gitter Badger Date: Sun, 26 Oct 2014 02:28:17 +0000 Subject: [PATCH 01/22] Added Gitter badge --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index d52039c9..f4fefbfa 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ # Getting Started with the EWS Managed API +[![Gitter](https://badges.gitter.im/Join Chat.svg)](https://gitter.im/OfficeDev/ews-managed-api?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) The Exchange Web Services (EWS) Managed API provides a managed interface for developing .NET client applications that use EWS. By using the EWS Managed API, you can access almost all the information stored in an Office 365, Exchange Online, or Exchange Server mailbox. From b0e8021d51c1547df7aa907d9a3335ed0b9ddf6e Mon Sep 17 00:00:00 2001 From: Victor Boctor Date: Sat, 24 Jan 2015 14:07:18 -0800 Subject: [PATCH 02/22] Reference nuget package in readme The recommended way to download EWS Managed API is via nuget.org. --- README.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index f4fefbfa..e2a99a69 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,12 @@ # Getting Started with the EWS Managed API -[![Gitter](https://badges.gitter.im/Join Chat.svg)](https://gitter.im/OfficeDev/ews-managed-api?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) +[![Gitter](https://badges.gitter.im/Join Chat.svg)](https://gitter.im/OfficeDev/ews-managed-api?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) The Exchange Web Services (EWS) Managed API provides a managed interface for developing .NET client applications that use EWS. By using the EWS Managed API, you can access almost all the information stored in an Office 365, Exchange Online, or Exchange Server mailbox. ## Download options -The EWS Managed API is available as an open-source project on GitHub, or as a Microsoft Windows Installer on the [Microsoft Download Center](http://go.microsoft.com/fwlink/?LinkID=255472). -The project available on GitHub is based on the EWS Managed API 2.2, and includes any updates made since the release of that version. +Download EWS Managed API via [nuget](http://www.nuget.org/packages/Microsoft.Exchange.WebServices/). ## Getting started resources From 45459165001657f3db7d92d094b960d3abec390f Mon Sep 17 00:00:00 2001 From: David Claux Date: Thu, 26 Mar 2015 17:11:26 -0700 Subject: [PATCH 03/22] Port latest updates from Microsoft codebase Thanks to @LukeMarlin and @rich-perry for their contributions. Notable changes: - Removed ResourceManager and need for resx file - Added missing values in WellKnownFolderName enumeration - Added support for GetUserUnifiedGroups - Added support for GetUserPhoto - Added support for FindPeople - Minor bug fixes --- .gitignore | 366 +- Autodiscover/AutodiscoverService.cs | 2 +- ComplexProperties/AttributedString.cs | 137 + .../AttributedStringCollection.cs | 163 + ComplexProperties/Attribution.cs | 137 + ComplexProperties/AttributionCollection.cs | 122 + ComplexProperties/PersonaEmailAddress.cs | 267 + .../PersonaEmailAddressCollection.cs | 194 + ComplexProperties/PersonaId.cs | 89 + .../TimeZones/TimeZoneDefinition.cs | 72 +- .../TimeZones/TimeZoneTransitionGroup.cs | 11 +- Core/EwsUtilities.cs | 13 +- Core/ExchangeService.cs | 279 + Core/PropertySet.cs | 2 + Core/Requests/FindPeopleRequest.cs | 164 + Core/Requests/GetOMEConfigurationRequest.cs | 86 + Core/Requests/GetUserPhotoRequest.cs | 209 + Core/Requests/HangingServiceRequestBase.cs | 4 +- Core/Requests/RegisterConsentRequest.cs | 112 + Core/Requests/ServiceRequestBase.cs | 45 +- .../SetEncryptionConfigurationRequest.cs | 4 +- Core/Requests/SetOMEConfigurationRequest.cs | 100 + Core/Requests/SimpleServiceRequestBase.cs | 17 +- Core/Responses/FindPeopleResponse.cs | 108 + .../GetEncryptionConfigurationResponse.cs | 11 +- Core/Responses/GetOMEConfigurationResponse.cs | 50 + Core/Responses/GetServerTimeZonesResponse.cs | 2 +- Core/Responses/GetUserPhotoResponse.cs | 100 + Core/Responses/RegisterConsentResponse.cs | 28 + Core/Responses/ServiceResponse.cs | 9 + Core/Responses/SetOMEConfigurationResponse.cs | 26 + Core/ServiceObjects/Items/Persona.cs | 367 + Core/ServiceObjects/Schemas/FolderSchema.cs | 2 +- Core/ServiceObjects/Schemas/PersonaSchema.cs | 411 + .../Schemas/ServiceObjectSchema.cs | 1 + Core/ServiceObjects/Schemas/Xsd/messages.xsd | 4139 --------- Core/ServiceObjects/Schemas/Xsd/types.xsd | 7542 ----------------- Core/ServiceObjects/ServiceObjectInfo.cs | 7 + Core/XmlElementNames.cs | 158 + Enumerations/ConsentState.cs | 32 + Enumerations/GetUserPhotoStatus.cs | 33 + Enumerations/ServiceError.cs | 37 +- Enumerations/ServiceObjectType.cs | 7 +- Enumerations/TraceFlags.cs | 5 + Enumerations/UnifiedGroupEnumTypes.cs | 112 + Enumerations/UserPhotoSize.cs | 45 + Enumerations/UserSettingName.cs | 10 + Enumerations/WellKnownFolderName.cs | 86 +- .../RequestedUnifiedGroupsSet.cs | 87 + Groups/ComplexProperties/UnifiedGroup.cs | 165 + .../ComplexProperties/UnifiedGroupIdentity.cs | 72 + Groups/ComplexProperties/UnifiedGroupsSet.cs | 128 + .../GetUnifiedGroupUnseenCountRequest.cs | 134 + .../Requests/GetUserUnifiedGroupsRequest.cs | 135 + .../GetUnifiedGroupUnseenCountResponse.cs | 58 + .../Responses/GetUserUnifiedGroupsResponse.cs | 95 + Microsoft.Exchange.WebServices.Data.csproj | 47 +- Microsoft.Exchange.WebServices.Strings.cs | 2367 ------ Properties/AssemblyInfoOpenSource.cs | 6 +- .../TimeZonePropertyDefinition.cs | 4 +- ResourceManager/ExchangeResourceManager.cs | 125 - ResourceManager/LocalizedString.cs | 621 -- Search/FindPeopleResults.cs | 48 + Search/GetUserPhotoResults.cs | 76 + Search/PeopleIndexedItemView.cs | 173 + Strings.cs | 205 + 66 files changed, 5425 insertions(+), 15044 deletions(-) create mode 100644 ComplexProperties/AttributedString.cs create mode 100644 ComplexProperties/AttributedStringCollection.cs create mode 100644 ComplexProperties/Attribution.cs create mode 100644 ComplexProperties/AttributionCollection.cs create mode 100644 ComplexProperties/PersonaEmailAddress.cs create mode 100644 ComplexProperties/PersonaEmailAddressCollection.cs create mode 100644 ComplexProperties/PersonaId.cs create mode 100644 Core/Requests/FindPeopleRequest.cs create mode 100644 Core/Requests/GetOMEConfigurationRequest.cs create mode 100644 Core/Requests/GetUserPhotoRequest.cs create mode 100644 Core/Requests/RegisterConsentRequest.cs create mode 100644 Core/Requests/SetOMEConfigurationRequest.cs create mode 100644 Core/Responses/FindPeopleResponse.cs create mode 100644 Core/Responses/GetOMEConfigurationResponse.cs create mode 100644 Core/Responses/GetUserPhotoResponse.cs create mode 100644 Core/Responses/RegisterConsentResponse.cs create mode 100644 Core/Responses/SetOMEConfigurationResponse.cs create mode 100644 Core/ServiceObjects/Items/Persona.cs create mode 100644 Core/ServiceObjects/Schemas/PersonaSchema.cs delete mode 100644 Core/ServiceObjects/Schemas/Xsd/messages.xsd delete mode 100644 Core/ServiceObjects/Schemas/Xsd/types.xsd create mode 100644 Enumerations/ConsentState.cs create mode 100644 Enumerations/GetUserPhotoStatus.cs create mode 100644 Enumerations/UnifiedGroupEnumTypes.cs create mode 100644 Enumerations/UserPhotoSize.cs create mode 100644 Groups/ComplexProperties/RequestedUnifiedGroupsSet.cs create mode 100644 Groups/ComplexProperties/UnifiedGroup.cs create mode 100644 Groups/ComplexProperties/UnifiedGroupIdentity.cs create mode 100644 Groups/ComplexProperties/UnifiedGroupsSet.cs create mode 100644 Groups/Requests/GetUnifiedGroupUnseenCountRequest.cs create mode 100644 Groups/Requests/GetUserUnifiedGroupsRequest.cs create mode 100644 Groups/Responses/GetUnifiedGroupUnseenCountResponse.cs create mode 100644 Groups/Responses/GetUserUnifiedGroupsResponse.cs delete mode 100644 Microsoft.Exchange.WebServices.Strings.cs delete mode 100644 ResourceManager/ExchangeResourceManager.cs delete mode 100644 ResourceManager/LocalizedString.cs create mode 100644 Search/FindPeopleResults.cs create mode 100644 Search/GetUserPhotoResults.cs create mode 100644 Search/PeopleIndexedItemView.cs create mode 100644 Strings.cs diff --git a/.gitignore b/.gitignore index 89cb0b08..20938efd 100644 --- a/.gitignore +++ b/.gitignore @@ -1,184 +1,184 @@ -## Ignore Visual Studio temporary files, build results, and -## files generated by popular Visual Studio add-ons. - -# User-specific files -*.suo -*.user -*.userosscache -*.sln.docstates - -# Build results -[Dd]ebug/ -[Dd]ebugPublic/ -[Rr]elease/ -[Rr]eleases/ -x64/ -x86/ -build/ -bld/ -[Bb]in/ -[Oo]bj/ - -# Roslyn cache directories -*.ide/ - -# MSTest test Results -[Tt]est[Rr]esult*/ -[Bb]uild[Ll]og.* - -#NUNIT -*.VisualState.xml -TestResult.xml - -# Build Results of an ATL Project -[Dd]ebugPS/ -[Rr]eleasePS/ -dlldata.c - -*_i.c -*_p.c -*_i.h -*.ilk -*.meta -*.obj -*.pch -*.pdb -*.pgc -*.pgd -*.rsp -*.sbr -*.tlb -*.tli -*.tlh -*.tmp -*.tmp_proj -*.log -*.vspscc -*.vssscc -.builds -*.pidb -*.svclog -*.scc - -# Chutzpah Test files -_Chutzpah* - -# Visual C++ cache files -ipch/ -*.aps -*.ncb -*.opensdf -*.sdf -*.cachefile - -# Visual Studio profiler -*.psess -*.vsp -*.vspx - -# TFS 2012 Local Workspace -$tf/ - -# Guidance Automation Toolkit -*.gpState - -# ReSharper is a .NET coding add-in -_ReSharper*/ -*.[Rr]e[Ss]harper -*.DotSettings.user - -# JustCode is a .NET coding addin-in -.JustCode - -# TeamCity is a build add-in -_TeamCity* - -# DotCover is a Code Coverage Tool -*.dotCover - -# NCrunch -_NCrunch_* -.*crunch*.local.xml - -# MightyMoose -*.mm.* -AutoTest.Net/ - -# Web workbench (sass) -.sass-cache/ - -# Installshield output folder -[Ee]xpress/ - -# DocProject is a documentation generator add-in -DocProject/buildhelp/ -DocProject/Help/*.HxT -DocProject/Help/*.HxC -DocProject/Help/*.hhc -DocProject/Help/*.hhk -DocProject/Help/*.hhp -DocProject/Help/Html2 -DocProject/Help/html - -# Click-Once directory -publish/ - -# Publish Web Output -*.[Pp]ublish.xml -*.azurePubxml -# TODO: Comment the next line if you want to checkin your web deploy settings -# but database connection strings (with potential passwords) will be unencrypted -*.pubxml -*.publishproj - -# NuGet Packages -*.nupkg -# The packages folder can be ignored because of Package Restore -**/packages/* -# except build/, which is used as an MSBuild target. -!**/packages/build/ -# If using the old MSBuild-Integrated Package Restore, uncomment this: -#!**/packages/repositories.config - -# Windows Azure Build Output -csx/ -*.build.csdef - -# Windows Store app package directory -AppPackages/ - -# Others -sql/ -*.Cache -ClientBin/ -[Ss]tyle[Cc]op.* -~$* -*~ -*.dbmdl -*.dbproj.schemaview -*.pfx -*.publishsettings -node_modules/ - -# RIA/Silverlight projects -Generated_Code/ - -# Backup & report files from converting an old project file -# to a newer Visual Studio version. Backup files are not needed, -# because we have git ;-) -_UpgradeReport_Files/ -Backup*/ -UpgradeLog*.XML -UpgradeLog*.htm - -# SQL Server files -*.mdf -*.ldf - -# Business Intelligence projects -*.rdl.data -*.bim.layout -*.bim_*.settings - -# Microsoft Fakes +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.userosscache +*.sln.docstates + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +build/ +bld/ +[Bb]in/ +[Oo]bj/ + +# Roslyn cache directories +*.ide/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +#NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opensdf +*.sdf +*.cachefile + +# Visual Studio profiler +*.psess +*.vsp +*.vspx + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding addin-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# NCrunch +_NCrunch_* +.*crunch*.local.xml + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# TODO: Comment the next line if you want to checkin your web deploy settings +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# NuGet Packages +*.nupkg +# The packages folder can be ignored because of Package Restore +**/packages/* +# except build/, which is used as an MSBuild target. +!**/packages/build/ +# If using the old MSBuild-Integrated Package Restore, uncomment this: +#!**/packages/repositories.config + +# Windows Azure Build Output +csx/ +*.build.csdef + +# Windows Store app package directory +AppPackages/ + +# Others +sql/ +*.Cache +ClientBin/ +[Ss]tyle[Cc]op.* +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.pfx +*.publishsettings +node_modules/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +*.mdf +*.ldf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings + +# Microsoft Fakes FakesAssemblies/ \ No newline at end of file diff --git a/Autodiscover/AutodiscoverService.cs b/Autodiscover/AutodiscoverService.cs index 35c09b8c..a72c5c15 100644 --- a/Autodiscover/AutodiscoverService.cs +++ b/Autodiscover/AutodiscoverService.cs @@ -694,7 +694,7 @@ private bool TryLastChanceHostRedirection( this.DisableScpLookupIfDuplicateRedirection(settings.RedirectTarget, redirectionEmailAddresses); settings = this.InternalGetLegacyUserSettings( - emailAddress, + settings.RedirectTarget, redirectionEmailAddresses, ref currentHop); return true; diff --git a/ComplexProperties/AttributedString.cs b/ComplexProperties/AttributedString.cs new file mode 100644 index 00000000..858d226c --- /dev/null +++ b/ComplexProperties/AttributedString.cs @@ -0,0 +1,137 @@ +// --------------------------------------------------------------------------- +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// --------------------------------------------------------------------------- + +//----------------------------------------------------------------------- +// Defines the AttributedString class. +//----------------------------------------------------------------------- + +namespace Microsoft.Exchange.WebServices.Data +{ + using System; + using System.Collections.Generic; + using System.Xml; + + /// + /// Represents an attributed string, a string with a value and a list of attributions. + /// + public sealed class AttributedString : ComplexProperty + { + /// + /// Internal attribution store + /// + private List attributionList; + + /// + /// String value + /// + public string Value { get; set; } + + /// + /// Attribution values + /// + public IList Attributions { get; set; } + + /// + /// Default constructor + /// + public AttributedString() + : base() + { + } + + /// + /// Constructor + /// + public AttributedString(string value) + : this() + { + EwsUtilities.ValidateParam(value, "value"); + this.Value = value; + } + + /// + /// Constructor + /// + /// String value + /// A list of attributions + public AttributedString(string value, IList attributions) + : this(value) + { + if (attributions == null) + { + throw new ArgumentNullException("attributions"); + } + + foreach (string s in attributions) + { + EwsUtilities.ValidateParam(s, "attributions"); + } + + this.Attributions = attributions; + } + + /// + /// Defines an implicit conversion from a regular string to an attributedString. + /// + /// String value of the attributed string being created + /// An attributed string initialized with the specified value + public static implicit operator AttributedString(string value) + { + return new AttributedString(value); + } + + /// + /// Tries to read an attributed string blob represented in XML. + /// + /// XML reader + /// Whether reading succeeded + internal override bool TryReadElementFromXml(EwsServiceXmlReader reader) + { + switch (reader.LocalName) + { + case XmlElementNames.Value: + this.Value = reader.ReadElementValue(); + return true; + case XmlElementNames.Attributions: + return this.LoadAttributionsFromXml(reader); + default: + return false; + } + } + + /// + /// Read attribution blobs from XML + /// + /// XML reader + /// Whether reading succeeded + internal bool LoadAttributionsFromXml(EwsServiceXmlReader reader) + { + if (!reader.IsEmptyElement) + { + string localName = reader.LocalName; + this.attributionList = new List(); + + do + { + reader.Read(); + if (reader.NodeType == XmlNodeType.Element && + reader.LocalName == XmlElementNames.Attribution) + { + string s = reader.ReadElementValue(); + if (!string.IsNullOrEmpty(s)) + { + this.attributionList.Add(s); + } + } + } + while (!reader.IsEndElement(XmlNamespace.Types, localName)); + this.Attributions = this.attributionList.ToArray(); + } + + return true; + } + } +} diff --git a/ComplexProperties/AttributedStringCollection.cs b/ComplexProperties/AttributedStringCollection.cs new file mode 100644 index 00000000..70989a72 --- /dev/null +++ b/ComplexProperties/AttributedStringCollection.cs @@ -0,0 +1,163 @@ +// --------------------------------------------------------------------------- +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// --------------------------------------------------------------------------- + +//----------------------------------------------------------------------- +// Implements an attributed string collection. +//----------------------------------------------------------------------- + +namespace Microsoft.Exchange.WebServices.Data +{ + using System.Collections.Generic; + + /// + /// Represents a collection of attributed strings + /// + public sealed class AttributedStringCollection : ComplexPropertyCollection + { + /// + /// Collection parent XML element name + /// + private readonly string collectionItemXmlElementName; + + /// + /// Creates a new instance of the class. + /// + internal AttributedStringCollection() + : this(XmlElementNames.StringAttributedValue) + { + } + + /// + /// Creates a new instance of the class. + /// + /// Name of the collection item XML element. + internal AttributedStringCollection(string collectionItemXmlElementName) + : base() + { + EwsUtilities.ValidateParam(collectionItemXmlElementName, "collectionItemXmlElementName"); + this.collectionItemXmlElementName = collectionItemXmlElementName; + } + + /// + /// Adds an attributed string to the collection. + /// + /// Attributed string to be added + public void Add(AttributedString attributedString) + { + this.InternalAdd(attributedString); + } + + /// + /// Adds multiple attributed strings to the collection. + /// + /// Attributed strings to be added + public void AddRange(IEnumerable attributedStrings) + { + if (attributedStrings != null) + { + foreach (AttributedString attributedString in attributedStrings) + { + this.Add(attributedString); + } + } + } + + /// + /// Adds an attributed string to the collection. + /// + /// The SMTP address used to initialize the e-mail address. + /// An AttributedString object initialized with the provided SMTP address. + public AttributedString Add(string stringValue) + { + AttributedString attributedString = new AttributedString(stringValue); + + this.Add(attributedString); + + return attributedString; + } + + /// + /// Adds a string value and list of attributions + /// + /// String value of the attributed string being added + /// Attributions of the attributed string being added + /// The added attributedString object + public AttributedString Add(string stringValue, IList attributions) + { + AttributedString attributedString = new AttributedString(stringValue, attributions); + + this.Add(attributedString); + + return attributedString; + } + + /// + /// Clears the collection. + /// + public void Clear() + { + this.InternalClear(); + } + + /// + /// Removes an attributed string from the collection. + /// + /// Attributed string to be removed + /// Whether succeeded + public bool Remove(AttributedString attributedString) + { + EwsUtilities.ValidateParam(attributedString, "attributedString"); + + return this.InternalRemove(attributedString); + } + + /// + /// Creates an AttributedString object from an XML element name. + /// + /// The XML element name from which to create the attributed string object + /// An AttributedString object + internal override AttributedString CreateComplexProperty(string xmlElementName) + { + EwsUtilities.ValidateParam(xmlElementName, "xmlElementName"); + if (xmlElementName == this.collectionItemXmlElementName) + { + return new AttributedString(); + } + else + { + return null; + } + } + + /// + /// Creates the default complex property. + /// + /// + internal override AttributedString CreateDefaultComplexProperty() + { + return new AttributedString(); + } + + /// + /// Retrieves the XML element name corresponding to the provided AttributedString object. + /// + /// The AttributedString object from which to determine the XML element name. + /// The XML element name corresponding to the provided AttributedString object. + internal override string GetCollectionItemXmlElementName(AttributedString attributedString) + { + return this.collectionItemXmlElementName; + } + + /// + /// Determine whether we should write collection to XML or not. + /// + /// Always true, even if the collection is empty. + internal override bool ShouldWriteToRequest() + { + return true; + } + } +} diff --git a/ComplexProperties/Attribution.cs b/ComplexProperties/Attribution.cs new file mode 100644 index 00000000..362744fb --- /dev/null +++ b/ComplexProperties/Attribution.cs @@ -0,0 +1,137 @@ +// --------------------------------------------------------------------------- +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// --------------------------------------------------------------------------- + +//----------------------------------------------------------------------- +// Defines the Attribution class. +//----------------------------------------------------------------------- + +namespace Microsoft.Exchange.WebServices.Data +{ + /// + /// Represents an attribution of an attributed string + /// + public sealed class Attribution : ComplexProperty + { + /// + /// Attribution id + /// + public string Id { get; set; } + + /// + /// Attribution source + /// + public ItemId SourceId { get; set; } + + /// + /// Display name + /// + public string DisplayName { get; set; } + + /// + /// Whether writable + /// + public bool IsWritable { get; set; } + + /// + /// Whether a quick contact + /// + public bool IsQuickContact { get; set; } + + /// + /// Whether hidden + /// + public bool IsHidden { get; set; } + + /// + /// Folder id + /// + public FolderId FolderId { get; set; } + + /// + /// Default constructor + /// + public Attribution() + : base() + { + } + + /// + /// Creates an instance with required values only + /// + /// Attribution id + /// Source Id + /// Display name + public Attribution(string id, ItemId sourceId, string displayName) + : this(id, sourceId, displayName, false, false, false, null) + { + } + + /// + /// Creates an instance with all values + /// + /// Attribution id + /// Source Id + /// Display name + /// Whether writable + /// Wther quick contact + /// Whether hidden + /// Folder id + public Attribution(string id, ItemId sourceId, string displayName, bool isWritable, bool isQuickContact, bool isHidden, FolderId folderId) + : this() + { + EwsUtilities.ValidateParam(id, "id"); + EwsUtilities.ValidateParam(displayName, "displayName"); + + this.Id = id; + this.SourceId = sourceId; + this.DisplayName = displayName; + this.IsWritable = isWritable; + this.IsQuickContact = isQuickContact; + this.IsHidden = isHidden; + this.FolderId = folderId; + } + + /// + /// Tries to read element from XML + /// + /// XML reader + /// Whether reading succeeded + internal override bool TryReadElementFromXml(EwsServiceXmlReader reader) + { + switch (reader.LocalName) + { + case XmlElementNames.Id: + this.Id = reader.ReadElementValue(); + break; + case XmlElementNames.SourceId: + this.SourceId = new ItemId(); + this.SourceId.LoadFromXml(reader, reader.LocalName); + break; + case XmlElementNames.DisplayName: + this.DisplayName = reader.ReadElementValue(); + break; + case XmlElementNames.IsWritable: + this.IsWritable = reader.ReadElementValue(); + break; + case XmlElementNames.IsQuickContact: + this.IsQuickContact = reader.ReadElementValue(); + break; + case XmlElementNames.IsHidden: + this.IsHidden = reader.ReadElementValue(); + break; + case XmlElementNames.FolderId: + this.FolderId = new FolderId(); + this.FolderId.LoadFromXml(reader, reader.LocalName); + break; + + default: + return base.TryReadElementFromXml(reader); + } + + return true; + } + } +} diff --git a/ComplexProperties/AttributionCollection.cs b/ComplexProperties/AttributionCollection.cs new file mode 100644 index 00000000..7e6fece8 --- /dev/null +++ b/ComplexProperties/AttributionCollection.cs @@ -0,0 +1,122 @@ +// --------------------------------------------------------------------------- +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// --------------------------------------------------------------------------- + +//----------------------------------------------------------------------- +// Implements an attribution collection. +//----------------------------------------------------------------------- + +namespace Microsoft.Exchange.WebServices.Data +{ + using System.Collections.Generic; + + /// + /// Represents a collection of attributions + /// + public sealed class AttributionCollection : ComplexPropertyCollection + { + /// + /// XML element name + /// + private readonly string collectionItemXmlElementName; + + /// + /// Creates a new instance of the class. + /// + internal AttributionCollection() + : this(XmlElementNames.Attribution) + { + } + + /// + /// Creates a new instance of the class. + /// + /// Name of the collection item XML element. + internal AttributionCollection(string collectionItemXmlElementName) + : base() + { + EwsUtilities.ValidateParam(collectionItemXmlElementName, "collectionItemXmlElementName"); + this.collectionItemXmlElementName = collectionItemXmlElementName; + } + + /// + /// Adds an attribution to the collection. + /// + /// Attributions to be added + public void Add(Attribution attribution) + { + this.InternalAdd(attribution); + } + + /// + /// Adds multiple attributions to the collection. + /// + /// Attributions to be added + public void AddRange(IEnumerable attributions) + { + if (attributions != null) + { + foreach (Attribution attribution in attributions) + { + this.Add(attribution); + } + } + } + + /// + /// Clears the collection. + /// + public void Clear() + { + this.InternalClear(); + } + + /// + /// Creates an attribution object from an XML element name. + /// + /// Attribution XML node name + /// The attribution object created + internal override Attribution CreateComplexProperty(string xmlElementName) + { + EwsUtilities.ValidateParam(xmlElementName, "xmlElementName"); + if (xmlElementName == this.collectionItemXmlElementName) + { + return new Attribution(); + } + else + { + return null; + } + } + + /// + /// Creates the default complex property. + /// + /// + internal override Attribution CreateDefaultComplexProperty() + { + return new Attribution(); + } + + /// + /// Retrieves the XML element name corresponding to the provided attribution object. + /// + /// The attribution object from which to determine the XML element name. + /// The XML element name corresponding to the provided attribution object. + internal override string GetCollectionItemXmlElementName(Attribution attribution) + { + return this.collectionItemXmlElementName; + } + + /// + /// Determine whether we should write collection to XML or not. + /// + /// Always true, even if the collection is empty. + internal override bool ShouldWriteToRequest() + { + return true; + } + } +} diff --git a/ComplexProperties/PersonaEmailAddress.cs b/ComplexProperties/PersonaEmailAddress.cs new file mode 100644 index 00000000..0f74bf18 --- /dev/null +++ b/ComplexProperties/PersonaEmailAddress.cs @@ -0,0 +1,267 @@ +// --------------------------------------------------------------------------- +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// --------------------------------------------------------------------------- + +//----------------------------------------------------------------------- +// Defines the PersonaEmailAddress class. +//----------------------------------------------------------------------- + +namespace Microsoft.Exchange.WebServices.Data +{ + /// + /// Represents an e-mail address. + /// + public sealed class PersonaEmailAddress : ComplexProperty, ISearchStringProvider + { + /// + /// Creates a new instance of the class. + /// + public PersonaEmailAddress() + : base() + { + _emailAddress = new EmailAddress(); + } + + /// + /// Creates a new instance of the class. + /// + /// The SMTP address used to initialize the PersonaEmailAddress. + public PersonaEmailAddress(string smtpAddress) + : this() + { + EwsUtilities.ValidateParam(smtpAddress, "smtpAddress"); + this.Address = smtpAddress; + } + + /// + /// Creates a new instance of the class. + /// + /// The name used to initialize the PersonaEmailAddress. + /// The SMTP address used to initialize the PersonaEmailAddress. + public PersonaEmailAddress(string name, string smtpAddress) + : this(smtpAddress) + { + EwsUtilities.ValidateParam(name, "name"); + this.Name = name; + } + + /// + /// Name accessors + /// + public string Name + { + get + { + return _emailAddress.Name; + } + + set + { + _emailAddress.Name = value; + } + } + + /// + /// Email address accessors. The type of the Address property must match the specified routing type. + /// If RoutingType is not set, Address is assumed to be an SMTP address. + /// + public string Address + { + get + { + return _emailAddress.Address; + } + + set + { + _emailAddress.Address = value; + } + } + + /// + /// Routing type accessors. If RoutingType is not set, Address is assumed to be an SMTP address. + /// + public string RoutingType + { + get + { + return _emailAddress.RoutingType; + } + + set + { + _emailAddress.RoutingType = value; + } + } + + /// + /// Mailbox type accessors + /// + public MailboxType? MailboxType + { + get + { + return _emailAddress.MailboxType; + } + + set + { + _emailAddress.MailboxType = value; + } + } + + /// + /// PersonaEmailAddress Id accessors + /// + public ItemId Id + { + get + { + return _emailAddress.Id; + } + + set + { + _emailAddress.Id = value; + } + } + + /// + /// Original display name accessors + /// + public string OriginalDisplayName { get; set; } + + /// + /// Email address details + /// + private EmailAddress _emailAddress; + + /// + /// Defines an implicit conversion from a string representing an SMTP address to PeronaEmailAddress. + /// + /// The SMTP address to convert to EmailAddress. + /// An EmailAddress initialized with the specified SMTP address. + public static implicit operator PersonaEmailAddress(string smtpAddress) + { + return new PersonaEmailAddress(smtpAddress); + } + + /// + /// Tries to read element from XML. + /// + /// XML reader + /// Whether the element was read + internal override bool TryReadElementFromXml(EwsServiceXmlReader reader) + { + while (true) + { + switch (reader.LocalName) + { + case XmlElementNames.Name: + this.Name = reader.ReadElementValue(); + break; + case XmlElementNames.EmailAddress: + this.Address = reader.ReadElementValue(); + + // Process the next node before returning. Otherwise, the current node + // makes ComplexProperty.InternalLoadFromXml think that this ends the outer + // node, causing the remaining children of the outer EmailAddress node to be skipped. + reader.Read(); + if (reader.NodeType == System.Xml.XmlNodeType.Element) + { + continue; + } + break; + case XmlElementNames.RoutingType: + this.RoutingType = reader.ReadElementValue(); + break; + case XmlElementNames.MailboxType: + this.MailboxType = reader.ReadElementValue(); + break; + case XmlElementNames.ItemId: + this.Id = new ItemId(); + this.Id.LoadFromXml(reader, reader.LocalName); + break; + case XmlElementNames.OriginalDisplayName: + this.OriginalDisplayName = reader.ReadElementValue(); + break; + default: + return false; + } + + return true; + } + } + + /// + /// Writes elements to XML. + /// + /// XML writer + internal override void WriteElementsToXml(EwsServiceXmlWriter writer) + { + writer.WriteElementValue(XmlNamespace.Types, XmlElementNames.Name, this.Name); + writer.WriteElementValue(XmlNamespace.Types, XmlElementNames.EmailAddress, this.Address); + writer.WriteElementValue(XmlNamespace.Types, XmlElementNames.RoutingType, this.RoutingType); + writer.WriteElementValue(XmlNamespace.Types, XmlElementNames.MailboxType, this.MailboxType); + + if (!string.IsNullOrEmpty(this.OriginalDisplayName)) + { + writer.WriteElementValue(XmlNamespace.Types, XmlElementNames.OriginalDisplayName, this.OriginalDisplayName); + } + + if (this.Id != null) + { + this.Id.WriteToXml(writer, XmlElementNames.ItemId); + } + } + + #region ISearchStringProvider methods + /// + /// Get a string representation for using this instance in a search filter. + /// + /// String representation of instance. + string ISearchStringProvider.GetSearchString() + { + return this.Address; + } + #endregion + + #region Object method overrides + /// + /// Returns a that represents the current . + /// + /// + /// A that represents the current . + /// + public override string ToString() + { + string addressPart; + + if (string.IsNullOrEmpty(this.Address)) + { + return string.Empty; + } + + if (!string.IsNullOrEmpty(this.RoutingType)) + { + addressPart = this.RoutingType + ":" + this.Address; + } + else + { + addressPart = this.Address; + } + + if (!string.IsNullOrEmpty(this.Name)) + { + return this.Name + " <" + addressPart + ">"; + } + else + { + return addressPart; + } + } + #endregion + } +} diff --git a/ComplexProperties/PersonaEmailAddressCollection.cs b/ComplexProperties/PersonaEmailAddressCollection.cs new file mode 100644 index 00000000..bedf3223 --- /dev/null +++ b/ComplexProperties/PersonaEmailAddressCollection.cs @@ -0,0 +1,194 @@ +// --------------------------------------------------------------------------- +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// --------------------------------------------------------------------------- + +//----------------------------------------------------------------------- +// Implements an e-mail address collection. +//----------------------------------------------------------------------- + +namespace Microsoft.Exchange.WebServices.Data +{ + using System; + using System.Collections.Generic; + + /// + /// Represents a collection of persona e-mail addresses. + /// + public sealed class PersonaEmailAddressCollection : ComplexPropertyCollection + { + /// + /// XML element name + /// + private readonly string collectionItemXmlElementName; + + /// + /// Creates a new instance of the class. + /// + /// + /// MSDN example incorrectly shows root element as EmailAddress. In fact, it is Address. + /// + internal PersonaEmailAddressCollection() + : this(XmlElementNames.Address) + { + } + + /// + /// Creates a new instance of the class. + /// + /// Name of the collection item XML element. + internal PersonaEmailAddressCollection(string collectionItemXmlElementName) + : base() + { + this.collectionItemXmlElementName = collectionItemXmlElementName; + } + + /// + /// Adds a persona e-mail address to the collection. + /// + /// The persona e-mail address to add. + public void Add(PersonaEmailAddress emailAddress) + { + this.InternalAdd(emailAddress); + } + + /// + /// Adds multiple persona e-mail addresses to the collection. + /// + /// The collection of persona e-mail addresses to add. + public void AddRange(IEnumerable emailAddresses) + { + if (emailAddresses != null) + { + foreach (PersonaEmailAddress emailAddress in emailAddresses) + { + this.Add(emailAddress); + } + } + } + + /// + /// Adds a persona e-mail address to the collection. + /// + /// The SMTP address used to initialize the persona e-mail address. + /// An PersonaEmailAddress object initialized with the provided SMTP address. + public PersonaEmailAddress Add(string smtpAddress) + { + PersonaEmailAddress emailAddress = new PersonaEmailAddress(smtpAddress); + + this.Add(emailAddress); + + return emailAddress; + } + + /// + /// Adds multiple e-mail addresses to the collection. + /// + /// The SMTP addresses to be added as persona email addresses + public void AddRange(IEnumerable smtpAddresses) + { + if (smtpAddresses != null) + { + foreach (string smtpAddress in smtpAddresses) + { + this.Add(smtpAddress); + } + } + } + + /// + /// Adds an e-mail address to the collection. + /// + /// The name used to initialize the persona e-mail address. + /// The SMTP address used to initialize the persona e-mail address. + /// An PersonaEmailAddress object initialized with the provided SMTP address. + public PersonaEmailAddress Add(string name, string smtpAddress) + { + PersonaEmailAddress emailAddress = new PersonaEmailAddress(name, smtpAddress); + + this.Add(emailAddress); + + return emailAddress; + } + + /// + /// Clears the collection. + /// + public void Clear() + { + this.InternalClear(); + } + + /// + /// Removes a persona e-mail address from the collection. + /// + /// The index of the e-mail address to remove. + public void RemoveAt(int index) + { + if (index < 0 || index >= this.Count) + { + throw new ArgumentOutOfRangeException("index", Strings.IndexIsOutOfRange); + } + + this.InternalRemoveAt(index); + } + + /// + /// Removes a persona e-mail address from the collection. + /// + /// The e-mail address to remove. + /// Whether removed from the collection + public bool Remove(PersonaEmailAddress personaEmailAddress) + { + EwsUtilities.ValidateParam(personaEmailAddress, "personaEmailAddress"); + + return this.InternalRemove(personaEmailAddress); + } + + /// + /// Creates a PersonaEmailAddress object from an XML element name. + /// + /// The XML element name from which to create the persona e-mail address. + /// A PersonaEmailAddress object. + internal override PersonaEmailAddress CreateComplexProperty(string xmlElementName) + { + if (xmlElementName == this.collectionItemXmlElementName) + { + return new PersonaEmailAddress(); + } + else + { + return null; + } + } + + /// + /// Creates the default complex property. + /// + /// + internal override PersonaEmailAddress CreateDefaultComplexProperty() + { + return new PersonaEmailAddress(); + } + + /// + /// Retrieves the XML element name corresponding to the provided PersonaEmailAddress object. + /// + /// The PersonaEmailAddress object from which to determine the XML element name. + /// The XML element name corresponding to the provided PersonaEmailAddress object. + internal override string GetCollectionItemXmlElementName(PersonaEmailAddress personaEmailAddress) + { + return this.collectionItemXmlElementName; + } + + /// + /// Determine whether we should write collection to XML or not. + /// + /// Always true, even if the collection is empty. + internal override bool ShouldWriteToRequest() + { + return true; + } + } +} diff --git a/ComplexProperties/PersonaId.cs b/ComplexProperties/PersonaId.cs new file mode 100644 index 00000000..413d1ce1 --- /dev/null +++ b/ComplexProperties/PersonaId.cs @@ -0,0 +1,89 @@ +// --------------------------------------------------------------------------- +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// --------------------------------------------------------------------------- + +//----------------------------------------------------------------------- +// Defines the PersonaId class. +//----------------------------------------------------------------------- + +namespace Microsoft.Exchange.WebServices.Data +{ + using System; + + /// + /// Represents the Id of a Persona. + /// + public sealed class PersonaId : ServiceId + { + /// + /// Creates a new instance of the class. + /// + internal PersonaId() + : base() + { + } + + /// + /// Defines an implicit conversion from Id string to PersonaId. + /// + /// The unique Id to convert to PersonaId. + /// A PersonaId initialized with the specified unique Id. + public static implicit operator PersonaId(string uniqueId) + { + return new PersonaId(uniqueId); + } + + /// + /// Defines an implicit conversion from PersonaId to a Id string. + /// + /// The PersonaId to be converted + /// A PersonaId initialized with the specified unique Id. + public static implicit operator String(PersonaId PersonaId) + { + if (PersonaId == null) + { + throw new ArgumentNullException("PersonaId"); + } + + if (String.IsNullOrEmpty(PersonaId.UniqueId)) + { + return string.Empty; + } + else + { + // Ignoring the change key info + return PersonaId.UniqueId; + } + } + + /// + /// Gets the name of the XML element. + /// + /// XML element name. + internal override string GetXmlElementName() + { + return XmlElementNames.PersonaId; + } + + /// + /// Creates a new instance of PersonaId. + /// + /// The unique Id used to initialize the . + public PersonaId(string uniqueId) + : base(uniqueId) + { + } + + /// + /// Gets a string representation of the Persona Id. + /// + /// The string representation of the Persona id. + public override string ToString() + { + // We have ignored the change key portion + return this.UniqueId; + } + } +} \ No newline at end of file diff --git a/ComplexProperties/TimeZones/TimeZoneDefinition.cs b/ComplexProperties/TimeZones/TimeZoneDefinition.cs index 84923ebd..00dd8a32 100644 --- a/ComplexProperties/TimeZones/TimeZoneDefinition.cs +++ b/ComplexProperties/TimeZones/TimeZoneDefinition.cs @@ -84,15 +84,15 @@ internal TimeZoneDefinition(TimeZoneInfo timeZoneInfo) standardPeriod.Id = TimeZonePeriod.StandardPeriodId; standardPeriod.Name = TimeZonePeriod.StandardPeriodName; standardPeriod.Bias = -timeZoneInfo.BaseUtcOffset; - - this.periods.Add(standardPeriod.Id, standardPeriod); - + TimeZoneInfo.AdjustmentRule[] adjustmentRules = timeZoneInfo.GetAdjustmentRules(); TimeZoneTransition transitionToStandardPeriod = new TimeZoneTransition(this, standardPeriod); if (adjustmentRules.Length == 0) { + this.periods.Add(standardPeriod.Id, standardPeriod); + // If the time zone info doesn't support Daylight Saving Time, we just need to // create one transition to one group with one transition to the standard period. TimeZoneTransitionGroup transitionGroup = new TimeZoneTransitionGroup(this, "0"); @@ -132,6 +132,7 @@ internal TimeZoneDefinition(TimeZoneInfo timeZoneInfo) absoluteDateTransition.DateTime = adjustmentRules[i].DateStart; transition = absoluteDateTransition; + this.periods.Add(standardPeriod.Id, standardPeriod); } else { @@ -235,7 +236,24 @@ internal override bool TryReadElementFromXml(EwsServiceXmlReader reader) TimeZonePeriod period = new TimeZonePeriod(); period.LoadFromXml(reader); - this.periods.Add(period.Id, period); + // OM:1648848 Bad timezone data from clients can include duplicate rules + // for one year, with duplicate ID. In that case, let the first one win. + if (!this.periods.ContainsKey(period.Id)) + { + this.periods.Add(period.Id, period); + } + else + { + reader.Service.TraceMessage( + TraceFlags.EwsTimeZones, + string.Format( + "An entry with the same key (Id) '{0}' already exists in Periods. Cannot add another one. Existing entry: [Name='{1}', Bias='{2}']. Entry to skip: [Name='{3}', Bias='{4}'].", + period.Id, + this.Periods[period.Id].Name, + this.Periods[period.Id].Bias, + period.Name, + period.Bias)); + } } } while (!reader.IsEndElement(XmlNamespace.Types, XmlElementNames.Periods)); @@ -316,7 +334,24 @@ internal override void LoadFromJson(JsonObject jsonProperty, ExchangeService ser TimeZonePeriod period = new TimeZonePeriod(); period.LoadFromJson(jsonPeriod as JsonObject, service); - this.periods.Add(period.Id, period); + // OM:1648848 Bad timezone data from clients can include duplicate rules + // for one year, with duplicate ID. In that case, let the first one win. + if (!this.periods.ContainsKey(period.Id)) + { + this.periods.Add(period.Id, period); + } + else + { + service.TraceMessage( + TraceFlags.EwsTimeZones, + string.Format( + "An entry with the same key (Id) '{0}' already exists in Periods. Cannot add another one. Existing entry: [Name='{1}', Bias='{2}']. Entry to skip: [Name='{3}', Bias='{4}'].", + period.Id, + this.Periods[period.Id].Name, + this.Periods[period.Id].Bias, + period.Name, + period.Bias)); + } } break; @@ -524,8 +559,9 @@ internal void Validate() /// /// Converts this time zone definition into a TimeZoneInfo structure. /// + /// The service. /// A TimeZoneInfo representing the same time zone as this definition. - internal TimeZoneInfo ToTimeZoneInfo() + internal TimeZoneInfo ToTimeZoneInfo(ExchangeService service) { this.Validate(); @@ -556,14 +592,28 @@ internal TimeZoneInfo ToTimeZoneInfo() effectiveEndDate = endDate; } - TimeZoneInfo.AdjustmentRule adjustmentRule = this.transitions[i].TargetGroup.CreateAdjustmentRule(startDate, effectiveEndDate); + // OM:1648848 Due to bad timezone data from clients the + // startDate may not always come before the effectiveEndDate + if (startDate < effectiveEndDate) + { + TimeZoneInfo.AdjustmentRule adjustmentRule = this.transitions[i].TargetGroup.CreateAdjustmentRule(startDate, effectiveEndDate); - if (adjustmentRule != null) + if (adjustmentRule != null) + { + adjustmentRules.Add(adjustmentRule); + } + + startDate = endDate; + } + else { - adjustmentRules.Add(adjustmentRule); + service.TraceMessage( + TraceFlags.EwsTimeZones, + string.Format( + "The startDate '{0}' is not before the effectiveEndDate '{1}'. Will skip creating adjustment rule.", + startDate, + effectiveEndDate)); } - - startDate = endDate; } if (adjustmentRules.Count == 0) diff --git a/ComplexProperties/TimeZones/TimeZoneTransitionGroup.cs b/ComplexProperties/TimeZones/TimeZoneTransitionGroup.cs index 2a68bae6..c72aa7dd 100644 --- a/ComplexProperties/TimeZones/TimeZoneTransitionGroup.cs +++ b/ComplexProperties/TimeZones/TimeZoneTransitionGroup.cs @@ -177,9 +177,18 @@ internal virtual void InitializeFromAdjustmentRule(TimeZoneInfo.AdjustmentRule a daylightPeriod, adjustmentRule.DaylightTransitionStart); + TimeZonePeriod standardPeriodToSet = new TimeZonePeriod(); + standardPeriodToSet.Id = string.Format( + "{0}/{1}", + standardPeriod.Id, + adjustmentRule.DateStart.Year); + standardPeriodToSet.Name = standardPeriod.Name; + standardPeriodToSet.Bias = standardPeriod.Bias; + this.timeZoneDefinition.Periods.Add(standardPeriodToSet.Id, standardPeriodToSet); + this.transitionToStandard = TimeZoneTransition.CreateTimeZoneTransition( this.timeZoneDefinition, - standardPeriod, + standardPeriodToSet, adjustmentRule.DaylightTransitionEnd); this.transitions.Add(this.transitionToDaylight); diff --git a/Core/EwsUtilities.cs b/Core/EwsUtilities.cs index b5c93c4a..92c906a3 100644 --- a/Core/EwsUtilities.cs +++ b/Core/EwsUtilities.cs @@ -46,8 +46,17 @@ internal static class EwsUtilities private static LazyMember buildVersion = new LazyMember( delegate() { - FileVersionInfo fileInfo = FileVersionInfo.GetVersionInfo(Assembly.GetExecutingAssembly().Location); - return fileInfo.FileVersion; + try + { + FileVersionInfo fileInfo = FileVersionInfo.GetVersionInfo(Assembly.GetExecutingAssembly().Location); + return fileInfo.FileVersion; + } + catch + { + // OM:2026839 When run in an environment with partial trust, fetching the build version blows up. + // Just return a hardcoded value on failure. + return "0.0"; + } }); /// diff --git a/Core/ExchangeService.cs b/Core/ExchangeService.cs index 75f2374b..45e40069 100644 --- a/Core/ExchangeService.cs +++ b/Core/ExchangeService.cs @@ -19,6 +19,8 @@ namespace Microsoft.Exchange.WebServices.Data using System.Net; using System.Xml; using Microsoft.Exchange.WebServices.Autodiscover; + using Microsoft.Exchange.WebServices.Data.Enumerations; + using Microsoft.Exchange.WebServices.Data.Groups; /// /// Represents a binding to the Exchange Web Services. @@ -29,6 +31,18 @@ public sealed class ExchangeService : ExchangeServiceBase private const string TargetServerVersionHeaderName = "X-EWS-TargetVersion"; + /// + /// The two contants below are used to set the AnchorMailbox and ExplicitLogonUser values + /// in the request header. + /// + /// + /// Note: Setting this values will route the request directly to the backend hosting the + /// AnchorMailbox. These headers should be used primarily for UnifiedGroup scenario where + /// a request needs to be routed directly to the group mailbox versus the user mailbox. + /// + private const string AnchorMailboxHeaderName = "X-AnchorMailbox"; + private const string ExplicitLogonUserHeaderName = "X-OWA-ExplicitLogonUser"; + #endregion #region Fields @@ -45,6 +59,7 @@ public sealed class ExchangeService : ExchangeServiceBase private ExchangeService.RenderingMode renderingMode = RenderingMode.Xml; private bool traceEnablePrettyPrinting = true; private string targetServerVersion = null; + private string anchorMailbox = null; #endregion @@ -1445,6 +1460,152 @@ public ServiceResponseCollection MarkAsJunk(IEnumerable + /// This method is for search scenarios. Retrieves a set of personas satisfying the specified search conditions. + /// + /// Id of the folder being searched + /// The search filter. Available search filter classes + /// include SearchFilter.IsEqualTo, SearchFilter.ContainsSubstring and + /// SearchFilter.SearchFilterCollection + /// The view which defines the number of persona being returned + /// The query string for which the search is being performed + /// A collection of personas matching the search conditions + public ICollection FindPeople(FolderId folderId, SearchFilter searchFilter, ViewBase view, string queryString) + { + EwsUtilities.ValidateParamAllowNull(folderId, "folderId"); + EwsUtilities.ValidateParamAllowNull(searchFilter, "searchFilter"); + EwsUtilities.ValidateParam(view, "view"); + EwsUtilities.ValidateParam(queryString, "queryString"); + EwsUtilities.ValidateMethodVersion(this, ExchangeVersion.Exchange2013_SP1, "FindPeople"); + + FindPeopleRequest request = new FindPeopleRequest(this); + + request.FolderId = folderId; + request.SearchFilter = searchFilter; + request.View = view; + request.QueryString = queryString; + + return request.Execute().Personas; + } + + /// + /// This method is for search scenarios. Retrieves a set of personas satisfying the specified search conditions. + /// + /// Name of the folder being searched + /// The search filter. Available search filter classes + /// include SearchFilter.IsEqualTo, SearchFilter.ContainsSubstring and + /// SearchFilter.SearchFilterCollection + /// The view which defines the number of persona being returned + /// The query string for which the search is being performed + /// A collection of personas matching the search conditions + public ICollection FindPeople(WellKnownFolderName folderName, SearchFilter searchFilter, ViewBase view, string queryString) + { + return this.FindPeople(new FolderId(folderName), searchFilter, view, queryString); + } + + /// + /// This method is for browse scenarios. Retrieves a set of personas satisfying the specified browse conditions. + /// Browse scenariosdon't require query string. + /// + /// Id of the folder being browsed + /// Search filter + /// The view which defines paging and the number of persona being returned + /// A result object containing resultset for browsing + public FindPeopleResults FindPeople(FolderId folderId, SearchFilter searchFilter, ViewBase view) + { + EwsUtilities.ValidateParamAllowNull(folderId, "folderId"); + EwsUtilities.ValidateParamAllowNull(searchFilter, "searchFilter"); + EwsUtilities.ValidateParamAllowNull(view, "view"); + EwsUtilities.ValidateMethodVersion(this, ExchangeVersion.Exchange2013_SP1, "FindPeople"); + + FindPeopleRequest request = new FindPeopleRequest(this); + + request.FolderId = folderId; + request.SearchFilter = searchFilter; + request.View = view; + + return request.Execute().Results; + } + + /// + /// This method is for browse scenarios. Retrieves a set of personas satisfying the specified browse conditions. + /// Browse scenarios don't require query string. + /// + /// Name of the folder being browsed + /// Search filter + /// The view which defines paging and the number of persona being returned + /// A result object containing resultset for browsing + public FindPeopleResults FindPeople(WellKnownFolderName folderName, SearchFilter searchFilter, ViewBase view) + { + return this.FindPeople(new FolderId(folderName), searchFilter, view); + } + + /// + /// Get a user's photo. + /// + /// The user's email address + /// The desired size of the returned photo. Valid photo sizes are in UserPhotoSize + /// A photo's cache ID which will allow the caller to ensure their cached photo is up to date + /// A result object containing the photo state + public GetUserPhotoResults GetUserPhoto(string emailAddress, string userPhotoSize, string entityTag) + { + EwsUtilities.ValidateParam(emailAddress, "emailAddress"); + EwsUtilities.ValidateParam(userPhotoSize, "userPhotoSize"); + EwsUtilities.ValidateParamAllowNull(entityTag, "entityTag"); + + GetUserPhotoRequest request = new GetUserPhotoRequest(this); + + request.EmailAddress = emailAddress; + request.UserPhotoSize = userPhotoSize; + request.EntityTag = entityTag; + + return request.Execute().Results; + } + + /// + /// Begins an async request for a user photo + /// + /// An AsyncCallback delegate + /// An object that contains state information for this request + /// The user's email address + /// The desired size of the returned photo. Valid photo sizes are in UserPhotoSize + /// A photo's cache ID which will allow the caller to ensure their cached photo is up to date + /// An IAsyncResult that references the asynchronous request. + public IAsyncResult BeginGetUserPhoto( + AsyncCallback callback, + object state, + string emailAddress, + string userPhotoSize, + string entityTag) + { + EwsUtilities.ValidateParam(emailAddress, "emailAddress"); + EwsUtilities.ValidateParam(userPhotoSize, "userPhotoSize"); + EwsUtilities.ValidateParamAllowNull(entityTag, "entityTag"); + + GetUserPhotoRequest request = new GetUserPhotoRequest(this); + + request.EmailAddress = emailAddress; + request.UserPhotoSize = userPhotoSize; + request.EntityTag = entityTag; + + return request.BeginExecute(callback, state); + } + + /// + /// Ends an async request for a user's photo + /// + /// An IAsyncResult that references the asynchronous request. + /// A result object containing the photo state + public GetUserPhotoResults EndGetUserPhoto(IAsyncResult asyncResult) + { + GetUserPhotoRequest request = AsyncRequestResult.ExtractServiceRequest(this, asyncResult); + return request.EndExecute(asyncResult).Results; + } + + #endregion + #region Attachment operations /// @@ -4696,6 +4857,22 @@ public void DisableApp(string id, DisableReasonType disableReason) request.Execute(); } + /// + /// Sets the consent state of an extension. + /// + /// Extension id. + /// Sets the consent state of an extension. + /// Exception will be thrown for errors. + public void RegisterConsent(string id, ConsentState state) + { + EwsUtilities.ValidateParam(id, "id"); + EwsUtilities.ValidateParam(state, "state"); + + RegisterConsentRequest request = new RegisterConsentRequest(this, id, state); + + request.Execute(); + } + /// /// Get App Marketplace Url. /// @@ -4790,6 +4967,28 @@ public void SetEncryptionConfiguration(string imageBase64, string emailText, str request.Execute(); } + /// + /// Get the OME (i.e. Office Message Encryption) configuration data. This method is used in server-to-server calls to retrieve OME configuration + /// + /// OME Configuration response object + public GetOMEConfigurationResponse GetOMEConfiguration() + { + GetOMEConfigurationRequest request = new GetOMEConfigurationRequest(this); + + return request.Execute(); + } + + /// + /// Set the OME (i.e. Office Message Encryption) configuration data. This method is used in server-to-server calls to set encryption configuration + /// + /// The xml + public void SetOMEConfiguration(string xml) + { + SetOMEConfigurationRequest request = new SetOMEConfigurationRequest(this, xml); + + request.Execute(); + } + /// /// Set the client extension data. This method is used in server-to-server calls to install/uninstall/configure ORG /// extensions to support admin's management of ORG extensions via powershell/UMC. @@ -4804,6 +5003,79 @@ public void SetClientExtension(List actions) #endregion + #region Groups + /// + /// Gets the list of unified groups associated with the user + /// + /// The Requested Unified Groups Sets + /// The smtp address of accessing user. + /// UserUnified groups. + public Collection GetUserUnifiedGroups( + IEnumerable requestedUnifiedGroupsSets, + string userSmtpAddress) + { + EwsUtilities.ValidateParam(requestedUnifiedGroupsSets, "requestedUnifiedGroupsSets"); + EwsUtilities.ValidateParam(userSmtpAddress, "userSmtpAddress"); + + return this.GetUserUnifiedGroupsInternal(requestedUnifiedGroupsSets, userSmtpAddress); + } + + /// + /// Gets the list of unified groups associated with the user + /// + /// The Requested Unified Groups Sets + /// UserUnified groups. + public Collection GetUserUnifiedGroups(IEnumerable requestedUnifiedGroupsSets) + { + EwsUtilities.ValidateParam(requestedUnifiedGroupsSets, "requestedUnifiedGroupsSets"); + return this.GetUserUnifiedGroupsInternal(requestedUnifiedGroupsSets, null); + } + + /// + /// Gets the list of unified groups associated with the user + /// + /// The Requested Unified Groups Sets + /// The smtp address of accessing user. + /// UserUnified groups. + private Collection GetUserUnifiedGroupsInternal( + IEnumerable requestedUnifiedGroupsSets, + string userSmtpAddress) + { + GetUserUnifiedGroupsRequest request = new GetUserUnifiedGroupsRequest(this); + + if (!string.IsNullOrEmpty(userSmtpAddress)) + { + request.UserSmtpAddress = userSmtpAddress; + } + + if (requestedUnifiedGroupsSets != null) + { + request.RequestedUnifiedGroupsSets = requestedUnifiedGroupsSets; + } + + return request.Execute().GroupsSets; + } + + /// + /// Gets the UnifiedGroupsUnseenCount for the group specfied + /// + /// The smtpaddress of group for which unseendata is desired + /// The LastVisitedTimeUtc of group for which unseendata is desired + /// UnifiedGroupsUnseenCount + public int GetUnifiedGroupUnseenCount(string groupMailboxSmtpAddress, DateTime lastVisitedTimeUtc) + { + EwsUtilities.ValidateParam(groupMailboxSmtpAddress, "groupMailboxSmtpAddress"); + + // Set the AnchorMailbox value for this request so that the necessary headers are set to route the request to the group mailbox. + this.anchorMailbox = groupMailboxSmtpAddress; + + GetUnifiedGroupUnseenCountRequest request = new GetUnifiedGroupUnseenCountRequest(this, lastVisitedTimeUtc, UnifiedGroupIdentityType.SmtpAddress, groupMailboxSmtpAddress); + + return request.Execute().UnseenCount; + } + + #endregion + #region Diagnostic Method -- Only used by test /// @@ -5054,6 +5326,13 @@ internal IEwsHttpWebRequest PrepareHttpWebRequest(string methodName) request.Headers.Set(ExchangeService.TargetServerVersionHeaderName, this.TargetServerVersion); } + // If the anchorMailboxField is set, then add the necessary headers for it. + if (!string.IsNullOrEmpty(anchorMailbox)) + { + request.Headers.Set(ExchangeService.AnchorMailboxHeaderName, this.anchorMailbox); + request.Headers.Set(ExchangeService.ExplicitLogonUserHeaderName, this.anchorMailbox); + } + return request; } diff --git a/Core/PropertySet.cs b/Core/PropertySet.cs index 4c9abb98..519bdaf5 100644 --- a/Core/PropertySet.cs +++ b/Core/PropertySet.cs @@ -241,6 +241,8 @@ private static string GetShapeName(ServiceObjectType serviceObjectType) return XmlElementNames.FolderShape; case ServiceObjectType.Conversation: return XmlElementNames.ConversationShape; + case ServiceObjectType.Persona: + return XmlElementNames.PersonaShape; default: EwsUtilities.Assert( false, diff --git a/Core/Requests/FindPeopleRequest.cs b/Core/Requests/FindPeopleRequest.cs new file mode 100644 index 00000000..9da296df --- /dev/null +++ b/Core/Requests/FindPeopleRequest.cs @@ -0,0 +1,164 @@ +// --------------------------------------------------------------------------- +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// --------------------------------------------------------------------------- + +//----------------------------------------------------------------------- +// Defines the FindPeopleRequest class. +//----------------------------------------------------------------------- + +namespace Microsoft.Exchange.WebServices.Data +{ + /// + /// Represents a request of a find persona operation + /// + internal sealed class FindPeopleRequest : SimpleServiceRequestBase + { + /// + /// Default constructor + /// + /// Exchange web service + internal FindPeopleRequest(ExchangeService service) + : base(service) + { + } + + /// + /// Accessors of the view controlling the number of personas returned. + /// + internal ViewBase View { get; set; } + + /// + /// Folder Id accessors + /// + internal FolderId FolderId { get; set; } + + /// + /// Search filter accessors + /// Available search filter classes include SearchFilter.IsEqualTo, + /// SearchFilter.ContainsSubstring and SearchFilter.SearchFilterCollection. If SearchFilter + /// is null, no search filters are applied. + /// + internal SearchFilter SearchFilter { get; set; } + + /// + /// Query string accessors + /// + internal string QueryString { get; set; } + + /// + /// Validate request. + /// + internal override void Validate() + { + base.Validate(); + this.View.InternalValidate(this); + } + + /// + /// Writes XML attributes. + /// + /// The writer. + internal override void WriteAttributesToXml(EwsServiceXmlWriter writer) + { + base.WriteAttributesToXml(writer); + this.View.WriteAttributesToXml(writer); + } + + /// + /// Writes XML elements. + /// + /// The writer. + internal override void WriteElementsToXml(EwsServiceXmlWriter writer) + { + if (this.SearchFilter != null) + { + // Emit the Restriction element + writer.WriteStartElement(XmlNamespace.Messages, XmlElementNames.Restriction); + this.SearchFilter.WriteToXml(writer); + writer.WriteEndElement(); + } + + // Emit the View element + this.View.WriteToXml(writer, null); + + // Emit the SortOrder + this.View.WriteOrderByToXml(writer); + + // Emit the ParentFolderId element + if (this.FolderId != null) + { + writer.WriteStartElement(XmlNamespace.Messages, XmlElementNames.ParentFolderId); + this.FolderId.WriteToXml(writer); + writer.WriteEndElement(); + } + + if (!string.IsNullOrEmpty(this.QueryString)) + { + // Emit the QueryString element + writer.WriteStartElement(XmlNamespace.Messages, XmlElementNames.QueryString); + writer.WriteValue(this.QueryString, XmlElementNames.QueryString); + writer.WriteEndElement(); + } + + if (this.Service.RequestedServerVersion >= this.GetMinimumRequiredServerVersion()) + { + if (this.View.PropertySet != null) + { + this.View.PropertySet.WriteToXml(writer, ServiceObjectType.Persona); + } + } + } + + /// + /// Parses the response. + /// + /// The reader. + /// Response object. + internal override object ParseResponse(EwsServiceXmlReader reader) + { + FindPeopleResponse response = new FindPeopleResponse(); + response.LoadFromXml(reader, XmlElementNames.FindPeopleResponse); + return response; + } + + /// + /// Gets the name of the XML element. + /// + /// XML element name. + internal override string GetXmlElementName() + { + return XmlElementNames.FindPeople; + } + + /// + /// Gets the name of the response XML element. + /// + /// XML element name. + internal override string GetResponseXmlElementName() + { + return XmlElementNames.FindPeopleResponse; + } + + /// + /// Gets the request version. + /// + /// Earliest Exchange version in which this request is supported. + internal override ExchangeVersion GetMinimumRequiredServerVersion() + { + return ExchangeVersion.Exchange2013_SP1; + } + + /// + /// Executes this request. + /// + /// Service response. + internal FindPeopleResponse Execute() + { + FindPeopleResponse serviceResponse = (FindPeopleResponse)this.InternalExecute(); + serviceResponse.ThrowIfNecessary(); + return serviceResponse; + } + } +} \ No newline at end of file diff --git a/Core/Requests/GetOMEConfigurationRequest.cs b/Core/Requests/GetOMEConfigurationRequest.cs new file mode 100644 index 00000000..e5ad4ce3 --- /dev/null +++ b/Core/Requests/GetOMEConfigurationRequest.cs @@ -0,0 +1,86 @@ +// --------------------------------------------------------------------------- +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// --------------------------------------------------------------------------- + +//----------------------------------------------------------------------- +// Defines the GetOMEConfigurationRequest class. +//----------------------------------------------------------------------- + +namespace Microsoft.Exchange.WebServices.Data +{ + /// + /// Represents a GetOMEConfiguration request. + /// + internal sealed class GetOMEConfigurationRequest : SimpleServiceRequestBase + { + /// + /// Initializes a new instance of the class. + /// + /// The service. + internal GetOMEConfigurationRequest(ExchangeService service) + : base(service) + { + } + + /// + /// Gets the name of the XML element. + /// + /// XML element name, + internal override string GetXmlElementName() + { + return XmlElementNames.GetOMEConfigurationRequest; + } + + /// + /// Writes XML elements. + /// + /// The writer. + internal override void WriteElementsToXml(EwsServiceXmlWriter writer) + { + // Don't have parameters in request + } + + /// + /// Gets the name of the response XML element. + /// + /// XML element name, + internal override string GetResponseXmlElementName() + { + return XmlElementNames.GetOMEConfigurationResponse; + } + + /// + /// Parses the response. + /// + /// The reader. + /// Response object. + internal override object ParseResponse(EwsServiceXmlReader reader) + { + GetOMEConfigurationResponse response = new GetOMEConfigurationResponse(); + response.LoadFromXml(reader, XmlElementNames.GetOMEConfigurationResponse); + return response; + } + + /// + /// Gets the request version. + /// + /// Earliest Exchange version in which this request is supported. + internal override ExchangeVersion GetMinimumRequiredServerVersion() + { + return ExchangeVersion.Exchange2013; + } + + /// + /// Executes this request. + /// + /// Service response. + internal GetOMEConfigurationResponse Execute() + { + GetOMEConfigurationResponse serviceResponse = (GetOMEConfigurationResponse)this.InternalExecute(); + serviceResponse.ThrowIfNecessary(); + return serviceResponse; + } + } +} \ No newline at end of file diff --git a/Core/Requests/GetUserPhotoRequest.cs b/Core/Requests/GetUserPhotoRequest.cs new file mode 100644 index 00000000..395ffd3d --- /dev/null +++ b/Core/Requests/GetUserPhotoRequest.cs @@ -0,0 +1,209 @@ +// --------------------------------------------------------------------------- +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// --------------------------------------------------------------------------- + +//----------------------------------------------------------------------- +// Defines the GetUserPhotoRequest class. +//----------------------------------------------------------------------- + +namespace Microsoft.Exchange.WebServices.Data +{ + using System; + using System.Net; + using Microsoft.Exchange.WebServices.Data; + + /// + /// Represents a request of a get user photo operation + /// + internal sealed class GetUserPhotoRequest : SimpleServiceRequestBase + { + /// + /// Default constructor + /// + /// Exchange web service + internal GetUserPhotoRequest(ExchangeService service) + : base(service) + { + } + + /// + /// email address accessor + /// + internal string EmailAddress { get; set; } + + /// + /// user photo size accessor + /// + internal string UserPhotoSize { get; set; } + + /// + /// EntityTag accessor + /// + internal string EntityTag { get; set; } + + /// + /// Creates a NotFound instance of the result + /// + /// The canonical NotFound result + internal static GetUserPhotoResponse GetNotFoundResponse() + { + GetUserPhotoResponse serviceResponse = new GetUserPhotoResponse(); + serviceResponse.Results.Status = GetUserPhotoStatus.PhotoOrUserNotFound; + + return serviceResponse; + } + + /// + /// Validate request. + /// + internal override void Validate() + { + if (string.IsNullOrEmpty(this.EmailAddress)) + { + throw new ServiceLocalException(Strings.InvalidEmailAddress); + } + + if (string.IsNullOrEmpty(this.UserPhotoSize)) + { + throw new ServiceLocalException(Strings.UserPhotoSizeNotSpecified); + } + + base.Validate(); + } + + /// + /// Writes XML attributes. + /// + /// The writer. + internal override void WriteAttributesToXml(EwsServiceXmlWriter writer) + { + base.WriteAttributesToXml(writer); + } + + /// + /// Writes XML elements. + /// + /// The writer. + internal override void WriteElementsToXml(EwsServiceXmlWriter writer) + { + // Emit the EmailAddress element + writer.WriteStartElement(XmlNamespace.Messages, XmlElementNames.Email); + writer.WriteValue(this.EmailAddress, XmlElementNames.Email); + writer.WriteEndElement(); + + writer.WriteStartElement(XmlNamespace.Messages, XmlElementNames.SizeRequested); + writer.WriteValue(this.UserPhotoSize, XmlElementNames.SizeRequested); + writer.WriteEndElement(); + } + + /// + /// Adds header values to the request + /// + /// The collection of headers to add to + internal override void AddHeaders(WebHeaderCollection webHeaderCollection) + { + // Check if the ETag was specified + if (!string.IsNullOrEmpty(this.EntityTag)) + { + // Ensure the ETag is wrapped in quotes + string quotedETag = this.EntityTag; + if (!this.EntityTag.StartsWith("\"")) + { + quotedETag = "\"" + quotedETag; + } + if (!this.EntityTag.EndsWith("\"")) + { + quotedETag = quotedETag + "\""; + } + + webHeaderCollection[HttpRequestHeader.IfNoneMatch] = quotedETag; + } + } + + /// + /// Parses the response. + /// + /// The reader. + /// The HTTP response headers + /// Response object. + internal override object ParseResponse(EwsServiceXmlReader reader, WebHeaderCollection responseHeaders) + { + GetUserPhotoResponse response = new GetUserPhotoResponse(); + response.LoadFromXml(reader, XmlElementNames.GetUserPhotoResponse); + response.ReadHeader(responseHeaders); + return response; + } + + /// + /// Gets the name of the XML element. + /// + /// XML element name. + internal override string GetXmlElementName() + { + return XmlElementNames.GetUserPhoto; + } + + /// + /// Gets the name of the response XML element. + /// + /// XML element name. + internal override string GetResponseXmlElementName() + { + return XmlElementNames.GetUserPhotoResponse; + } + + /// + /// Gets the request version. + /// + /// Earliest Exchange version in which this request is supported. + internal override ExchangeVersion GetMinimumRequiredServerVersion() + { + return ExchangeVersion.Exchange2013; + } + + /// + /// Executes this request. + /// + /// Service response. + internal GetUserPhotoResponse Execute() + { + return GetUserPhotoRequest.GetResultOrDefault(this.InternalExecute); + } + + /// + /// Ends executing this async request. + /// + /// The async result + /// Service response collection. + internal GetUserPhotoResponse EndExecute(IAsyncResult asyncResult) + { + return GetUserPhotoRequest.GetResultOrDefault(() => this.EndInternalExecute(asyncResult)); + } + + private static GetUserPhotoResponse GetResultOrDefault(Func serviceResponseFactory) + { + try + { + return (GetUserPhotoResponse)serviceResponseFactory(); + } + catch (ServiceRequestException ex) + { + // 404 is a valid return code in the case of GetUserPhoto when the photo is + // not found, so it is necessary to catch this exception here. + WebException webException = ex.InnerException as WebException; + if (webException != null) + { + HttpWebResponse errorResponse = webException.Response as HttpWebResponse; + if (errorResponse != null && errorResponse.StatusCode == HttpStatusCode.NotFound) + { + return GetUserPhotoRequest.GetNotFoundResponse(); + } + } + + throw; + } + } + } +} \ No newline at end of file diff --git a/Core/Requests/HangingServiceRequestBase.cs b/Core/Requests/HangingServiceRequestBase.cs index c68c00da..8c3b9083 100644 --- a/Core/Requests/HangingServiceRequestBase.cs +++ b/Core/Requests/HangingServiceRequestBase.cs @@ -194,7 +194,7 @@ private void ParseResponses(object state) { try { - responseObject = this.ReadResponse(ewsXmlReader); + responseObject = this.ReadResponse(ewsXmlReader, this.response.Headers); } finally { @@ -208,7 +208,7 @@ private void ParseResponses(object state) } else { - responseObject = this.ReadResponse(ewsXmlReader); + responseObject = this.ReadResponse(ewsXmlReader, this.response.Headers); } this.responseHandler(responseObject); diff --git a/Core/Requests/RegisterConsentRequest.cs b/Core/Requests/RegisterConsentRequest.cs new file mode 100644 index 00000000..c1ba900f --- /dev/null +++ b/Core/Requests/RegisterConsentRequest.cs @@ -0,0 +1,112 @@ +// --------------------------------------------------------------------------- +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// --------------------------------------------------------------------------- + +namespace Microsoft.Exchange.WebServices.Data +{ + using System; + using System.Collections.Generic; + using System.IO; + using System.Text; + + using Microsoft.Exchange.WebServices.Data.Enumerations; + + /// + /// Represents a RegisterConsent request. + /// + internal sealed class RegisterConsentRequest : SimpleServiceRequestBase + { + /// + /// Initializes a new instance of the class. + /// + /// The service. + /// Extension id. + /// Sets the consent state of an extension. + internal RegisterConsentRequest(ExchangeService service, string id, ConsentState state) + : base(service) + { + this.Id = id; + this.ConsentState = state; + } + + /// + /// Extension id + /// + private string Id + { + get; + set; + } + + /// + /// User decision on the consent state of an extension + /// + private ConsentState ConsentState + { + get; + set; + } + + /// + /// Gets the name of the XML element. + /// + /// XML element name. + internal override string GetXmlElementName() + { + return XmlElementNames.DisableAppRequest; + } + + /// + /// Writes XML elements. + /// + /// The writer. + internal override void WriteElementsToXml(EwsServiceXmlWriter writer) + { + writer.WriteElementValue(XmlNamespace.Messages, XmlElementNames.ID, this.Id); + writer.WriteElementValue(XmlNamespace.Messages, XmlElementNames.AcceptanceState, this.ConsentState); + } + + /// + /// Gets the name of the response XML element. + /// + /// XML element name. + internal override string GetResponseXmlElementName() + { + return XmlElementNames.RegisterConsentResponse; + } + + /// + /// Parses the response. + /// + /// The reader. + /// Response object. + internal override object ParseResponse(EwsServiceXmlReader reader) + { + RegisterConsentResponse response = new RegisterConsentResponse(); + response.LoadFromXml(reader, XmlElementNames.RegisterConsentResponse); + return response; + } + + /// + /// Gets the request version. + /// + /// Earliest Exchange version in which this request is supported. + internal override ExchangeVersion GetMinimumRequiredServerVersion() + { + return ExchangeVersion.Exchange2013_SP1; + } + + /// + /// Executes this request. + /// + /// Service response. + internal RegisterConsentResponse Execute() + { + RegisterConsentResponse serviceResponse = (RegisterConsentResponse)this.InternalExecute(); + serviceResponse.ThrowIfNecessary(); + return serviceResponse; + } + } +} \ No newline at end of file diff --git a/Core/Requests/ServiceRequestBase.cs b/Core/Requests/ServiceRequestBase.cs index c895f896..16c236a4 100644 --- a/Core/Requests/ServiceRequestBase.cs +++ b/Core/Requests/ServiceRequestBase.cs @@ -113,7 +113,22 @@ private static Stream WrapStream(Stream responseStream, string contentEncoding) /// /// The reader. /// Response object. - internal abstract object ParseResponse(EwsServiceXmlReader reader); + internal virtual object ParseResponse(EwsServiceXmlReader reader) + { + throw new NotImplementedException("you must override either this or the 2-parameter version"); + } + + /// + /// Parses the response. + /// + /// The reader. + /// Response headers + /// Response object. + /// If this is overriden instead of the 1-parameter version, you can read response headers + internal virtual object ParseResponse(EwsServiceXmlReader reader, WebHeaderCollection responseHeaders) + { + return this.ParseResponse(reader); + } /// /// Parses the response. @@ -171,12 +186,25 @@ internal virtual void WriteAttributesToXml(EwsServiceXmlWriter writer) { } + /// + /// Allows the subclasses to add their own header information + /// + /// The HTTP request headers + internal virtual void AddHeaders(WebHeaderCollection webHeaderCollection) + { + } + /// /// Initializes a new instance of the class. /// /// The service. internal ServiceRequestBase(ExchangeService service) { + if (service == null) + { + throw new ArgumentNullException("service"); + } + this.service = service; this.ThrowIfNotSupportedByRequestedServerVersion(); } @@ -498,8 +526,9 @@ private Stream GetWebRequestStream(IEwsHttpWebRequest request) /// Reads the response. /// /// The XML reader. + /// HTTP response headers /// Service response. - protected object ReadResponse(EwsServiceXmlReader ewsXmlReader) + protected object ReadResponse(EwsServiceXmlReader ewsXmlReader, WebHeaderCollection responseHeaders) { object serviceResponse; @@ -510,7 +539,14 @@ protected object ReadResponse(EwsServiceXmlReader ewsXmlReader) ewsXmlReader.ReadStartElement(XmlNamespace.Messages, this.GetResponseXmlElementName()); - serviceResponse = this.ParseResponse(ewsXmlReader); + if (responseHeaders != null) + { + serviceResponse = this.ParseResponse(ewsXmlReader, responseHeaders); + } + else + { + serviceResponse = this.ParseResponse(ewsXmlReader); + } ewsXmlReader.ReadEndElementIfNecessary(XmlNamespace.Messages, this.GetResponseXmlElementName()); @@ -778,6 +814,9 @@ protected IEwsHttpWebRequest BuildEwsHttpWebRequest() bool needSignature = this.Service.Credentials != null && this.Service.Credentials.NeedSignature; bool needTrace = this.Service.IsTraceEnabledFor(TraceFlags.EwsRequest); + // The request might need to add additional headers + this.AddHeaders(request.Headers); + // If tracing is enabled, we generate the request in-memory so that we // can pass it along to the ITraceListener. Then we copy the stream to // the request stream. diff --git a/Core/Requests/SetEncryptionConfigurationRequest.cs b/Core/Requests/SetEncryptionConfigurationRequest.cs index 48b547fa..3507805e 100644 --- a/Core/Requests/SetEncryptionConfigurationRequest.cs +++ b/Core/Requests/SetEncryptionConfigurationRequest.cs @@ -124,9 +124,7 @@ internal override void WriteElementsToXml(EwsServiceXmlWriter writer) writer.WriteElementValue(XmlNamespace.Messages, XmlElementNames.EncryptionConfigurationEmailText, this.EmailText); writer.WriteElementValue(XmlNamespace.Messages, XmlElementNames.EncryptionConfigurationPortalText, this.PortalText); writer.WriteElementValue(XmlNamespace.Messages, XmlElementNames.EncryptionConfigurationDisclaimerText, this.disclaimerText); - - // TODO: Uncomment after server schema change have been deployed to all machines - // writer.WriteElementValue(XmlNamespace.Messages, XmlElementNames.EncryptionConfigurationOTPEnabled, this.otpEnabled); + writer.WriteElementValue(XmlNamespace.Messages, XmlElementNames.EncryptionConfigurationOTPEnabled, this.otpEnabled); } /// diff --git a/Core/Requests/SetOMEConfigurationRequest.cs b/Core/Requests/SetOMEConfigurationRequest.cs new file mode 100644 index 00000000..66a0f89a --- /dev/null +++ b/Core/Requests/SetOMEConfigurationRequest.cs @@ -0,0 +1,100 @@ +// --------------------------------------------------------------------------- +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// --------------------------------------------------------------------------- + +//----------------------------------------------------------------------- +// Defines the SetOMEConfigurationRequest class. +//----------------------------------------------------------------------- + +namespace Microsoft.Exchange.WebServices.Data +{ + /// + /// Represents a SetOMEConfiguration request. + /// + internal sealed class SetOMEConfigurationRequest : SimpleServiceRequestBase + { + /// + /// The XML representation of EncryptionConfigurationData + /// + private readonly string xml; + + /// + /// The XML representation of EncryptionConfigurationData + /// + public string Xml + { + get { return this.xml; } + } + + /// + /// Initializes a new instance of the class. + /// + /// The service. + /// The XML representation of EncryptionConfigurationData + internal SetOMEConfigurationRequest(ExchangeService service, string xml) : base(service) + { + this.xml = xml; + } + + /// + /// Gets the name of the XML element. + /// + /// XML element name, + internal override string GetXmlElementName() + { + return XmlElementNames.SetOMEConfigurationRequest; + } + + /// + /// Writes XML elements. + /// + /// The writer. + internal override void WriteElementsToXml(EwsServiceXmlWriter writer) + { + writer.WriteElementValue(XmlNamespace.Messages, XmlElementNames.OMEConfigurationXml, this.Xml); + } + + /// + /// Gets the name of the response XML element. + /// + /// XML element name, + internal override string GetResponseXmlElementName() + { + return XmlElementNames.SetOMEConfigurationResponse; + } + + /// + /// Parses the response. + /// + /// The reader. + /// Response object. + internal override object ParseResponse(EwsServiceXmlReader reader) + { + SetOMEConfigurationResponse response = new SetOMEConfigurationResponse(); + response.LoadFromXml(reader, GetResponseXmlElementName()); + return response; + } + + /// + /// Gets the request version. + /// + /// Earliest Exchange version in which this request is supported. + internal override ExchangeVersion GetMinimumRequiredServerVersion() + { + return ExchangeVersion.Exchange2013; + } + + /// + /// Executes this request. + /// + /// Service response. + internal ServiceResponse Execute() + { + SetOMEConfigurationResponse serviceResponse = (SetOMEConfigurationResponse)this.InternalExecute(); + serviceResponse.ThrowIfNecessary(); + return serviceResponse; + } + } +} \ No newline at end of file diff --git a/Core/Requests/SimpleServiceRequestBase.cs b/Core/Requests/SimpleServiceRequestBase.cs index 011f164e..8a7af0de 100644 --- a/Core/Requests/SimpleServiceRequestBase.cs +++ b/Core/Requests/SimpleServiceRequestBase.cs @@ -128,7 +128,7 @@ private object ReadResponse(IEwsHttpWebResponse response) { this.TraceResponseXml(response, memoryStream); - serviceResponse = this.ReadResponseXml(memoryStream); + serviceResponse = this.ReadResponseXml(memoryStream, response.Headers); } else if (this.Service.RenderingMethod == ExchangeService.RenderingMode.JSON) { @@ -148,7 +148,7 @@ private object ReadResponse(IEwsHttpWebResponse response) { if (this.Service.RenderingMethod == ExchangeService.RenderingMode.Xml) { - serviceResponse = this.ReadResponseXml(responseStream); + serviceResponse = this.ReadResponseXml(responseStream, response.Headers); } else if (this.Service.RenderingMethod == ExchangeService.RenderingMode.JSON) { @@ -204,10 +204,21 @@ private object ReadResponseJson(Stream responseStream) /// The response stream. /// private object ReadResponseXml(Stream responseStream) + { + return this.ReadResponseXml(responseStream, null); + } + + /// + /// Reads the response XML. + /// + /// The response stream. + /// The HTTP response headers + /// + private object ReadResponseXml(Stream responseStream, WebHeaderCollection responseHeaders) { object serviceResponse; EwsServiceXmlReader ewsXmlReader = new EwsServiceXmlReader(responseStream, this.Service); - serviceResponse = this.ReadResponse(ewsXmlReader); + serviceResponse = this.ReadResponse(ewsXmlReader, responseHeaders); return serviceResponse; } } diff --git a/Core/Responses/FindPeopleResponse.cs b/Core/Responses/FindPeopleResponse.cs new file mode 100644 index 00000000..29a2fbc8 --- /dev/null +++ b/Core/Responses/FindPeopleResponse.cs @@ -0,0 +1,108 @@ +// --------------------------------------------------------------------------- +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// --------------------------------------------------------------------------- + +//----------------------------------------------------------------------- +// Defines the FindPeopleResponse class. +//----------------------------------------------------------------------- + +namespace Microsoft.Exchange.WebServices.Data +{ + using System.Collections.Generic; + using System.Xml; + + /// + /// Represents the response to a Persona search operation. + /// + internal sealed class FindPeopleResponse : ServiceResponse + { + /// + /// Initializes a new instance of the class. + /// + internal FindPeopleResponse() + : base() + { + this.Results = new FindPeopleResults(); + } + + /// + /// Gets the collection of Personas in results. + /// + internal ICollection Personas + { + get + { + return this.Results.Personas; + } + } + + /// + /// Gets FindPersona results. + /// + /// FindPersona results. + internal FindPeopleResults Results { get; private set; } + + /// + /// Read Personas from XML. + /// + /// The reader. + internal override void ReadElementsFromXml(EwsServiceXmlReader reader) + { + EwsUtilities.Assert( + this.Results.Personas != null, + "FindPeopleResponse.ReadElementsFromXml", + "Personas is null."); + + reader.ReadStartElement(XmlNamespace.Messages, XmlElementNames.People); + if (!reader.IsEmptyElement) + { + do + { + reader.Read(); + + if (reader.NodeType == XmlNodeType.Element) + { + Persona item = EwsUtilities.CreateEwsObjectFromXmlElementName(reader.Service, reader.LocalName); + + if (item == null) + { + reader.SkipCurrentElement(); + } + else + { + // Don't clear propertyBag because all properties have been initialized in the persona constructor. + item.LoadFromXml(reader, false, null, false); + this.Results.Personas.Add(item); + } + } + } + while (!reader.IsEndElement(XmlNamespace.Messages, XmlElementNames.People)); + } + + reader.Read(); + + if (reader.IsStartElement(XmlNamespace.Messages, XmlElementNames.TotalNumberOfPeopleInView) && !reader.IsEmptyElement) + { + this.Results.TotalCount = reader.ReadElementValue(); + + reader.Read(); + } + + if (reader.IsStartElement(XmlNamespace.Messages, XmlElementNames.FirstMatchingRowIndex) && !reader.IsEmptyElement) + { + this.Results.FirstMatchingRowIndex = reader.ReadElementValue(); + + reader.Read(); + } + + if (reader.IsStartElement(XmlNamespace.Messages, XmlElementNames.FirstLoadedRowIndex) && !reader.IsEmptyElement) + { + this.Results.FirstLoadedRowIndex = reader.ReadElementValue(); + + reader.Read(); + } + } + } +} diff --git a/Core/Responses/GetEncryptionConfigurationResponse.cs b/Core/Responses/GetEncryptionConfigurationResponse.cs index 7fce38c4..f2132957 100644 --- a/Core/Responses/GetEncryptionConfigurationResponse.cs +++ b/Core/Responses/GetEncryptionConfigurationResponse.cs @@ -100,16 +100,7 @@ internal override void ReadElementsFromXml(EwsServiceXmlReader reader) this.emailText = reader.ReadElementValue(XmlNamespace.Messages, XmlElementNames.EncryptionConfigurationEmailText); this.portalText = reader.ReadElementValue(XmlNamespace.Messages, XmlElementNames.EncryptionConfigurationPortalText); this.disclaimerText = reader.ReadElementValue(XmlNamespace.Messages, XmlElementNames.EncryptionConfigurationDisclaimerText); - - // TODO: Remove the try/catch after both client & server have been deployed to all machines - try - { - this.otpEnabled = reader.ReadElementValue(XmlNamespace.Messages, XmlElementNames.EncryptionConfigurationOTPEnabled); - } - catch (ServiceXmlDeserializationException) - { - this.otpEnabled = true; - } + this.otpEnabled = reader.ReadElementValue(XmlNamespace.Messages, XmlElementNames.EncryptionConfigurationOTPEnabled); } } } diff --git a/Core/Responses/GetOMEConfigurationResponse.cs b/Core/Responses/GetOMEConfigurationResponse.cs new file mode 100644 index 00000000..da990c89 --- /dev/null +++ b/Core/Responses/GetOMEConfigurationResponse.cs @@ -0,0 +1,50 @@ +// --------------------------------------------------------------------------- +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// --------------------------------------------------------------------------- + +//----------------------------------------------------------------------- +// Defines the GetOMEConfigurationResponse class. +//----------------------------------------------------------------------- + +namespace Microsoft.Exchange.WebServices.Data +{ + /// + /// Represents the response to a GetOMEConfiguration operation. + /// + public sealed class GetOMEConfigurationResponse : ServiceResponse + { + /// + /// The XML representation of EncryptionConfigurationData + /// + private string xml; + + /// + /// Initializes a new instance of the class. + /// + internal GetOMEConfigurationResponse() + : base() + { + } + + /// + /// The XML representation of EncryptionConfigurationData + /// + public string Xml + { + get { return this.xml; } + } + + /// + /// Reads response elements from XML. + /// + /// The reader. + internal override void ReadElementsFromXml(EwsServiceXmlReader reader) + { + base.ReadElementsFromXml(reader); + + this.xml = reader.ReadElementValue(XmlNamespace.Messages, XmlElementNames.OMEConfigurationXml); + } + } +} diff --git a/Core/Responses/GetServerTimeZonesResponse.cs b/Core/Responses/GetServerTimeZonesResponse.cs index d7d1053a..a5715704 100644 --- a/Core/Responses/GetServerTimeZonesResponse.cs +++ b/Core/Responses/GetServerTimeZonesResponse.cs @@ -49,7 +49,7 @@ internal override void ReadElementsFromXml(EwsServiceXmlReader reader) TimeZoneDefinition timeZoneDefinition = new TimeZoneDefinition(); timeZoneDefinition.LoadFromXml(reader); - this.timeZones.Add(timeZoneDefinition.ToTimeZoneInfo()); + this.timeZones.Add(timeZoneDefinition.ToTimeZoneInfo(reader.Service)); } } while (!reader.IsEndElement(XmlNamespace.Messages, XmlElementNames.TimeZoneDefinitions)); diff --git a/Core/Responses/GetUserPhotoResponse.cs b/Core/Responses/GetUserPhotoResponse.cs new file mode 100644 index 00000000..df358310 --- /dev/null +++ b/Core/Responses/GetUserPhotoResponse.cs @@ -0,0 +1,100 @@ +// --------------------------------------------------------------------------- +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// --------------------------------------------------------------------------- + +//----------------------------------------------------------------------- +// Defines the GetUserPhotoResponse class. +//----------------------------------------------------------------------- + +namespace Microsoft.Exchange.WebServices.Data +{ + using System; + using System.Collections.Generic; + using System.Globalization; + using System.IO; + using System.Net; + using System.Xml; + + /// + /// Represents the response to GetUserPhoto operation. + /// + internal sealed class GetUserPhotoResponse : ServiceResponse + { + /// + /// Initializes a new instance of the class. + /// + internal GetUserPhotoResponse() + { + this.Results = new GetUserPhotoResults(); + } + + /// + /// Gets GetUserPhoto results. + /// + /// GetUserPhoto results. + internal GetUserPhotoResults Results { get; private set; } + + /// + /// Read Photo results from XML. + /// + /// The reader. + internal override void ReadElementsFromXml(EwsServiceXmlReader reader) + { + bool hasChanged = reader.ReadElementValue(XmlNamespace.Messages, XmlElementNames.HasChanged); + + reader.ReadStartElement(XmlNamespace.Messages, XmlElementNames.PictureData); + byte[] photoData = reader.ReadBase64ElementValue(); + + // We only get a content type if we get a photo + if (photoData.Length > 0) + { + this.Results.Photo = photoData; + this.Results.ContentType = reader.ReadElementValue(XmlNamespace.Messages, XmlElementNames.ContentType); + } + + if (hasChanged) + { + if (this.Results.Photo.Length == 0) + { + this.Results.Status = GetUserPhotoStatus.PhotoOrUserNotFound; + } + else + { + this.Results.Status = GetUserPhotoStatus.PhotoReturned; + } + } + else + { + this.Results.Status = GetUserPhotoStatus.PhotoUnchanged; + } + } + + /// + /// Read Photo response headers + /// + /// The response header. + internal override void ReadHeader(WebHeaderCollection responseHeaders) + { + // Parse out the ETag, trimming the quotes + string etag = responseHeaders[HttpResponseHeader.ETag]; + if (etag != null) + { + etag = etag.Replace("\"", ""); + + if (etag.Length > 0) + { + this.Results.EntityTag = etag; + } + } + + // Parse the Expires tag, leaving it in UTC + string expires = responseHeaders[HttpResponseHeader.Expires]; + if (expires != null && expires.Length > 0) + { + this.Results.Expires = DateTime.Parse(expires, null, DateTimeStyles.RoundtripKind); + } + } + } +} \ No newline at end of file diff --git a/Core/Responses/RegisterConsentResponse.cs b/Core/Responses/RegisterConsentResponse.cs new file mode 100644 index 00000000..dc54bbe3 --- /dev/null +++ b/Core/Responses/RegisterConsentResponse.cs @@ -0,0 +1,28 @@ +// --------------------------------------------------------------------------- +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// --------------------------------------------------------------------------- + +namespace Microsoft.Exchange.WebServices.Data +{ + using System.Collections.ObjectModel; + using System.IO; + using System.Xml; + + /// + /// Represents the response to a RegisterResponse operation. + /// Today this class doesn't add extra functionality. Keep this class here so in the future + /// we can return extension info upon installation complete. + /// + internal sealed class RegisterConsentResponse : ServiceResponse + { + /// + /// Initializes a new instance of the class. + /// + public RegisterConsentResponse() + : base() + { + } + } +} diff --git a/Core/Responses/ServiceResponse.cs b/Core/Responses/ServiceResponse.cs index 82a60937..22168fe6 100644 --- a/Core/Responses/ServiceResponse.cs +++ b/Core/Responses/ServiceResponse.cs @@ -14,6 +14,7 @@ namespace Microsoft.Exchange.WebServices.Data using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; + using System.Net; /// /// Represents the standard response to an Exchange Web Services operation. @@ -228,6 +229,14 @@ internal virtual void ReadElementsFromXml(EwsServiceXmlReader reader) { } + /// + /// Reads the headers from a HTTP response + /// + /// a collection of response headers + internal virtual void ReadHeader(WebHeaderCollection responseHeaders) + { + } + /// /// Reads response elements from Json. /// diff --git a/Core/Responses/SetOMEConfigurationResponse.cs b/Core/Responses/SetOMEConfigurationResponse.cs new file mode 100644 index 00000000..83c8065b --- /dev/null +++ b/Core/Responses/SetOMEConfigurationResponse.cs @@ -0,0 +1,26 @@ +// --------------------------------------------------------------------------- +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// --------------------------------------------------------------------------- + +//----------------------------------------------------------------------- +// Defines the SetOMEConfigurationResponse class. +//----------------------------------------------------------------------- + +namespace Microsoft.Exchange.WebServices.Data +{ + /// + /// Represents the response to a SetOMEConfigurationResponse operation. + /// + internal sealed class SetOMEConfigurationResponse : ServiceResponse + { + /// + /// Initializes a new instance of the class. + /// + public SetOMEConfigurationResponse() + : base() + { + } + } +} \ No newline at end of file diff --git a/Core/ServiceObjects/Items/Persona.cs b/Core/ServiceObjects/Items/Persona.cs new file mode 100644 index 00000000..08131c7b --- /dev/null +++ b/Core/ServiceObjects/Items/Persona.cs @@ -0,0 +1,367 @@ +// --------------------------------------------------------------------------- +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// --------------------------------------------------------------------------- + +//----------------------------------------------------------------------- +// Defines the Persona class. +//----------------------------------------------------------------------- + +namespace Microsoft.Exchange.WebServices.Data +{ + using System; + + /// + /// Represents a Persona. Properties available on Personas are defined in the PersonaSchema class. + /// + [Attachable] + [ServiceObjectDefinition(XmlElementNames.Persona)] + public class Persona : Item + { + /// + /// Initializes an unsaved local instance of . To bind to an existing Persona, use Persona.Bind() instead. + /// + /// The ExchangeService object to which the Persona will be bound. + public Persona(ExchangeService service) + : base(service) + { + this.PersonaType = string.Empty; + this.CreationTime = null; + this.DisplayNameFirstLastHeader = string.Empty; + this.DisplayNameLastFirstHeader = string.Empty; + this.DisplayName = string.Empty; + this.DisplayNameFirstLast = string.Empty; + this.DisplayNameLastFirst = string.Empty; + this.FileAs = string.Empty; + this.Generation = string.Empty; + this.DisplayNamePrefix = string.Empty; + this.GivenName = string.Empty; + this.Surname = string.Empty; + this.Title = string.Empty; + this.CompanyName = string.Empty; + this.ImAddress = string.Empty; + this.HomeCity = string.Empty; + this.WorkCity = string.Empty; + this.Alias = string.Empty; + this.RelevanceScore = 0; + + // Remaining properties are initialized when the property definition is created in + // PersonaSchema.cs. + } + + /// + /// Binds to an existing Persona and loads the specified set of properties. + /// Calling this method results in a call to EWS. + /// + /// The service to use to bind to the Persona. + /// The Id of the Persona to bind to. + /// The set of properties to load. + /// A Persona instance representing the Persona corresponding to the specified Id. + public static new Persona Bind( + ExchangeService service, + ItemId id, + PropertySet propertySet) + { + return service.BindToItem(id, propertySet); + } + + /// + /// Binds to an existing Persona and loads its first class properties. + /// Calling this method results in a call to EWS. + /// + /// The service to use to bind to the Persona. + /// The Id of the Persona to bind to. + /// A Persona instance representing the Persona corresponding to the specified Id. + public static new Persona Bind(ExchangeService service, ItemId id) + { + return Persona.Bind( + service, + id, + PropertySet.FirstClassProperties); + } + + /// + /// Internal method to return the schema associated with this type of object. + /// + /// The schema associated with this type of object. + internal override ServiceObjectSchema GetSchema() + { + return PersonaSchema.Instance; + } + + /// + /// Gets the minimum required server version. + /// + /// Earliest Exchange version in which this service object type is supported. + internal override ExchangeVersion GetMinimumRequiredServerVersion() + { + return ExchangeVersion.Exchange2013_SP1; + } + + /// + /// The property definition for the Id of this object. + /// + /// A PropertyDefinition instance. + internal override PropertyDefinition GetIdPropertyDefinition() + { + return PersonaSchema.PersonaId; + } + + /// + /// Validates this instance. + /// + internal override void Validate() + { + base.Validate(); + } + + #region Properties + + /// + /// Gets the persona id + /// + public ItemId PersonaId + { + get { return (ItemId)this.PropertyBag[this.GetIdPropertyDefinition()]; } + set { this.PropertyBag[this.GetIdPropertyDefinition()] = value; } + } + + /// + /// Gets the persona type + /// + public string PersonaType + { + get { return (string)this.PropertyBag[PersonaSchema.PersonaType]; } + set { this.PropertyBag[PersonaSchema.PersonaType] = value; } + } + + /// + /// Gets the creation time of the underlying contact + /// + public DateTime? CreationTime + { + get { return (DateTime?)this.PropertyBag[PersonaSchema.CreationTime]; } + set { this.PropertyBag[PersonaSchema.CreationTime] = value; } + } + + /// + /// Gets the header of the FirstLast display name + /// + public string DisplayNameFirstLastHeader + { + get { return (string)this.PropertyBag[PersonaSchema.DisplayNameFirstLastHeader]; } + set { this.PropertyBag[PersonaSchema.DisplayNameFirstLastHeader] = value; } + } + + /// + /// Gets the header of the LastFirst display name + /// + public string DisplayNameLastFirstHeader + { + get { return (string)this.PropertyBag[PersonaSchema.DisplayNameLastFirstHeader]; } + set { this.PropertyBag[PersonaSchema.DisplayNameLastFirstHeader] = value; } + } + + /// + /// Gets the display name + /// + public string DisplayName + { + get { return (string)this.PropertyBag[PersonaSchema.DisplayName]; } + set { this.PropertyBag[PersonaSchema.DisplayName] = value; } + } + + /// + /// Gets the display name in first last order + /// + public string DisplayNameFirstLast + { + get { return (string)this.PropertyBag[PersonaSchema.DisplayNameFirstLast]; } + set { this.PropertyBag[PersonaSchema.DisplayNameFirstLast] = value; } + } + + /// + /// Gets the display name in last first order + /// + public string DisplayNameLastFirst + { + get { return (string)this.PropertyBag[PersonaSchema.DisplayNameLastFirst]; } + set { this.PropertyBag[PersonaSchema.DisplayNameLastFirst] = value; } + } + + /// + /// Gets the name under which this Persona is filed as. FileAs can be manually set or + /// can be automatically calculated based on the value of the FileAsMapping property. + /// + public string FileAs + { + get { return (string)this.PropertyBag[PersonaSchema.FileAs]; } + set { this.PropertyBag[PersonaSchema.FileAs] = value; } + } + + /// + /// Gets the generation of the Persona + /// + public string Generation + { + get { return (string)this.PropertyBag[PersonaSchema.Generation]; } + set { this.PropertyBag[PersonaSchema.Generation] = value; } + } + + /// + /// Gets the DisplayNamePrefix of the Persona + /// + public string DisplayNamePrefix + { + get { return (string)this.PropertyBag[PersonaSchema.DisplayNamePrefix]; } + set { this.PropertyBag[PersonaSchema.DisplayNamePrefix] = value; } + } + + /// + /// Gets the given name of the Persona + /// + public string GivenName + { + get { return (string)this.PropertyBag[PersonaSchema.GivenName]; } + set { this.PropertyBag[PersonaSchema.GivenName] = value; } + } + + /// + /// Gets the surname of the Persona + /// + public string Surname + { + get { return (string)this.PropertyBag[PersonaSchema.Surname]; } + set { this.PropertyBag[PersonaSchema.Surname] = value; } + } + + /// + /// Gets the Persona's title + /// + public string Title + { + get { return (string)this.PropertyBag[PersonaSchema.Title]; } + set { this.PropertyBag[PersonaSchema.Title] = value; } + } + + /// + /// Gets the company name of the Persona + /// + public string CompanyName + { + get { return (string)this.PropertyBag[PersonaSchema.CompanyName]; } + set { this.PropertyBag[PersonaSchema.CompanyName] = value; } + } + + /// + /// Gets the email of the persona + /// + public PersonaEmailAddress EmailAddress + { + get { return (PersonaEmailAddress)this.PropertyBag[PersonaSchema.EmailAddress]; } + set { this.PropertyBag[PersonaSchema.EmailAddress] = value; } + } + + /// + /// Gets the list of e-mail addresses of the contact + /// + public PersonaEmailAddressCollection EmailAddresses + { + get { return (PersonaEmailAddressCollection)this.PropertyBag[PersonaSchema.EmailAddresses]; } + set { this.PropertyBag[PersonaSchema.EmailAddresses] = value; } + } + + /// + /// Gets the IM address of the persona + /// + public string ImAddress + { + get { return (string)this.PropertyBag[PersonaSchema.ImAddress]; } + set { this.PropertyBag[PersonaSchema.ImAddress] = value; } + } + + /// + /// Gets the city of the Persona's home + /// + public string HomeCity + { + get { return (string)this.PropertyBag[PersonaSchema.HomeCity]; } + set { this.PropertyBag[PersonaSchema.HomeCity] = value; } + } + + /// + /// Gets the city of the Persona's work place + /// + public string WorkCity + { + get { return (string)this.PropertyBag[PersonaSchema.WorkCity]; } + set { this.PropertyBag[PersonaSchema.WorkCity] = value; } + } + + /// + /// Gets the alias of the Persona + /// + public string Alias + { + get { return (string)this.PropertyBag[PersonaSchema.Alias]; } + set { this.PropertyBag[PersonaSchema.Alias] = value; } + } + + /// + /// Gets the relevance score + /// + public int RelevanceScore + { + get { return (int)this.PropertyBag[PersonaSchema.RelevanceScore]; } + set { this.PropertyBag[PersonaSchema.RelevanceScore] = value; } + } + + /// + /// Gets the list of attributions + /// + public AttributionCollection Attributions + { + get { return (AttributionCollection)this.PropertyBag[PersonaSchema.Attributions]; } + set { this.PropertyBag[PersonaSchema.Attributions] = value; } + } + + /// + /// Gets the list of office locations + /// + public AttributedStringCollection OfficeLocations + { + get { return (AttributedStringCollection)this.PropertyBag[PersonaSchema.OfficeLocations]; } + set { this.PropertyBag[PersonaSchema.OfficeLocations] = value; } + } + + /// + /// Gets the list of IM addresses of the persona + /// + public AttributedStringCollection ImAddresses + { + get { return (AttributedStringCollection)this.PropertyBag[PersonaSchema.ImAddresses]; } + set { this.PropertyBag[PersonaSchema.ImAddresses] = value; } + } + + /// + /// Gets the list of departments of the persona + /// + public AttributedStringCollection Departments + { + get { return (AttributedStringCollection)this.PropertyBag[PersonaSchema.Departments]; } + set { this.PropertyBag[PersonaSchema.Departments] = value; } + } + + /// + /// Gets the list of photo URLs + /// + public AttributedStringCollection ThirdPartyPhotoUrls + { + get { return (AttributedStringCollection)this.PropertyBag[PersonaSchema.ThirdPartyPhotoUrls]; } + set { this.PropertyBag[PersonaSchema.ThirdPartyPhotoUrls] = value; } + } + + #endregion + } +} diff --git a/Core/ServiceObjects/Schemas/FolderSchema.cs b/Core/ServiceObjects/Schemas/FolderSchema.cs index f6d71c0b..0353bfb6 100644 --- a/Core/ServiceObjects/Schemas/FolderSchema.cs +++ b/Core/ServiceObjects/Schemas/FolderSchema.cs @@ -159,7 +159,7 @@ private static class FieldUris new GenericPropertyDefinition( XmlElementNames.DistinguishedFolderId, FieldUris.DistinguishedFolderId, - PropertyDefinitionFlags.CanFind, + PropertyDefinitionFlags.CanSet | PropertyDefinitionFlags.CanFind, ExchangeVersion.Exchange2013, true); diff --git a/Core/ServiceObjects/Schemas/PersonaSchema.cs b/Core/ServiceObjects/Schemas/PersonaSchema.cs new file mode 100644 index 00000000..0f6ec50c --- /dev/null +++ b/Core/ServiceObjects/Schemas/PersonaSchema.cs @@ -0,0 +1,411 @@ +// --------------------------------------------------------------------------- +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// --------------------------------------------------------------------------- + +//----------------------------------------------------------------------- +// Defines the PersonaSchema class. +//----------------------------------------------------------------------- + +namespace Microsoft.Exchange.WebServices.Data +{ + using System.Diagnostics.CodeAnalysis; + + /// + /// Persona schema + /// + [Schema] + public class PersonaSchema : ItemSchema + { + /// + /// FieldURIs for persona. + /// + private static class FieldUris + { + public const string PersonaId = "persona:PersonaId"; + public const string PersonaType = "persona:PersonaType"; + public const string CreationTime = "persona:CreationTime"; + public const string DisplayNameFirstLastHeader = "persona:DisplayNameFirstLastHeader"; + public const string DisplayNameLastFirstHeader = "persona:DisplayNameLastFirstHeader"; + public const string DisplayName = "persona:DisplayName"; + public const string DisplayNameFirstLast = "persona:DisplayNameFirstLast"; + public const string DisplayNameLastFirst = "persona:DisplayNameLastFirst"; + public const string FileAs = "persona:FileAs"; + public const string Generation = "persona:Generation"; + public const string DisplayNamePrefix = "persona:DisplayNamePrefix"; + public const string GivenName = "persona:GivenName"; + public const string Surname = "persona:Surname"; + public const string Title = "persona:Title"; + public const string CompanyName = "persona:CompanyName"; + public const string EmailAddress = "persona:EmailAddress"; + public const string EmailAddresses = "persona:EmailAddresses"; + public const string ImAddress = "persona:ImAddress"; + public const string HomeCity = "persona:HomeCity"; + public const string WorkCity = "persona:WorkCity"; + public const string Alias = "persona:Alias"; + public const string RelevanceScore = "persona:RelevanceScore"; + public const string Attributions = "persona:Attributions"; + public const string OfficeLocations = "persona:OfficeLocations"; + public const string ImAddresses = "persona:ImAddresses"; + public const string Departments = "persona:Departments"; + public const string ThirdPartyPhotoUrls = "persona:ThirdPartyPhotoUrls"; + } + + /// + /// Defines the PersonaId property. + /// + [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes", Justification = "Immutable type")] + public static readonly PropertyDefinition PersonaId = + new ComplexPropertyDefinition( + XmlElementNames.PersonaId, + FieldUris.PersonaId, + PropertyDefinitionFlags.AutoInstantiateOnRead | PropertyDefinitionFlags.CanSet | PropertyDefinitionFlags.CanUpdate | PropertyDefinitionFlags.CanDelete | PropertyDefinitionFlags.CanFind, + ExchangeVersion.Exchange2013_SP1, + delegate() { return new ItemId(); }); + + /// + /// Defines the PersonaType property. + /// + [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes", Justification = "Immutable type")] + public static readonly PropertyDefinition PersonaType = + new StringPropertyDefinition( + XmlElementNames.PersonaType, + FieldUris.PersonaType, + PropertyDefinitionFlags.CanSet | PropertyDefinitionFlags.CanUpdate | PropertyDefinitionFlags.CanDelete | PropertyDefinitionFlags.CanFind, + ExchangeVersion.Exchange2013_SP1); + + /// + /// Defines the CreationTime property. + /// + [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes", Justification = "Immutable type")] + public static readonly PropertyDefinition CreationTime = + new DateTimePropertyDefinition( + XmlElementNames.CreationTime, + FieldUris.CreationTime, + PropertyDefinitionFlags.CanSet | PropertyDefinitionFlags.CanUpdate | PropertyDefinitionFlags.CanDelete | PropertyDefinitionFlags.CanFind, + ExchangeVersion.Exchange2013_SP1); + + /// + /// Defines the DisplayNameFirstLastHeader property. + /// + [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes", Justification = "Immutable type")] + public static readonly PropertyDefinition DisplayNameFirstLastHeader = + new StringPropertyDefinition( + XmlElementNames.DisplayNameFirstLastHeader, + FieldUris.DisplayNameFirstLastHeader, + PropertyDefinitionFlags.CanSet | PropertyDefinitionFlags.CanUpdate | PropertyDefinitionFlags.CanDelete | PropertyDefinitionFlags.CanFind, + ExchangeVersion.Exchange2013_SP1); + + /// + /// Defines the DisplayNameLastFirstHeader property. + /// + [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes", Justification = "Immutable type")] + public static readonly PropertyDefinition DisplayNameLastFirstHeader = + new StringPropertyDefinition( + XmlElementNames.DisplayNameLastFirstHeader, + FieldUris.DisplayNameLastFirstHeader, + PropertyDefinitionFlags.CanSet | PropertyDefinitionFlags.CanUpdate | PropertyDefinitionFlags.CanDelete | PropertyDefinitionFlags.CanFind, + ExchangeVersion.Exchange2013_SP1); + + /// + /// Defines the DisplayName property. + /// + [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes", Justification = "Immutable type")] + public static readonly PropertyDefinition DisplayName = + new StringPropertyDefinition( + XmlElementNames.DisplayName, + FieldUris.DisplayName, + PropertyDefinitionFlags.CanSet | PropertyDefinitionFlags.CanUpdate | PropertyDefinitionFlags.CanDelete | PropertyDefinitionFlags.CanFind, + ExchangeVersion.Exchange2013_SP1); + + /// + /// Defines the DisplayNameFirstLast property. + /// + [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes", Justification = "Immutable type")] + public static readonly PropertyDefinition DisplayNameFirstLast = + new StringPropertyDefinition( + XmlElementNames.DisplayNameFirstLast, + FieldUris.DisplayNameFirstLast, + PropertyDefinitionFlags.CanSet | PropertyDefinitionFlags.CanUpdate | PropertyDefinitionFlags.CanDelete | PropertyDefinitionFlags.CanFind, + ExchangeVersion.Exchange2013_SP1); + + /// + /// Defines the DisplayNameLastFirst property. + /// + [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes", Justification = "Immutable type")] + public static readonly PropertyDefinition DisplayNameLastFirst = + new StringPropertyDefinition( + XmlElementNames.DisplayNameLastFirst, + FieldUris.DisplayNameLastFirst, + PropertyDefinitionFlags.CanSet | PropertyDefinitionFlags.CanUpdate | PropertyDefinitionFlags.CanDelete | PropertyDefinitionFlags.CanFind, + ExchangeVersion.Exchange2013_SP1); + + /// + /// Defines the FileAs property. + /// + [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes", Justification = "Immutable type")] + public static readonly PropertyDefinition FileAs = + new StringPropertyDefinition( + XmlElementNames.FileAs, + FieldUris.FileAs, + PropertyDefinitionFlags.CanSet | PropertyDefinitionFlags.CanUpdate | PropertyDefinitionFlags.CanDelete | PropertyDefinitionFlags.CanFind, + ExchangeVersion.Exchange2013_SP1); + + /// + /// Defines the Generation property. + /// + [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes", Justification = "Immutable type")] + public static readonly PropertyDefinition Generation = + new StringPropertyDefinition( + XmlElementNames.Generation, + FieldUris.Generation, + PropertyDefinitionFlags.CanSet | PropertyDefinitionFlags.CanUpdate | PropertyDefinitionFlags.CanDelete | PropertyDefinitionFlags.CanFind, + ExchangeVersion.Exchange2013_SP1); + + /// + /// Defines the DisplayNamePrefix property. + /// + [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes", Justification = "Immutable type")] + public static readonly PropertyDefinition DisplayNamePrefix = + new StringPropertyDefinition( + XmlElementNames.DisplayNamePrefix, + FieldUris.DisplayNamePrefix, + PropertyDefinitionFlags.CanSet | PropertyDefinitionFlags.CanUpdate | PropertyDefinitionFlags.CanDelete | PropertyDefinitionFlags.CanFind, + ExchangeVersion.Exchange2013_SP1); + + /// + /// Defines the GivenName property. + /// + [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes", Justification = "Immutable type")] + public static readonly PropertyDefinition GivenName = + new StringPropertyDefinition( + XmlElementNames.GivenName, + FieldUris.GivenName, + PropertyDefinitionFlags.CanSet | PropertyDefinitionFlags.CanUpdate | PropertyDefinitionFlags.CanDelete | PropertyDefinitionFlags.CanFind, + ExchangeVersion.Exchange2013_SP1); + + /// + /// Defines the Surname property. + /// + [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes", Justification = "Immutable type")] + public static readonly PropertyDefinition Surname = + new StringPropertyDefinition( + XmlElementNames.Surname, + FieldUris.Surname, + PropertyDefinitionFlags.CanSet | PropertyDefinitionFlags.CanUpdate | PropertyDefinitionFlags.CanDelete | PropertyDefinitionFlags.CanFind, + ExchangeVersion.Exchange2013_SP1); + + /// + /// Defines the Title property. + /// + [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes", Justification = "Immutable type")] + public static readonly PropertyDefinition Title = + new StringPropertyDefinition( + XmlElementNames.Title, + FieldUris.Title, + PropertyDefinitionFlags.CanSet | PropertyDefinitionFlags.CanUpdate | PropertyDefinitionFlags.CanDelete | PropertyDefinitionFlags.CanFind, + ExchangeVersion.Exchange2013_SP1); + + /// + /// Defines the CompanyName property. + /// + [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes", Justification = "Immutable type")] + public static readonly PropertyDefinition CompanyName = + new StringPropertyDefinition( + XmlElementNames.CompanyName, + FieldUris.CompanyName, + PropertyDefinitionFlags.CanSet | PropertyDefinitionFlags.CanUpdate | PropertyDefinitionFlags.CanDelete | PropertyDefinitionFlags.CanFind, + ExchangeVersion.Exchange2013_SP1); + + /// + /// Defines the EmailAddress property. + /// + [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes", Justification = "Immutable type")] + public static readonly PropertyDefinition EmailAddress = + new ComplexPropertyDefinition( + XmlElementNames.EmailAddress, + FieldUris.EmailAddress, + PropertyDefinitionFlags.AutoInstantiateOnRead | PropertyDefinitionFlags.CanSet | PropertyDefinitionFlags.CanUpdate | PropertyDefinitionFlags.CanDelete | PropertyDefinitionFlags.CanFind, + ExchangeVersion.Exchange2013_SP1, + delegate() { return new PersonaEmailAddress(); }); + + /// + /// Defines the EmailAddresses property. + /// + [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes", Justification = "Immutable type")] + public static readonly PropertyDefinition EmailAddresses = + new ComplexPropertyDefinition( + XmlElementNames.EmailAddresses, + FieldUris.EmailAddresses, + PropertyDefinitionFlags.AutoInstantiateOnRead | PropertyDefinitionFlags.CanSet | PropertyDefinitionFlags.CanUpdate | PropertyDefinitionFlags.CanDelete | PropertyDefinitionFlags.CanFind, + ExchangeVersion.Exchange2013_SP1, + delegate() { return new PersonaEmailAddressCollection(); }); + + /// + /// Defines the ImAddress property. + /// + [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes", Justification = "Immutable type")] + public static readonly PropertyDefinition ImAddress = + new StringPropertyDefinition( + XmlElementNames.ImAddress, + FieldUris.ImAddress, + PropertyDefinitionFlags.CanSet | PropertyDefinitionFlags.CanUpdate | PropertyDefinitionFlags.CanDelete | PropertyDefinitionFlags.CanFind, + ExchangeVersion.Exchange2013_SP1); + + /// + /// Defines the HomeCity property. + /// + [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes", Justification = "Immutable type")] + public static readonly PropertyDefinition HomeCity = + new StringPropertyDefinition( + XmlElementNames.HomeCity, + FieldUris.HomeCity, + PropertyDefinitionFlags.CanSet | PropertyDefinitionFlags.CanUpdate | PropertyDefinitionFlags.CanDelete | PropertyDefinitionFlags.CanFind, + ExchangeVersion.Exchange2013_SP1); + + /// + /// Defines the WorkCity property. + /// + [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes", Justification = "Immutable type")] + public static readonly PropertyDefinition WorkCity = + new StringPropertyDefinition( + XmlElementNames.WorkCity, + FieldUris.WorkCity, + PropertyDefinitionFlags.CanSet | PropertyDefinitionFlags.CanUpdate | PropertyDefinitionFlags.CanDelete | PropertyDefinitionFlags.CanFind, + ExchangeVersion.Exchange2013_SP1); + + /// + /// Defines the Alias property. + /// + [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes", Justification = "Immutable type")] + public static readonly PropertyDefinition Alias = + new StringPropertyDefinition( + XmlElementNames.Alias, + FieldUris.Alias, + PropertyDefinitionFlags.CanSet | PropertyDefinitionFlags.CanUpdate | PropertyDefinitionFlags.CanDelete | PropertyDefinitionFlags.CanFind, + ExchangeVersion.Exchange2013_SP1); + + /// + /// Defines the RelevanceScore property. + /// + [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes", Justification = "Immutable type")] + public static readonly PropertyDefinition RelevanceScore = + new IntPropertyDefinition( + XmlElementNames.RelevanceScore, + FieldUris.RelevanceScore, + PropertyDefinitionFlags.CanSet | PropertyDefinitionFlags.CanUpdate | PropertyDefinitionFlags.CanDelete | PropertyDefinitionFlags.CanFind, + ExchangeVersion.Exchange2013_SP1, + true); + + /// + /// Defines the Attributions property + /// + [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes", Justification = "Immutable type")] + public static readonly PropertyDefinition Attributions = + new ComplexPropertyDefinition( + XmlElementNames.Attributions, + FieldUris.Attributions, + PropertyDefinitionFlags.AutoInstantiateOnRead | PropertyDefinitionFlags.CanSet | PropertyDefinitionFlags.CanUpdate | PropertyDefinitionFlags.CanDelete | PropertyDefinitionFlags.CanFind, + ExchangeVersion.Exchange2013_SP1, + delegate() { return new AttributionCollection(); }); + + /// + /// Defines the OfficeLocations property. + /// + [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes", Justification = "Immutable type")] + public static readonly PropertyDefinition OfficeLocations = + new ComplexPropertyDefinition( + XmlElementNames.OfficeLocations, + FieldUris.OfficeLocations, + PropertyDefinitionFlags.AutoInstantiateOnRead | PropertyDefinitionFlags.CanSet | PropertyDefinitionFlags.CanUpdate | PropertyDefinitionFlags.CanDelete | PropertyDefinitionFlags.CanFind, + ExchangeVersion.Exchange2013_SP1, + delegate() { return new AttributedStringCollection(); }); + + /// + /// Defines the ImAddresses property. + /// + [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes", Justification = "Immutable type")] + public static readonly PropertyDefinition ImAddresses = + new ComplexPropertyDefinition( + XmlElementNames.ImAddresses, + FieldUris.ImAddresses, + PropertyDefinitionFlags.AutoInstantiateOnRead | PropertyDefinitionFlags.CanSet | PropertyDefinitionFlags.CanUpdate | PropertyDefinitionFlags.CanDelete | PropertyDefinitionFlags.CanFind, + ExchangeVersion.Exchange2013_SP1, + delegate() { return new AttributedStringCollection(); }); + + /// + /// Defines the Departments property. + /// + [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes", Justification = "Immutable type")] + public static readonly PropertyDefinition Departments = + new ComplexPropertyDefinition( + XmlElementNames.Departments, + FieldUris.Departments, + PropertyDefinitionFlags.AutoInstantiateOnRead | PropertyDefinitionFlags.CanSet | PropertyDefinitionFlags.CanUpdate | PropertyDefinitionFlags.CanDelete | PropertyDefinitionFlags.CanFind, + ExchangeVersion.Exchange2013_SP1, + delegate() { return new AttributedStringCollection(); }); + + /// + /// Defines the ThirdPartyPhotoUrls property. + /// + [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes", Justification = "Immutable type")] + public static readonly PropertyDefinition ThirdPartyPhotoUrls = + new ComplexPropertyDefinition( + XmlElementNames.ThirdPartyPhotoUrls, + FieldUris.ThirdPartyPhotoUrls, + PropertyDefinitionFlags.AutoInstantiateOnRead | PropertyDefinitionFlags.CanSet | PropertyDefinitionFlags.CanUpdate | PropertyDefinitionFlags.CanDelete | PropertyDefinitionFlags.CanFind, + ExchangeVersion.Exchange2013_SP1, + delegate() { return new AttributedStringCollection(); }); + + // This must be declared after the property definitions + internal static new readonly PersonaSchema Instance = new PersonaSchema(); + + /// + /// Registers properties. + /// + /// + /// IMPORTANT NOTE: PROPERTIES MUST BE REGISTERED IN SCHEMA ORDER (i.e. the same order as they are defined in types.xsd) + /// + internal override void RegisterProperties() + { + base.RegisterProperties(); + + this.RegisterProperty(PersonaId); + this.RegisterProperty(PersonaType); + this.RegisterProperty(CreationTime); + this.RegisterProperty(DisplayNameFirstLastHeader); + this.RegisterProperty(DisplayNameLastFirstHeader); + this.RegisterProperty(DisplayName); + this.RegisterProperty(DisplayNameFirstLast); + this.RegisterProperty(DisplayNameLastFirst); + this.RegisterProperty(FileAs); + this.RegisterProperty(Generation); + this.RegisterProperty(DisplayNamePrefix); + this.RegisterProperty(GivenName); + this.RegisterProperty(Surname); + this.RegisterProperty(Title); + this.RegisterProperty(CompanyName); + this.RegisterProperty(EmailAddress); + this.RegisterProperty(EmailAddresses); + this.RegisterProperty(ImAddress); + this.RegisterProperty(HomeCity); + this.RegisterProperty(WorkCity); + this.RegisterProperty(Alias); + this.RegisterProperty(RelevanceScore); + this.RegisterProperty(Attributions); + this.RegisterProperty(OfficeLocations); + this.RegisterProperty(ImAddresses); + this.RegisterProperty(Departments); + this.RegisterProperty(ThirdPartyPhotoUrls); + } + + /// + /// internal constructor + /// + internal PersonaSchema() + : base() + { + } + } +} diff --git a/Core/ServiceObjects/Schemas/ServiceObjectSchema.cs b/Core/ServiceObjects/Schemas/ServiceObjectSchema.cs index 11b2d6d0..59eb8f06 100644 --- a/Core/ServiceObjects/Schemas/ServiceObjectSchema.cs +++ b/Core/ServiceObjects/Schemas/ServiceObjectSchema.cs @@ -52,6 +52,7 @@ public abstract class ServiceObjectSchema : IEnumerable typeList.Add(typeof(MeetingRequestSchema)); typeList.Add(typeof(MeetingCancellationSchema)); typeList.Add(typeof(MeetingResponseSchema)); + typeList.Add(typeof(PersonaSchema)); typeList.Add(typeof(PostItemSchema)); typeList.Add(typeof(PostReplySchema)); typeList.Add(typeof(ResponseMessageSchema)); diff --git a/Core/ServiceObjects/Schemas/Xsd/messages.xsd b/Core/ServiceObjects/Schemas/Xsd/messages.xsd deleted file mode 100644 index d2f6f0b0..00000000 --- a/Core/ServiceObjects/Schemas/Xsd/messages.xsd +++ /dev/null @@ -1,4139 +0,0 @@ - - - - - - - - - Represents the message keys that can be returned by response error messages - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Converts the passed source ids into the destination format. Change keys are not - returned. - - - - - - - - - - - - - - - - Response type for the ConvertId web method - - - - - - - - - - - Response Message for a single id conversion in the ConvertId web method. Note - that the AlternateId element will be missing in the case of an error. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Request type for the FindMailboxStatisticsByKeywords web method. - - - - - - - - - - - - - - - - - - - - - - - - - - Response type for the FindMailboxStatisticsByKeywords web method. - - - - - - - - - - - - Response message type for the FindMailboxStatisticsByKeywords web method. - - - - - - - - - - - - - - - - Request type for the GetSearchableMailboxes web method. - - - - - - - - - - - - - - - - - Response message type for the GetSearchableMailboxes web method. - - - - - - - - - - - - - - - - - - - Request type for the SearchMailboxes web method. - - - - - - - - - - - - - - - - - - - - - - - - Response type for the SearchMailboxes web method. - - - - - - - - - - - - Response message type for the SearchMailboxes web method. - - - - - - - - - - - - - - - - Request type for the GetDiscoverySearchConfiguration web method. - - - - - - - - - - - - - - - - - - Response message type for the GetDiscoverySearchConfiguration web method. - - - - - - - - - - - - - - - - - - Request type for the GetHoldOnMailboxes web method. - - - - - - - - - - - - - - - - Response message type for the GetHoldOnMailboxes web method. - - - - - - - - - - - - - - - - - - Request type for the SetHoldOnMailboxes web method. - - - - - - - - - - - - - - - - - - - - - - - - Response message type for the SetHoldOnMailboxes web method. - - - - - - - - - - - - - - - - - - Request type for the GetNonIndexableItemStatistics web method. - - - - - - - - - - - - - - - - - Response message type for the GetNonIndexableItemStatistics web method. - - - - - - - - - - - - - - - - - - Request type for the GetNonIndexableItemDetails web method. - - - - - - - - - - - - - - - - - - - - Response message type for the GetNonIndexableItemDetails web method. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Request type for the GetUserRetentionPolicyTags web method. - - - - - - - - - - - - - Response message type for the GetUserRetentionPolicyTags web method. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Core/ServiceObjects/Schemas/Xsd/types.xsd b/Core/ServiceObjects/Schemas/Xsd/types.xsd deleted file mode 100644 index 2d4e4d67..00000000 --- a/Core/ServiceObjects/Schemas/Xsd/types.xsd +++ /dev/null @@ -1,7542 +0,0 @@ - - - - - - - - - - - - Allow attributes in the soap namespace to be used here - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Allow attributes in the soap namespace to be used here - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Allow attributes in the soap namespace to be used here - - - - - - - - Surfaces the various logon types that are supported for conversion - - - - - - - - - - - - - - - - Allow attributes in the soap namespace to be used here - - - - - - - - - - - - - - - - - - - - - - - - - - - Allow attributes in the soap namespace to be used here - - - - - - - - - - - - - - - - - - - - - - - - - - - Allow attributes in the soap namespace to be used here - - - - - - - - - - Precision for returned DateTime values - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Identifier for a fully resolved email address - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - The regular expression captures the standard representation of a GUID - - - - - - - - - - - Defines the well known property set ids for extended properties. - - - - - - - - - - - - - - - - - - - - Includes all of the extended property types that we support. Note that Error, Null, - Object and Object array can not be used in restrictions, or for setting/getting values. - They are only there for error reporting purposes. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - This type represents the property tag (MINUS the type part). There are two options - for representation: - 1. Hex ==> 0x3fa4 - 2. Decimal ==> 0-65535 - - - - - - - - - - - - - - - Represents an extended property. Note that there are only a couple of valid attribute - combinations. Note that all occurances require the PropertyType attribute. - - 1. (DistinguishedPropertySetId || PropertySetId) + (PropertyName || Property Id) - 2. PropertyTag - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Represents an extended property instance (both its path identifier along with its - associated value). - - - - - - - - - - - - - - - Types of sub-tree traversal for deletion and enumeration - - - - - - - - - - - Types of sub-tree traversal for deletion and enumeration - - - - - - - - - - Types of sub-tree traversal for deletion and enumeration - - - - - - - - - - - Types of sub-tree traversal for conversations - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Type of conflict resolution to attempt during update - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Utility type which should never appear in user documents - - - - - - - - - - - URIs for the distinguished folders accessible from a mailbox - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Identifier for a distinguished folder - - - - - - - - - - - - - - - Identifier for a fully resolved folder - - - - - - - - - - - - Identifier for a address list - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Types of view filters for finding items/conversations - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Compound property for Managed Folder related information for Managed Folders. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Abstract base type for item identifiers. Should never be used in web service calls - - - - - - - - - - - Identifier for a fully resolved item - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Internal abstract base type for reply objects. - Should not appear in client code - - - - - - - - - - - - - - Abstract base type for reply objects - - - - - - - The name of this reply object class as an English string. The client - application is required to translate it if it's running in a different locale - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Allow attributes in the soap namespace to be used here - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - This max/min evaluation is applied to the field specified within the group by - instance for EACH item within that group. This determines which item from each group - is to be selected as the representative for that group. - - - - - - - - - - - - Represents the field of each item to aggregate on and the qualifier to apply to that - field in determining which item will represent the group. - - - - - - - - - - - - - - - - - - - Allows consumers to specify arbitrary groupings for FindItem queries. - - - - - - - - - - - - - - - - - - - - - Represents standard groupings for GroupBy queries. - - - - - - - - - - - Allows consumers to access standard groupings for FindItem queries. This is in - contrast to the arbitrary (custom) groupings available via the t:GroupByType - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Surfaces the various id types that are supported for conversion - - - - - - - - - - - - - - - Surfaces alternate representations of an item or folder id. No change key is included. - - - - - - - - - Represents an alternate mailbox folder or item Id. - - - - - - - - - - - - - - - Represents an alternate public folder Id. - - - - - - - - - - - - - Represents an alternate public folder item Id. - - - - - - - - - - - - - A non-empty array of alternate Ids. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - A permission on a folder - - - - - - - - - - - - - - - - A permission on a folder - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - The set of permissions on a folder - - - - - - - - - - The set of permissions on a folder - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Represents the message keys that can be returned for invalid recipients - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Size range type used for the WithinSizeRange rule predicate. - - - - - - - - - - Date range type used for the WithinDateRange rule predicate. - - - - - - - - - - Flagged for action enumeration, currently used in FlaggedForAction rule predicate - - - - - - - - - - - - - - - - - - - Rule predicates, used as rule conditions or exceptions - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Rule actions - - - - - - - - - - - - - - - - - - - - - Rule type - - - - - - - - - - - - - - - - - Array of rule objects - - - - - - - - Rule field URI enumerates all possible rule fields that could trigger validation error - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Rule validation error code describing what failed validation for each rule predicate or action. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Represents a single validation error on a particular rule property value, predicate property value or action property value - - - - - - - - - - - - Represents an array of rule validation errors - - - - - - - - - Represents a rule operation to be performed - - - - - - Represents an array of rule operations to be performed - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Array of search item kind enum. - - - - - - - - - - - User Mailbox. - - - - - - - - - - Array of user mailbox. - - - - - - - - - - - Searchable mailbox. - - - - - - - - - - - - - - - - - Array of searchable mailbox. - - - - - - - - - - - Keyword statistics search result. - - - - - - - - - - - - - Array of keyword statistics result. - - - - - - - - - - - Mailbox statistics search result. - - - - - - - - - - - - - Extended attributes of a target mailbox. - - - - - - - - - - - - Array of extended attributes of a target mailbox - - - - - - - - - - - - - - - - - - - Set of mailbox, search scope and its extended attributes. - - - - - - - - - - - - - Array of mailbox and its search scope. - - - - - - - - - - - Pair of query and a set of mailbox search scopes. - - - - - - - - - - - - Mailbox information for each preview item. - - - - - - - - - - - - Array of query and mailboxes. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Mailbox search preview item. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Array of search preview item. - - - - - - - - - - - Mailbox failed on search and its error message. - - - - - - - - - - - - - - Array of failed mailbox and error message. - - - - - - - - - - - Mailboxes search result. - - - - - - - - - - - - - - - - - - - - - Search refiner item. - - - - - - - - - - - - - - Array of search refiner item. - - - - - - - - - - - Mailbox statistics item. - - - - - - - - - - - - - - Array of mailbox statistics item. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Mailbox hold status. - - - - - - - - - - - - - Array of mailbox hold status. - - - - - - - - - - - Mailbox hold result. - - - - - - - - - - - - - - - - - - - Non indexable item statistic. - - - - - - - - - - - - - Array of non indexable item statistics. - - - - - - - - - - - - - - - - - - - - - - - - Non indexable item detail. - - - - - - - - - - - - - - - - - - - Array of non indexable item details. - - - - - - - - - - - Non indexable item details result. - - - - - - - - - - - - Discovery search configuration. - - - - - - - - - - - - - - - - Array of discovery search configuration. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Retention policy tag. - - - - - - - - - - - - - - - - - - - Array of retention policy tags. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - A Group on the ImContactList, with one or more members - - - - - - - - - - - - - - - - - - - - - - IM Contact List - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - List of possible reasons for disabling the client extension - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Core/ServiceObjects/ServiceObjectInfo.cs b/Core/ServiceObjects/ServiceObjectInfo.cs index 532340a4..cf28dff5 100644 --- a/Core/ServiceObjects/ServiceObjectInfo.cs +++ b/Core/ServiceObjects/ServiceObjectInfo.cs @@ -141,6 +141,13 @@ private void InitializeServiceObjectClassMap() delegate(ExchangeService srv) { return new MeetingResponse(srv); }, delegate(ItemAttachment itemAttachment, bool isNew) { return new MeetingResponse(itemAttachment); }); + // Persona + this.AddServiceObjectType( + XmlElementNames.Persona, + typeof(Persona), + delegate(ExchangeService srv) { return new Persona(srv); }, + null); + // PostItem this.AddServiceObjectType( XmlElementNames.PostItem, diff --git a/Core/XmlElementNames.cs b/Core/XmlElementNames.cs index 36330d94..c20fe2ea 100644 --- a/Core/XmlElementNames.cs +++ b/Core/XmlElementNames.cs @@ -22,6 +22,7 @@ internal static class XmlElementNames public const string ItemIds = "ItemIds"; public const string FolderId = "FolderId"; public const string FolderIds = "FolderIds"; + public const string SourceId = "SourceId"; public const string OccurrenceItemId = "OccurrenceItemId"; public const string RecurringMasterItemId = "RecurringMasterItemId"; public const string ItemShape = "ItemShape"; @@ -84,8 +85,11 @@ internal static class XmlElementNames public const string IsAssociated = "IsAssociated"; public const string IsDraft = "IsDraft"; public const string IsFromMe = "IsFromMe"; + public const string IsHidden = "IsHidden"; + public const string IsQuickContact = "IsQuickContact"; public const string IsResend = "IsResend"; public const string IsUnmodified = "IsUnmodified"; + public const string IsWritable = "IsWritable"; public const string InternetMessageHeader = "InternetMessageHeader"; public const string InternetMessageHeaders = "InternetMessageHeaders"; public const string DateTimeSent = "DateTimeSent"; @@ -612,6 +616,7 @@ internal static class XmlElementNames public const string UserOptions = "UserOptions"; public const string VotingResponse = "VotingResponse"; public const string NumberOfDays = "NumberOfDays"; + public const string AcceptanceState = "AcceptanceState"; public const string NlgEntityExtractionResult = "EntityExtractionResult"; public const string NlgAddresses = "Addresses"; @@ -663,6 +668,97 @@ internal static class XmlElementNames public const string MarkAsJunkResponseMessage = "MarkAsJunkResponseMessage"; public const string MovedItemId = "MovedItemId"; + #region Persona + + public const string CreationTime = "CreationTime"; + public const string People = "People"; + public const string Persona = "Persona"; + public const string PersonaId = "PersonaId"; + public const string PersonaShape = "PersonaShape"; + public const string RelevanceScore = "RelevanceScore"; + public const string TotalNumberOfPeopleInView = "TotalNumberOfPeopleInView"; + public const string FirstMatchingRowIndex = "FirstMatchingRowIndex"; + public const string FirstLoadedRowIndex = "FirstLoadedRowIndex"; + public const string YomiCompanyName = "YomiCompanyName"; + public const string Emails1 = "Emails1"; + public const string Emails2 = "Emails2"; + public const string Emails3 = "Emails3"; + public const string HomeAddresses = "HomeAddresses"; + public const string BusinessAddresses = "BusinessAddresses"; + public const string OtherAddresses = "OtherAddresses"; + public const string BusinessPhoneNumbers = "BusinessPhoneNumbers"; + public const string BusinessPhoneNumbers2 = "BusinessPhoneNumbers2"; + public const string AssistantPhoneNumbers = "AssistantPhoneNumbers"; + public const string TTYTDDPhoneNumbers = "TTYTDDPhoneNumbers"; + public const string HomePhones = "HomePhones"; + public const string HomePhones2 = "HomePhones2"; + public const string MobilePhones = "MobilePhones"; + public const string MobilePhones2 = "MobilePhones2"; + public const string CallbackPhones = "CallbackPhones"; + public const string CarPhones = "CarPhones"; + public const string HomeFaxes = "HomeFaxes"; + public const string OrganizationMainPhones = "OrganizationMainPhones"; + public const string OtherFaxes = "OtherFaxes"; + public const string OtherTelephones = "OtherTelephones"; + public const string OtherPhones2 = "OtherPhones2"; + public const string Pagers = "Pagers"; + public const string RadioPhones = "RadioPhones"; + public const string TelexNumbers = "TelexNumbers"; + public const string WorkFaxes = "WorkFaxes"; + public const string FileAses = "FileAses"; + public const string CompanyNames = "CompanyNames"; + public const string DisplayNames = "DisplayNames"; + public const string DisplayNamePrefixes = "DisplayNamePrefixes"; + public const string GivenNames = "GivenNames"; + public const string MiddleNames = "MiddleNames"; + public const string Surnames = "Surnames"; + public const string Generations = "Generations"; + public const string Nicknames = "Nicknames"; + public const string YomiCompanyNames = "YomiCompanyNames"; + public const string YomiFirstNames = "YomiFirstNames"; + public const string YomiLastNames = "YomiLastNames"; + public const string Managers = "Managers"; + public const string AssistantNames = "AssistantNames"; + public const string Professions = "Professions"; + public const string SpouseNames = "SpouseNames"; + public const string Departments = "Departments"; + public const string Titles = "Titles"; + public const string ImAddresses2 = "ImAddresses2"; + public const string ImAddresses3 = "ImAddresses3"; + public const string DisplayNamePrefix = "DisplayNamePrefix"; + public const string DisplayNameFirstLast = "DisplayNameFirstLast"; + public const string DisplayNameLastFirst = "DisplayNameLastFirst"; + public const string DisplayNameFirstLastHeader = "DisplayNameFirstLastHeader"; + public const string DisplayNameLastFirstHeader = "DisplayNameLastFirstHeader"; + public const string IsFavorite = "IsFavorite"; + public const string Schools = "Schools"; + public const string Hobbies = "Hobbies"; + public const string Locations = "Locations"; + public const string OfficeLocations = "OfficeLocations"; + public const string BusinessHomePages = "BusinessHomePages"; + public const string PersonalHomePages = "PersonalHomePages"; + public const string ThirdPartyPhotoUrls = "ThirdPartyPhotoUrls"; + public const string Attribution = "Attribution"; + public const string Attributions = "Attributions"; + public const string StringAttributedValue = "StringAttributedValue"; + public const string DisplayNameFirstLastSortKey = "DisplayNameFirstLastSortKey"; + public const string DisplayNameLastFirstSortKey = "DisplayNameLastFirstSortKey"; + public const string CompanyNameSortKey = "CompanyNameSortKey"; + public const string HomeCitySortKey = "HomeCitySortKey"; + public const string WorkCitySortKey = "WorkCitySortKey"; + public const string FileAsId = "FileAsId"; + public const string FileAsIds = "FileAsIds"; + public const string HomeCity = "HomeCity"; + public const string WorkCity = "WorkCity"; + public const string PersonaType = "PersonaType"; + public const string Birthdays = "Birthdays"; + public const string BirthdaysLocal = "BirthdaysLocal"; + public const string WeddingAnniversaries = "WeddingAnniversaries"; + public const string WeddingAnniversariesLocal = "WeddingAnniversariesLocal"; + public const string OriginalDisplayName = "OriginalDisplayName"; + + #endregion + #region Conversations public const string Conversations = "Conversations"; @@ -973,6 +1069,14 @@ internal static class XmlElementNames public const string DirectReports = "DirectReports"; #endregion + #region Photos + + public const string SizeRequested = "SizeRequested"; + public const string HasChanged = "HasChanged"; + public const string PictureData = "PictureData"; + + #endregion + #region Request/response element names public const string ResponseMessage = "ResponseMessage"; public const string ResponseMessages = "ResponseMessages"; @@ -1078,6 +1182,16 @@ internal static class XmlElementNames public const string MarkAllItemsAsReadResponse = "MarkAllItemsAsReadResponse"; public const string MarkAllItemsAsReadResponseMessage = "MarkAllItemsAsReadResponseMessage"; + // FindPeople + public const string FindPeople = "FindPeople"; + public const string FindPeopleResponse = "FindPeopleResponse"; + public const string FindPeopleResponseMessage = "FindPeopleResponseMessage"; + + // GetUserPhoto + public const string GetUserPhoto = "GetUserPhoto"; + public const string GetUserPhotoResponse = "GetUserPhotoResponse"; + public const string GetUserPhotoResponseMessage = "GetUserPhotoResponseMessage"; + // GetAttachment public const string GetAttachment = "GetAttachment"; public const string GetAttachmentResponse = "GetAttachmentResponse"; @@ -1395,6 +1509,13 @@ internal static class XmlElementNames public const string GetEncryptionConfigurationResponse = "GetEncryptionConfigurationResponse"; public const string SetEncryptionConfigurationResponse = "SetEncryptionConfigurationResponse"; + // GetOMEConfiguration/SetOMEConfiguration + public const string GetOMEConfigurationRequest = "GetOMEConfiguration"; + public const string SetOMEConfigurationRequest = "SetOMEConfiguration"; + public const string OMEConfigurationXml = "Xml"; + public const string GetOMEConfigurationResponse = "GetOMEConfigurationResponse"; + public const string SetOMEConfigurationResponse = "SetOMEConfigurationResponse"; + // InstallApp public const string InstallAppRequest = "InstallApp"; public const string InstallAppResponse = "InstallAppResponse"; @@ -1407,6 +1528,10 @@ internal static class XmlElementNames public const string DisableAppRequest = "DisableApp"; public const string DisableAppResponse = "DisableAppResponse"; + // RegisterConsent + public const string RegisterConsentRequest = "RegisterConsent"; + public const string RegisterConsentResponse = "RegisterConsentResponse"; + // GetAppMarketplaceUrl public const string GetAppMarketplaceUrlRequest = "GetAppMarketplaceUrl"; public const string GetAppMarketplaceUrlResponse = "GetAppMarketplaceUrlResponse"; @@ -1428,6 +1553,39 @@ internal static class XmlElementNames #endregion + #region Groups + + // GetUserUnifiedGroups + public const string GetUserUnifiedGroups = "GetUserUnifiedGroups"; + public const string RequestedGroupsSets = "RequestedGroupsSets"; + public const string RequestedUnifiedGroupsSetItem = "RequestedUnifiedGroupsSet"; + public const string SortType = "SortType"; + public const string FilterType = "FilterType"; + public const string SortDirection = "SortDirection"; + public const string GroupsLimit = "GroupsLimit"; + public const string UserSmtpAddress = "UserSmtpAddress"; + + public const string GetUserUnifiedGroupsResponseMessage = "GetUserUnifiedGroupsResponseMessage"; + public const string GroupsSets = "GroupsSets"; + public const string UnifiedGroupsSet = "UnifiedGroupsSet"; + public const string TotalGroups = "TotalGroups"; + public const string GroupsTag = "Groups"; + public const string UnifiedGroup = "UnifiedGroup"; + public const string MailboxGuid = "MailboxGuid"; + public const string LastVisitedTimeUtc = "LastVisitedTimeUtc"; + public const string AccessType = "AccessType"; + public const string ExternalDirectoryObjectId = "ExternalDirectoryObjectId"; + + // GetUnifiedGroupUnseenCount + public const string GetUnifiedGroupUnseenCount = "GetUnifiedGroupUnseenCount"; + public const string GroupIdentity = "GroupIdentity"; + public const string GroupIdentityType = "IdentityType"; + public const string GroupIdentityValue = "Value"; + + public const string GetUnifiedGroupUnseenCountResponseMessage = "GetUnifiedGroupUnseenCountResponseMessage"; + public const string UnseenCount = "UnseenCount"; + #endregion + #region SOAP element names public const string SOAPEnvelopeElementName = "Envelope"; diff --git a/Enumerations/ConsentState.cs b/Enumerations/ConsentState.cs new file mode 100644 index 00000000..b21f480f --- /dev/null +++ b/Enumerations/ConsentState.cs @@ -0,0 +1,32 @@ +// --------------------------------------------------------------------------- +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// --------------------------------------------------------------------------- + +namespace Microsoft.Exchange.WebServices.Data.Enumerations +{ + using System; + + /// + /// The consent states enumeration + /// + [Serializable] + public enum ConsentState + { + /// + /// User has closed the consent page or has not responded yet. + /// + NotResponded = 0, + + /// + /// User has requested to disable the extension. + /// + NotConsented = 1, + + /// + /// User has requested to enable the extension. + /// + Consented = 2 + } +} diff --git a/Enumerations/GetUserPhotoStatus.cs b/Enumerations/GetUserPhotoStatus.cs new file mode 100644 index 00000000..ec062fd1 --- /dev/null +++ b/Enumerations/GetUserPhotoStatus.cs @@ -0,0 +1,33 @@ +// --------------------------------------------------------------------------- +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// --------------------------------------------------------------------------- + +//----------------------------------------------------------------------- +// Defines the GetUserPhotoStatus enumeration. +//----------------------------------------------------------------------- + +namespace Microsoft.Exchange.WebServices.Data +{ + /// + /// Defines the response types from a GetUserPhoto request + /// + public enum GetUserPhotoStatus + { + /// + /// The photo was successfully returned + /// + PhotoReturned, + + /// + /// The photo has not changed since it was last obtained + /// + PhotoUnchanged, + + /// + /// The photo or user was not found on the server + /// + PhotoOrUserNotFound, + } +} diff --git a/Enumerations/ServiceError.cs b/Enumerations/ServiceError.cs index b7156afb..332ff0dd 100644 --- a/Enumerations/ServiceError.cs +++ b/Enumerations/ServiceError.cs @@ -2287,6 +2287,41 @@ public enum ServiceError /// /// Receive quota message per folder is exceeded. /// - ErrorMessagePerFolderCountReceiveQuotaExceeded + ErrorMessagePerFolderCountReceiveQuotaExceeded, + + /// + /// Unified group was not found. + /// + ErrorUnifiedGroupMailboxNotFound, + + /// + /// Invalid channel id. + /// + ErrorInvalidChannelId, + + /// + /// Another connection is opened on the same channel. + /// + ErrorNewChannelConnectionOpened, + + /// + /// The channel subscription cannot be found. + /// + ErrorChannelSubscriptionNotFound, + + /// + /// The channel contains too many subscriptions. + /// + ErrorExceededChannelSubscriptionCount, + + /// + /// The channel subscription already exists. + /// + ErrorChannelSubscriptionAlreadyExists, + + /// + /// The given channel subscription id is invalid. + /// + ErrorInvalidChannelSubscriptionId, } } diff --git a/Enumerations/ServiceObjectType.cs b/Enumerations/ServiceObjectType.cs index 51584999..7623690c 100644 --- a/Enumerations/ServiceObjectType.cs +++ b/Enumerations/ServiceObjectType.cs @@ -32,6 +32,11 @@ public enum ServiceObjectType /// /// Data represents a conversation /// - Conversation + Conversation, + + /// + /// Data represents a persona + /// + Persona } } diff --git a/Enumerations/TraceFlags.cs b/Enumerations/TraceFlags.cs index 5a05269a..11f93ec3 100644 --- a/Enumerations/TraceFlags.cs +++ b/Enumerations/TraceFlags.cs @@ -73,6 +73,11 @@ public enum TraceFlags : long /// AutodiscoverRequestHttpHeaders = 512, + /// + /// Trace EWS timezone related logic. + /// + EwsTimeZones = 1024, + /// /// All trace types enabled. /// diff --git a/Enumerations/UnifiedGroupEnumTypes.cs b/Enumerations/UnifiedGroupEnumTypes.cs new file mode 100644 index 00000000..39f594c3 --- /dev/null +++ b/Enumerations/UnifiedGroupEnumTypes.cs @@ -0,0 +1,112 @@ +// --------------------------------------------------------------------------- +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// --------------------------------------------------------------------------- + +//----------------------------------------------------------------------- +// Defines the UnifiedGroupsEnumTypes. +//----------------------------------------------------------------------- +namespace Microsoft.Exchange.WebServices.Data.Groups +{ + using System; + + /// + /// The UnifiedGroupsSortType enum + /// + public enum UnifiedGroupsSortType + { + /// + /// None + /// + None = 0, + + /// + /// Display Name + /// + DisplayName = 1, + + /// + /// Join Date + /// + JoinDate = 2, + + /// + /// Favorite Date + /// + FavoriteDate = 3, + + /// + /// Relevance + /// + Relevance = 4, + } + + /// + /// The UnifiedGroupsFilterType enum + /// + public enum UnifiedGroupsFilterType + { + /// + /// All + /// + All = 0, + + /// + /// Favorites + /// + Favorites = 1, + + /// + /// Exclude Favorites + /// + ExcludeFavorites = 2 + } + + /// + /// The UnifiedGroupAccessType enum + /// + public enum UnifiedGroupAccessType + { + /// + /// None + /// + None = 0, + + /// + /// Private Group + /// + Private = 1, + + /// + /// Secret Group + /// + Secret = 2, + + /// + /// Public Group + /// + Public = 3, + } + + /// + /// The UnifiedGroupIdentityType enum + /// + public enum UnifiedGroupIdentityType + { + /// + /// Smtp Address + /// + SmtpAddress = 0, + + /// + /// Legacy DN + /// + LegacyDn = 1, + + /// + /// ExternalDirectoryObjectId + /// + ExternalDirectoryObjectId = 2 + } +} diff --git a/Enumerations/UserPhotoSize.cs b/Enumerations/UserPhotoSize.cs new file mode 100644 index 00000000..11e0e317 --- /dev/null +++ b/Enumerations/UserPhotoSize.cs @@ -0,0 +1,45 @@ +// --------------------------------------------------------------------------- +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// --------------------------------------------------------------------------- + +//----------------------------------------------------------------------- +// Defines the UserPhotoSize enumeration. +//----------------------------------------------------------------------- + +namespace Microsoft.Exchange.WebServices.Data +{ + /// + /// Defines the different user photo sizes that can be requested + /// + public static class UserPhotoSize + { + /// Image of size 48x48 + public static readonly string HR48x48 = "HR48x48"; + + /// Image of size 64x64 + public static readonly string HR64x64 = "HR64x64"; + + /// Image of size 96x96 + public static readonly string HR96x96 = "HR96x96"; + + /// Image of size 120x120 + public static readonly string HR120x120 = "HR120x120"; + + /// Image of size 240x240 + public static readonly string HR240x240 = "HR240x240"; + + /// Image of size 360x360 + public static readonly string HR360x360 = "HR360x360"; + + /// Image of size 432x432 + public static readonly string HR432x432 = "HR432x432"; + + /// Image of size 504x504 + public static readonly string HR504x504 = "HR504x504"; + + /// Image of size 648x648 + public static readonly string HR648x648 = "HR648x648"; + } +} diff --git a/Enumerations/UserSettingName.cs b/Enumerations/UserSettingName.cs index c1d518bd..0e012f9b 100644 --- a/Enumerations/UserSettingName.cs +++ b/Enumerations/UserSettingName.cs @@ -503,5 +503,15 @@ public enum UserSettingName /// The grouping hint for certain clients. /// GroupingInformation = 96, + + /// + /// Internal OutlookService URL + /// + InternalOutlookServiceUrl = 98, + + /// + /// External OutlookService URL + /// + ExternalOutlookServiceUrl = 99 } } diff --git a/Enumerations/WellKnownFolderName.cs b/Enumerations/WellKnownFolderName.cs index 31ca7d78..15de0d19 100644 --- a/Enumerations/WellKnownFolderName.cs +++ b/Enumerations/WellKnownFolderName.cs @@ -146,6 +146,13 @@ public enum WellKnownFolderName [RequiredServerVersion(ExchangeVersion.Exchange2010_SP1)] [EwsEnum("recoverableitemspurges")] RecoverableItemsPurges, + + /// + /// The Dumpster 2.0 discovery hold folder + /// + [RequiredServerVersion(ExchangeVersion.Exchange2013_SP1)] + [EwsEnum("recoverableitemsdiscoveryholds")] + RecoverableItemsDiscoveryHolds, /// /// The root of the archive mailbox. @@ -154,10 +161,17 @@ public enum WellKnownFolderName [EwsEnum("archiveroot")] ArchiveRoot, - /// - /// The message folder root in the archive mailbox. - /// - [RequiredServerVersion(ExchangeVersion.Exchange2010_SP1)] + /// + /// The root of the archive mailbox. + /// + [RequiredServerVersion(ExchangeVersion.Exchange2013_SP1)] + [EwsEnum("archiveinbox")] + ArchiveInbox, + + /// + /// The message folder root in the archive mailbox. + /// + [RequiredServerVersion(ExchangeVersion.Exchange2010_SP1)] [EwsEnum("archivemsgfolderroot")] ArchiveMsgFolderRoot, @@ -196,6 +210,13 @@ public enum WellKnownFolderName [EwsEnum("archiverecoverableitemspurges")] ArchiveRecoverableItemsPurges, + /// + /// The Dumpster 2.0 discovery hold folder in the archive mailbox. + /// + [RequiredServerVersion(ExchangeVersion.Exchange2013_SP1)] + [EwsEnum("archiverecoverableitemsdiscoveryholds")] + ArchiveRecoverableItemsDiscoveryHolds, + /// /// The Sync Issues folder. /// @@ -245,14 +266,57 @@ public enum WellKnownFolderName [EwsEnum("conversationhistory")] ConversationHistory, - /// - /// ToDo search folder - /// - [RequiredServerVersion(ExchangeVersion.Exchange2013)] + /// + /// AdminAuditLogs folder + /// + [RequiredServerVersion(ExchangeVersion.Exchange2013)] + [EwsEnum("adminauditlogs")] + AdminAuditLogs, + + /// + /// ToDo search folder + /// + [RequiredServerVersion(ExchangeVersion.Exchange2013)] [EwsEnum("todosearch")] ToDoSearch, - //// Note when you adding new folder id here, please update sources\test\Services\src\ComponentTests\GlobalVersioningControl.cs - //// IsExchange2013Folder method accordingly. - } + /// + /// MyContacts folder + /// + [RequiredServerVersion(ExchangeVersion.Exchange2013)] + [EwsEnum("mycontacts")] + MyContacts, + + /// + /// Directory (GAL) + /// It is not a mailbox folder. It only indicates any GAL operation. + /// + [RequiredServerVersion(ExchangeVersion.Exchange2013_SP1)] + [EwsEnum("directory")] + Directory, + + /// + /// IMContactList folder + /// + [RequiredServerVersion(ExchangeVersion.Exchange2013)] + [EwsEnum("imcontactlist")] + IMContactList, + + /// + /// PeopleConnect folder + /// + [RequiredServerVersion(ExchangeVersion.Exchange2013)] + [EwsEnum("peopleconnect")] + PeopleConnect, + + /// + /// Favorites folder + /// + [RequiredServerVersion(ExchangeVersion.Exchange2013)] + [EwsEnum("favorites")] + Favorites, + + //// Note when you adding new folder id here, please update sources\test\Services\src\ComponentTests\GlobalVersioningControl.cs + //// IsExchange2013Folder method accordingly. + } } \ No newline at end of file diff --git a/Groups/ComplexProperties/RequestedUnifiedGroupsSet.cs b/Groups/ComplexProperties/RequestedUnifiedGroupsSet.cs new file mode 100644 index 00000000..c3bd7332 --- /dev/null +++ b/Groups/ComplexProperties/RequestedUnifiedGroupsSet.cs @@ -0,0 +1,87 @@ +// --------------------------------------------------------------------------- +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// --------------------------------------------------------------------------- + +//----------------------------------------------------------------------- +// Defines the RequestedUnifiedGroupsSet class. +//----------------------------------------------------------------------- +namespace Microsoft.Exchange.WebServices.Data.Groups +{ + /// + /// Defines the RequestedUnifiedGroupsSet class. + /// + public sealed class RequestedUnifiedGroupsSet : ComplexProperty, ISelfValidate, IJsonSerializable + { + /// + /// Initializes a new instance of the class. + /// + public RequestedUnifiedGroupsSet() + { + } + + /// + /// Initializes a new instance of the class. + /// + /// The filterType for the list of groups to be returned + /// The sort type for the list of groups to be returned + /// The sort direction for list of groups to be returned + public RequestedUnifiedGroupsSet( + UnifiedGroupsFilterType filterType, + UnifiedGroupsSortType sortType, + SortDirection sortDirection) + { + this.FilterType = filterType; + this.SortType = sortType; + this.SortDirection = sortDirection; + } + + /// + /// Gets or sets the sort type for the list of groups to be returned + /// + public UnifiedGroupsSortType SortType { get; set; } + + /// + /// Gets or sets the filter Type for the list of groups to be returned + /// + public UnifiedGroupsFilterType FilterType { get; set; } + + /// + /// Gets or sets the Sort Direction for the list of groups to be returned. + /// + public SortDirection SortDirection { get; set; } + + /// + /// Writes to XML. + /// + /// The writer. + /// Name of the XML element. + internal override void WriteToXml(EwsServiceXmlWriter writer, string xmlElementName) + { + writer.WriteStartElement(XmlNamespace.Types, xmlElementName); + writer.WriteElementValue(XmlNamespace.Types, XmlElementNames.SortType, this.SortType.ToString()); + writer.WriteElementValue(XmlNamespace.Types, XmlElementNames.FilterType, this.FilterType.ToString()); + writer.WriteElementValue(XmlNamespace.Types, XmlElementNames.SortDirection, this.SortDirection.ToString()); + + writer.WriteEndElement(); + } + + /// + /// Serializes the property to a Json value. + /// + /// The service. + /// + /// A Json value (either a JsonObject, an array of Json values, or a Json primitive) + /// + internal override object InternalToJson(ExchangeService service) + { + JsonObject jsonProperty = new JsonObject(); + jsonProperty.Add(XmlElementNames.SortType, this.SortType.ToString()); + jsonProperty.Add(XmlElementNames.FilterType, this.FilterType.ToString()); + jsonProperty.Add(XmlElementNames.SortDirection, this.SortDirection.ToString()); + + return jsonProperty; + } + } +} diff --git a/Groups/ComplexProperties/UnifiedGroup.cs b/Groups/ComplexProperties/UnifiedGroup.cs new file mode 100644 index 00000000..2668f2f4 --- /dev/null +++ b/Groups/ComplexProperties/UnifiedGroup.cs @@ -0,0 +1,165 @@ +// --------------------------------------------------------------------------- +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// --------------------------------------------------------------------------- + +//----------------------------------------------------------------------- +// Defines the UnifiedGroup class. +//----------------------------------------------------------------------- +namespace Microsoft.Exchange.WebServices.Data.Groups +{ + using System; + using System.Collections.Generic; + using System.Text; + + /// + /// Represents a UnifiedGroup class. + /// + public class UnifiedGroup : ComplexProperty + { + /// + /// Initializes a new instance of the class. + /// + internal UnifiedGroup() : + base() + { + } + + /// + /// Gets or sets whether this groups is a favorite group + /// + public bool IsFavorite { get; set; } + + /// + /// Gets or sets the ExternalDirectoryObjectId for this group + /// + public string ExternalDirectoryObjectId { get; set; } + + /// + /// Gets or sets the LastVisitedTimeUtc for this group and user + /// + public string LastVisitedTimeUtc { get; set; } + + /// + /// Gets or sets the SmtpAddress associated with this group + /// + public string SmtpAddress { get; set; } + + /// + /// Gets or sets the LegacyDN associated with this group + /// + public string LegacyDN { get; set; } + + /// + /// Gets or sets the MailboxGuid associated with this group + /// + public string MailboxGuid { get; set; } + + /// + /// Gets or sets the DisplayName associated with this group + /// + public string DisplayName { get; set; } + + /// + /// Gets or sets the AccessType associated with this group + /// + public UnifiedGroupAccessType AccessType { get; set; } + + /// + /// Read Conversations from XML. + /// + /// The reader. + /// The xml element to read. + internal override void LoadFromXml(EwsServiceXmlReader reader, string xmlElementName) + { + reader.EnsureCurrentNodeIsStartElement(XmlNamespace.Types, XmlElementNames.UnifiedGroup); + do + { + reader.Read(); + switch (reader.LocalName) + { + case XmlElementNames.SmtpAddress: + this.SmtpAddress = reader.ReadElementValue(); + break; + case XmlElementNames.LegacyDN: + this.LegacyDN = reader.ReadElementValue(); + break; + case XmlElementNames.MailboxGuid: + this.MailboxGuid = reader.ReadElementValue(); + break; + case XmlElementNames.DisplayName: + this.DisplayName = reader.ReadElementValue(); + break; + case XmlElementNames.IsFavorite: + this.IsFavorite = reader.ReadElementValue(); + break; + case XmlElementNames.LastVisitedTimeUtc: + this.LastVisitedTimeUtc = reader.ReadElementValue(); + break; + case XmlElementNames.AccessType: + this.AccessType = (UnifiedGroupAccessType)Enum.Parse(typeof(UnifiedGroupAccessType), reader.ReadElementValue(), false); + break; + case XmlElementNames.ExternalDirectoryObjectId: + this.ExternalDirectoryObjectId = reader.ReadElementValue(); + break; + default: + break; + } + } + while (!reader.IsEndElement(XmlNamespace.Types, XmlElementNames.UnifiedGroup)); + + // Skip end element + reader.EnsureCurrentNodeIsEndElement(XmlNamespace.NotSpecified, XmlElementNames.UnifiedGroup); + reader.Read(); + } + + /// + /// Reads response elements from Json. + /// + /// The response object. + /// The service. + internal override void LoadFromJson(JsonObject responseObject, ExchangeService service) + { + if (responseObject.ContainsKey(XmlElementNames.SmtpAddress)) + { + this.SmtpAddress = responseObject.ReadAsString(XmlElementNames.SmtpAddress); + } + + if (responseObject.ContainsKey(XmlElementNames.LegacyDN)) + { + this.LegacyDN = responseObject.ReadAsString(XmlElementNames.LegacyDN); + } + + if (responseObject.ContainsKey(XmlElementNames.MailboxGuid)) + { + this.MailboxGuid = responseObject.ReadAsString(XmlElementNames.MailboxGuid); + } + + if (responseObject.ContainsKey(XmlElementNames.DisplayName)) + { + this.DisplayName = responseObject.ReadAsString(XmlElementNames.DisplayName); + } + + if (responseObject.ContainsKey(XmlElementNames.IsFavorite)) + { + this.IsFavorite = responseObject.ReadAsBool(XmlElementNames.IsFavorite); + } + + if (responseObject.ContainsKey(XmlElementNames.LastVisitedTimeUtc)) + { + this.LastVisitedTimeUtc = responseObject.ReadAsString(XmlElementNames.LastVisitedTimeUtc); + } + + if (responseObject.ContainsKey(XmlElementNames.AccessType)) + { + this.AccessType = (UnifiedGroupAccessType)Enum.Parse(typeof(UnifiedGroupAccessType), responseObject.ReadAsString(XmlElementNames.AccessType), false); + } + + if (responseObject.ContainsKey(XmlElementNames.ExternalDirectoryObjectId)) + { + this.ExternalDirectoryObjectId = responseObject.ReadAsString(XmlElementNames.ExternalDirectoryObjectId); + } + } + } +} \ No newline at end of file diff --git a/Groups/ComplexProperties/UnifiedGroupIdentity.cs b/Groups/ComplexProperties/UnifiedGroupIdentity.cs new file mode 100644 index 00000000..f53e2d42 --- /dev/null +++ b/Groups/ComplexProperties/UnifiedGroupIdentity.cs @@ -0,0 +1,72 @@ +// --------------------------------------------------------------------------- +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// --------------------------------------------------------------------------- + +//----------------------------------------------------------------------- +// Defines the UnifiedGroupIdentity class. +//----------------------------------------------------------------------- +namespace Microsoft.Exchange.WebServices.Data.Groups +{ + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + + /// + /// Defines the UnifiedGroupIdentity class. + /// + internal sealed class UnifiedGroupIdentity : ComplexProperty, ISelfValidate, IJsonSerializable + { + /// + /// Initializes a new instance of the class + /// + /// The identity type + /// The value assocaited with the identity type + public UnifiedGroupIdentity(UnifiedGroupIdentityType identityType, string value) + { + this.IdentityType = identityType; + this.Value = value; + } + + /// + /// Gets or sets the IdentityType of the UnifiedGroup + /// + public UnifiedGroupIdentityType IdentityType { get; set; } + + /// + /// Gets or sets the value associated with the IdentityType for the UnifiedGroup + /// + public string Value { get; set; } + + /// + /// Writes to XML. + /// + /// The writer. + /// Name of the XML element. + internal override void WriteToXml(EwsServiceXmlWriter writer, string xmlElementName) + { + writer.WriteStartElement(XmlNamespace.Types, xmlElementName); + writer.WriteElementValue(XmlNamespace.Types, XmlElementNames.GroupIdentityType, this.IdentityType.ToString()); + writer.WriteElementValue(XmlNamespace.Types, XmlElementNames.GroupIdentityValue, this.Value); + writer.WriteEndElement(); + } + + /// + /// Serializes the property to a Json value. + /// + /// The service. + /// + /// A Json value (either a JsonObject, an array of Json values, or a Json primitive) + /// + internal override object InternalToJson(ExchangeService service) + { + JsonObject jsonProperty = new JsonObject(); + jsonProperty.Add(XmlElementNames.GroupIdentityType, this.IdentityType.ToString()); + jsonProperty.Add(XmlElementNames.GroupIdentityValue, this.Value); + + return jsonProperty; + } + } +} diff --git a/Groups/ComplexProperties/UnifiedGroupsSet.cs b/Groups/ComplexProperties/UnifiedGroupsSet.cs new file mode 100644 index 00000000..8d7beb33 --- /dev/null +++ b/Groups/ComplexProperties/UnifiedGroupsSet.cs @@ -0,0 +1,128 @@ +// --------------------------------------------------------------------------- +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// --------------------------------------------------------------------------- + +//----------------------------------------------------------------------- +// Defines the UnifiedGroupsSet class. +//----------------------------------------------------------------------- +namespace Microsoft.Exchange.WebServices.Data.Groups +{ + using System; + using System.Collections.Generic; + using System.Text; + + /// + /// Represents a UnifiedGroupsSet + /// + public class UnifiedGroupsSet : ComplexProperty + { + /// + /// The list of unifiedGroups in this set. + /// + private List unifiedGroups = new List(); + + /// + /// Initializes a new instance of the class. + /// + internal UnifiedGroupsSet() : + base() + { + } + + /// + /// Gets or sets the FilterType associated with this set + /// + public UnifiedGroupsFilterType FilterType { get; set; } + + /// + /// Gets or sets the total groups in this set + /// + public int TotalGroups { get; set; } + + /// + /// Gets the Groups contained in this set. + /// + public List Groups + { + get + { + return this.unifiedGroups; + } + } + + /// + /// Read Conversations from XML. + /// + /// The reader. + /// The name of the xml element + internal override void LoadFromXml(EwsServiceXmlReader reader, string xmlElementName) + { + reader.EnsureCurrentNodeIsStartElement(XmlNamespace.Types, XmlElementNames.UnifiedGroupsSet); + + do + { + reader.Read(); + switch (reader.LocalName) + { + case XmlElementNames.FilterType: + this.FilterType = (UnifiedGroupsFilterType)Enum.Parse(typeof(UnifiedGroupsFilterType), reader.ReadElementValue(), false); + break; + case XmlElementNames.TotalGroups: + this.TotalGroups = reader.ReadElementValue(); + break; + case XmlElementNames.GroupsTag: + reader.Read(); + while (reader.IsStartElement(XmlNamespace.Types, XmlElementNames.UnifiedGroup)) + { + UnifiedGroup unifiedGroup = new UnifiedGroup(); + unifiedGroup.LoadFromXml(reader, XmlElementNames.UnifiedGroup); + this.unifiedGroups.Add(unifiedGroup); + } + + // Skip end element. + reader.EnsureCurrentNodeIsEndElement(XmlNamespace.NotSpecified, XmlElementNames.GroupsTag); + reader.Read(); + break; + default: + break; + } + } + while (!reader.IsEndElement(XmlNamespace.Types, XmlElementNames.UnifiedGroupsSet)); + + // Skip end element + reader.EnsureCurrentNodeIsEndElement(XmlNamespace.Types, XmlElementNames.UnifiedGroupsSet); + reader.Read(); + } + + /// + /// Reads response elements from Json. + /// + /// The response object. + /// The service. + internal override void LoadFromJson(JsonObject responseObject, ExchangeService service) + { + if (responseObject.ContainsKey(XmlElementNames.FilterType)) + { + this.FilterType = (UnifiedGroupsFilterType)Enum.Parse(typeof(UnifiedGroupsFilterType), responseObject.ReadAsString(XmlElementNames.FilterType), false); + } + + if (responseObject.ContainsKey(XmlElementNames.TotalGroups)) + { + this.TotalGroups = responseObject.ReadAsInt(XmlElementNames.TotalGroups); + } + + if (responseObject.ContainsKey(XmlElementNames.GroupsTag)) + { + foreach (object unifiedGroup in responseObject.ReadAsArray(XmlElementNames.UnifiedGroup)) + { + JsonObject jsonUnifiedGroup = unifiedGroup as JsonObject; + UnifiedGroup unifiedGroupResponse = new UnifiedGroup(); + unifiedGroupResponse.LoadFromJson(jsonUnifiedGroup, service); + this.unifiedGroups.Add(unifiedGroupResponse); + } + } + } + } +} \ No newline at end of file diff --git a/Groups/Requests/GetUnifiedGroupUnseenCountRequest.cs b/Groups/Requests/GetUnifiedGroupUnseenCountRequest.cs new file mode 100644 index 00000000..5600946e --- /dev/null +++ b/Groups/Requests/GetUnifiedGroupUnseenCountRequest.cs @@ -0,0 +1,134 @@ +// --------------------------------------------------------------------------- +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// --------------------------------------------------------------------------- + +//----------------------------------------------------------------------- +// Defines the GetUnifiedGroupUnseenCountRequest class. +//----------------------------------------------------------------------- + +namespace Microsoft.Exchange.WebServices.Data.Groups +{ + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + + /// + /// Represents a request to the GetUnifiedGroupUnseenCount operation. + /// + internal sealed class GetUnifiedGroupUnseenCountRequest : SimpleServiceRequestBase, IJsonSerializable + { + /// + /// The last visited time utc for the group + /// + private readonly DateTime lastVisitedTimeUtc; + + /// + /// The identify type associated with the group + /// + private readonly UnifiedGroupIdentityType identityType; + + /// + /// The value of identity associated with the group + /// + private readonly string identityValue; + + /// + /// Initializes a new instance of the class. + /// + /// The service. + /// The last visited time utc for the group + /// The identity type for the group + /// The value associated with the identify type for the group + internal GetUnifiedGroupUnseenCountRequest( + ExchangeService service, + DateTime lastVisitedTimeUtc, + UnifiedGroupIdentityType identityType, + string value) : base(service) + { + this.lastVisitedTimeUtc = lastVisitedTimeUtc; + this.identityType = identityType; + this.identityValue = value; + } + + /// + /// Gets the name of the response XML element. + /// + /// XML element name. + internal override string GetResponseXmlElementName() + { + return XmlElementNames.GetUnifiedGroupUnseenCountResponseMessage; + } + + /// + /// Gets the name of the XML element. + /// + /// XML element name. + internal override string GetXmlElementName() + { + return XmlElementNames.GetUnifiedGroupUnseenCount; + } + + /// + /// Parses the response. + /// + /// The reader. + /// Response object. + internal override object ParseResponse(EwsServiceXmlReader reader) + { + GetUnifiedGroupUnseenCountResponse response = new GetUnifiedGroupUnseenCountResponse(); + response.LoadFromXml(reader, GetResponseXmlElementName()); + return response; + } + + /// + /// Writes XML elements. + /// + /// The writer. + internal override void WriteElementsToXml(EwsServiceXmlWriter writer) + { + UnifiedGroupIdentity groupIdentity = new UnifiedGroupIdentity(this.identityType, this.identityValue); + + groupIdentity.WriteToXml(writer, XmlElementNames.GroupIdentity); + writer.WriteElementValue(XmlNamespace.Messages, XmlElementNames.LastVisitedTimeUtc, this.lastVisitedTimeUtc.ToString("yyyy-MM-ddTHH:mm:ss.fffffffZ")); + } + + /// + /// Gets the request version. + /// + /// Earliest Exchange version in which this request is supported. + internal override ExchangeVersion GetMinimumRequiredServerVersion() + { + return ExchangeVersion.Exchange2013_SP1; + } + + /// + /// Executes this request. + /// + /// Service response. + internal GetUnifiedGroupUnseenCountResponse Execute() + { + return (GetUnifiedGroupUnseenCountResponse)this.InternalExecute(); + } + + /// + /// Creates a JSON representation of this object. + /// + /// The service. + /// + /// A Json value (either a JsonObject, an array of Json values, or a Json primitive) + /// + object IJsonSerializable.ToJson(ExchangeService service) + { + JsonObject jsonRequest = new JsonObject(); + + UnifiedGroupIdentity groupIdentity = new UnifiedGroupIdentity(this.identityType, this.identityValue); + + jsonRequest.Add(XmlElementNames.GroupIdentity, groupIdentity.InternalToJson(service)); + jsonRequest.Add(XmlElementNames.LastVisitedTimeUtc, this.lastVisitedTimeUtc.ToString()); + return jsonRequest; + } + } +} diff --git a/Groups/Requests/GetUserUnifiedGroupsRequest.cs b/Groups/Requests/GetUserUnifiedGroupsRequest.cs new file mode 100644 index 00000000..7e448ce2 --- /dev/null +++ b/Groups/Requests/GetUserUnifiedGroupsRequest.cs @@ -0,0 +1,135 @@ +// --------------------------------------------------------------------------- +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// --------------------------------------------------------------------------- + +//----------------------------------------------------------------------- +// Defines the GetUserUnifiedGroupsRequest class. +//----------------------------------------------------------------------- +namespace Microsoft.Exchange.WebServices.Data.Groups +{ + using System; + using System.Collections.Generic; + using System.Text; + using Microsoft.Exchange.WebServices.Data.Groups; + + /// + /// Represents a request to a GetUserUnifiedGroupsRequest operation + /// + internal sealed class GetUserUnifiedGroupsRequest : SimpleServiceRequestBase, IJsonSerializable + { + /// + /// Initializes a new instance of the class. + /// + /// The service. + internal GetUserUnifiedGroupsRequest(ExchangeService service) : base(service) + { + } + + /// + /// Gets or sets the RequestedUnifiedGroupsSet + /// + public IEnumerable RequestedUnifiedGroupsSets { get; set; } + + /// + /// Gets or sets the UserSmptAddress + /// + public string UserSmtpAddress { get; set; } + + /// + /// Gets the name of the response XML element. + /// + /// XML element name. + internal override string GetResponseXmlElementName() + { + return XmlElementNames.GetUserUnifiedGroupsResponseMessage; + } + + /// + /// Gets the name of the XML element. + /// + /// XML element name. + internal override string GetXmlElementName() + { + return XmlElementNames.GetUserUnifiedGroups; + } + + /// + /// Parses the response. + /// + /// The reader. + /// Response object. + internal override object ParseResponse(EwsServiceXmlReader reader) + { + GetUserUnifiedGroupsResponse response = new GetUserUnifiedGroupsResponse(); + response.LoadFromXml(reader, GetResponseXmlElementName()); + return response; + } + + /// + /// Writes XML elements. + /// + /// The writer. + internal override void WriteElementsToXml(EwsServiceXmlWriter writer) + { + writer.WriteStartElement(XmlNamespace.Messages, XmlElementNames.RequestedGroupsSets); + + if (this.RequestedUnifiedGroupsSets != null) + { + this.RequestedUnifiedGroupsSets.ForEach((unifiedGroupsSet) => unifiedGroupsSet.WriteToXml(writer, XmlElementNames.RequestedUnifiedGroupsSetItem)); + } + + writer.WriteEndElement(); + + if (!string.IsNullOrEmpty(this.UserSmtpAddress)) + { + writer.WriteElementValue(XmlNamespace.NotSpecified, XmlElementNames.UserSmtpAddress, this.UserSmtpAddress); + } + } + + /// + /// Gets the request version. + /// + /// Earliest Exchange version in which this request is supported. + internal override ExchangeVersion GetMinimumRequiredServerVersion() + { + return ExchangeVersion.Exchange2013_SP1; + } + + /// + /// Executes this request. + /// + /// Service response. + internal GetUserUnifiedGroupsResponse Execute() + { + return (GetUserUnifiedGroupsResponse)this.InternalExecute(); + } + + /// + /// Creates a JSON representation of this object. + /// + /// The service. + /// + /// A Json value (either a JsonObject, an array of Json values, or a Json primitive) + /// + object IJsonSerializable.ToJson(ExchangeService service) + { + JsonObject jsonRequest = new JsonObject(); + + List jsonPropertyCollection = new List(); + if (this.RequestedUnifiedGroupsSets != null) + { + this.RequestedUnifiedGroupsSets.ForEach((unifiedGroupsSet) => jsonPropertyCollection.Add(unifiedGroupsSet.InternalToJson(service))); + jsonRequest.Add(XmlElementNames.RequestedGroupsSets, jsonPropertyCollection.ToArray()); + } + + if (!string.IsNullOrEmpty(this.UserSmtpAddress)) + { + jsonRequest.Add(XmlElementNames.SmtpAddress, this.UserSmtpAddress); + } + + return jsonRequest; + } + } +} \ No newline at end of file diff --git a/Groups/Responses/GetUnifiedGroupUnseenCountResponse.cs b/Groups/Responses/GetUnifiedGroupUnseenCountResponse.cs new file mode 100644 index 00000000..79d32e07 --- /dev/null +++ b/Groups/Responses/GetUnifiedGroupUnseenCountResponse.cs @@ -0,0 +1,58 @@ +// --------------------------------------------------------------------------- +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// --------------------------------------------------------------------------- + +//----------------------------------------------------------------------- +// Defines the GetUnifiedGroupUnseenCountResponse class. +//----------------------------------------------------------------------- +namespace Microsoft.Exchange.WebServices.Data.Groups +{ + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + + /// + /// Represents a response to the GetUnifiedGroupUnseenCount operation + /// + internal sealed class GetUnifiedGroupUnseenCountResponse : ServiceResponse + { + /// + /// Initializes a new instance of the class. + /// + internal GetUnifiedGroupUnseenCountResponse() : + base() + { + } + + /// + /// Gets or sets the unseen count + /// + public int UnseenCount { get; set; } + + /// + /// Read response elements from XML. + /// + /// The reader. + internal override void ReadElementsFromXml(EwsServiceXmlReader reader) + { + base.ReadElementsFromXml(reader); + this.UnseenCount = reader.ReadElementValue(XmlNamespace.NotSpecified, XmlElementNames.UnseenCount); + } + + /// + /// Reads response elements from Json. + /// + /// The response object. + /// The service. + internal override void ReadElementsFromJson(JsonObject responseObject, ExchangeService service) + { + if (responseObject.ContainsKey(XmlElementNames.UnseenCount)) + { + this.UnseenCount = responseObject.ReadAsInt(XmlElementNames.UnseenCount); + } + } + } +} diff --git a/Groups/Responses/GetUserUnifiedGroupsResponse.cs b/Groups/Responses/GetUserUnifiedGroupsResponse.cs new file mode 100644 index 00000000..1657f690 --- /dev/null +++ b/Groups/Responses/GetUserUnifiedGroupsResponse.cs @@ -0,0 +1,95 @@ +// --------------------------------------------------------------------------- +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// --------------------------------------------------------------------------- + +//----------------------------------------------------------------------- +// Defines the GetUserUnifiedGroupsResponse class. +//----------------------------------------------------------------------- +namespace Microsoft.Exchange.WebServices.Data.Groups +{ + using System; + using System.Collections.Generic; + using System.Collections.ObjectModel; + using System.Text; + + /// + /// Represents a response to a GetUserUnifiedGroupsResponse operation + /// + internal sealed class GetUserUnifiedGroupsResponse : ServiceResponse + { + /// + /// The UnifiedGroups Sets associated with this response + /// + private Collection groupsSets = new Collection(); + + /// + /// Initializes a new instance of the class. + /// + internal GetUserUnifiedGroupsResponse() : + base() + { + } + + /// + /// Gets or sets the UnifiedGroupsSet associated with the response + /// + public Collection GroupsSets + { + get + { + return this.groupsSets; + } + } + + /// + /// Read Conversations from XML. + /// + /// The reader. + internal override void ReadElementsFromXml(EwsServiceXmlReader reader) + { + this.groupsSets.Clear(); + base.ReadElementsFromXml(reader); + + reader.ReadStartElement(XmlNamespace.Messages, XmlElementNames.GroupsSets); + + if (!reader.IsEmptyElement) + { + reader.Read(); + while (reader.IsStartElement(XmlNamespace.Types, XmlElementNames.UnifiedGroupsSet)) + { + UnifiedGroupsSet unifiedGroupsSet = new UnifiedGroupsSet(); + unifiedGroupsSet.LoadFromXml(reader, XmlElementNames.UnifiedGroupsSet); + this.groupsSets.Add(unifiedGroupsSet); + } + + // Skip end element GroupsSets + reader.EnsureCurrentNodeIsEndElement(XmlNamespace.NotSpecified, XmlElementNames.GroupsSets); + reader.Read(); + } + } + + /// + /// Reads response elements from Json. + /// + /// The response object. + /// The service. + internal override void ReadElementsFromJson(JsonObject responseObject, ExchangeService service) + { + this.groupsSets.Clear(); + base.ReadElementsFromJson(responseObject, service); + + if (responseObject.ContainsKey(XmlElementNames.GroupsSets)) + { + foreach (object unifiedGroupsSet in responseObject.ReadAsArray(XmlElementNames.UnifiedGroupsSet)) + { + JsonObject jsonUnifiedGroupsSet = unifiedGroupsSet as JsonObject; + UnifiedGroupsSet unifiedGroupsSetResponse = new UnifiedGroupsSet(); + unifiedGroupsSetResponse.LoadFromJson(jsonUnifiedGroupsSet, service); + this.groupsSets.Add(unifiedGroupsSetResponse); + } + } + } + } +} \ No newline at end of file diff --git a/Microsoft.Exchange.WebServices.Data.csproj b/Microsoft.Exchange.WebServices.Data.csproj index 0d924255..9feffa72 100644 --- a/Microsoft.Exchange.WebServices.Data.csproj +++ b/Microsoft.Exchange.WebServices.Data.csproj @@ -61,12 +61,32 @@ + + + + + + + + + + + + + + + + + + + + @@ -100,6 +120,10 @@ + + + + @@ -141,6 +165,7 @@ + @@ -214,6 +239,7 @@ + @@ -262,6 +288,7 @@ + @@ -354,7 +381,6 @@ - @@ -386,17 +412,19 @@ - + + + @@ -499,6 +527,7 @@ + @@ -571,6 +600,8 @@ + + @@ -658,7 +689,6 @@ - @@ -675,6 +705,7 @@ + @@ -771,12 +802,14 @@ + + @@ -817,14 +850,6 @@ - - - Designer - - - Designer - -