The Exchange 2010 SP2 Web Services SDK was released in October but Exchange 2010 SP2 was only recently made available for download earlier this month. With the update to the SDK, there's the common section detailing What's New in the SDK. While this information is very helpful, I felt the need to aggregate and summarize what's there so that I could get a better understanding of the changes.
For the benefit of the rest of the world, I've shared my notes below...
New Exchange2010_SP2 RequestServerVersion value. Obviously, there's a new schema version value which must be requested to take advantage of the changes outlined below.
ConvertId, GetUserOofSettings, SetUserOofSettings, and GetUserAvailability now support impersonation. GetUserOofSettings and SetUserOofSettings support for impersonation might have been added in a previous rollup update to Exchange 2010 SP1 but ConvertId and GetUserAvailability support for impersonation is new to SP2.
GetPasswordExpirationDate operation added. Pass an email address and get back a date indicating when the user's current password will expire.
FindItem and GetItem get a new SOAP header, DateTimePrecision. This allows you to request that you would like the millisecond values returned in DateTime property values. By default, EWS does not return milliseconds with DateTime values - it always returns zeroed out milliseconds. Unless you really need millisecond precision in some use case, I wouldn't recommend using this level of precision.
StoreEntryId element added to Item schema. This new schema property maps to PidTagStoreEntryId and could be used for interoperability with MAPI code. It could also be used to determine which items came from the same mailbox.
New elements added to the contacts schema:
IsArchive added to AlternateIdType. Enables support for ConvertId with archive mailboxes.
NoForward added to DeliverMeetingRequestsType. This means that meeting items will NOT be forwarded to the delegate.
ErrorAttachmentNestLevelLimitExceeded error code added. Error thrown if an item has attachments nested one past the allowed max for EWS (currently this limit is 10).
ContactDataShape added to ResolveNames. Same type as the shapes used in FindItem, GetItem, etc. - AllProperties, Default, IdOnly. Only affects the ContactData returned so if ReturnFullContactData is set to false then this element does nothing. IdOnly returns only the mailbox data and DirectoryId.
IsAssociated added to the UploadItemType. Enables uploading streams to the associated contents of a folder.
I recently found a bug in the December 2011 Release of EWSEditor and just checked in and released an updated build to EWSEditor to fix it. Here are my bug notes from the check in:
“…Bug in ValidationCallbackHelper.CertificateValidationCallBack caused certificate validation to fail always - unless the override validation setting was turned on. Instead, ValidationCallbackHelper.CertificateValidationCallBack now looks for SSL policy errors and returns true if there are none. If there are errors and override is not set then it will return false and output the error code in the debug log…”
You’ll notice that the build’s revision number is actually lower than the previous December 2011 release – please ignore that, 1.7.1.20840 is the latest release. This should be fixed going forward, sorry for the confusion.
Download the December 2011 Update of EWSEditor HERE.
Over a year has gone by since a public update to EWSEditor on the MSDN Code Gallery but it’s not been forgotten! The availability and popularity of Office 365 and Exchange Online make Exchange Web Services (and thus EWSEditor) even more relevant today as EWS becomes the primary mailbox access API for Exchange. Many of the folks I talk to these days are in the middle of redesigning their products to use EWS instead of MAPI.
When I first created EWSEditor, I was working on the support side of the business and thus my goal was to create a tool to help debug Exchange or fix client code. Now that I work on the consulting side of the business and talk more about best practices and architecture, I’m feeling the need to rework a lot of this code to “practice what I preach”. While this release doesn’t contain a huge amount of best practices refactoring, I plan to address this in the near future with additional updates to EWSEditor. This release is about getting the codebase healthier and to put some things in place to make it easier to add features in the future.
The biggest change of course is that EWSEditor has moved to CodePlex. Here is a summary of the other major changes and new features in the December 2011 update to EWSEditor….
While the Exchange ActiveSync protocol documentation (MS-AS* documents under the links below) has long been published on MSDN under the Open Specifications for Exchange Server Protocols, there has never been an accompanying set of “how to” documentation or sample implementations available. And I have had some insight into the challenges third party developers face, trying to turn the protocol specifications into an Exchange ActiveSync implementation. For that reason, I’m proud to have been a writer for some of our follow up implementation guidance for Exchange ActiveSync. You’ll find it in the Exchange Server section of MSDN under the label Exchange Server Interoperability Guidance which today is all about Exchange ActiveSync.
To wet your appetite, here are the list of documents published as of October 2011…
Implementing an Exchange ActiveSync client: provisioning by Jason Johnston Provisioning, policies, remote wipe, and the Allow/Block/Quarantine list in Exchange ActiveSync by Matt Stehle Working with the RecurrencePattern structure in [MS-OXOCAL] by Robert Knight Working with Meeting Requests in Exchange ActiveSync by Katarzyna Puchala Working with Meeting Responses in Exchange ActiveSync by Katarzyna Puchala Implementing an Exchange ActiveSync client: the transport mechanism by Jason Johnston Autodiscover for Exchange ActiveSync developers by Matt Stehle Exploring the Microsoft Exchange Server Open Specifications by Kim Brandl
Implementing an Exchange ActiveSync client: provisioning by Jason Johnston
Provisioning, policies, remote wipe, and the Allow/Block/Quarantine list in Exchange ActiveSync by Matt Stehle
Working with the RecurrencePattern structure in [MS-OXOCAL] by Robert Knight
Working with Meeting Requests in Exchange ActiveSync by Katarzyna Puchala
Working with Meeting Responses in Exchange ActiveSync by Katarzyna Puchala
Implementing an Exchange ActiveSync client: the transport mechanism by Jason Johnston
Autodiscover for Exchange ActiveSync developers by Matt Stehle
Exploring the Microsoft Exchange Server Open Specifications by Kim Brandl
I’ve been asked this several times and the question usually goes something like this…
Hey Matt, I’m trying to follow the instructions on MSDN for setting up ApplicationImpersonation in Exchange 2010 for my service account in Exchange Online in Office 365 but New-ManagementRoleAssignment isn’t available – what gives?
…To be honest, I haven’t looked too deep into why that particular cmdlet doesn’t work in Office 365. The reason I haven’t looked too deep into this is that regardless of the availability of this cmdlet, I prefer to recommend a different, more RBAC-centric approach.
Using New-RoleGroup instead, you can still assign the permissions in one line but instead of simply creating an assignment you define and name a role group. This makes management and identification of the accounts and permissions tied to your solution a lot easier. Take a look at the following command…
New-RoleGroup -Name "Contoso Service Accounts" -Roles ApplicationImpersonation –Members ContosoServiceAccountName
First, this cmdlet creates a role group with an identifiable name, “Contoso Service Accounts”. Then the second portion assigns roles to that group which in this case only includes ApplicationImpersonation but could include more. Lastly, an account is added as a member of the RoleGroup to give it all the permissions associated with it. This would be helpful in the case where you need multiple service accounts to handle your application load – you simply add/remove service accounts as members to this group as needed for quick provisioning. This also makes it easy for administrators to understand which accounts are related to your product and what they can do.
There were several different announcements around Office 365 this past week. Most importantly, the Office 365 public beta is wide open…
Office 365 Beta The Office 365 team announced on their blog last week that Office 365 has moved into a full public beta. As a developer, this is a super easy way to get a test Exchange, SharePoint, and Lync environment. From an Exchange perspective, be sure to try out and understand the different plans (small business, enterprise, and kiosk) that offer different types of mailbox access and size.
In another post linked to from this announcement, the Office 365 team is starting a series specifically about helping “small business stand tall”. Exchange, SharePoint, and Lync are the “killer apps” for the enterprise. Now with Office 365, they become accessible in an instant to even a one-person operation. This means, as an ISV, you’ll have entirely new markets for your products that integrate with these services and these new customers will have new demands on pricing and service delivery…
Office 365 Developer Training Kit To help ISVs develop applications for Office 365, the ISV team announced the Developer Training Kit for Office 365. Check it out…
“…The kit includes 7 sessions, over 10 hours of video, and 16 labs as both an offline training kit as well as an online training course on MSDN. Training Units in the Office 365 Developer Kit The Office 365 Developer Training Kit includes the following training units: Developing in the Cloud with Office 365 Developing for SharePoint Online with Sandbox Solutions Building Workflow Solutions for SharePoint Online Developing SharePoint Online Solutions with the Client Object Model. Leveraging Excel and Access Services in SharePoint Online Developing Communication Solutions for Lync Online Developing Messaging Solutions for Exchange Online…”
“…The kit includes 7 sessions, over 10 hours of video, and 16 labs as both an offline training kit as well as an online training course on MSDN.
The Office 365 Developer Training Kit includes the following training units:
Office 365 Marketplace To help ISVs and partners publish their applications and services we also announced an Office 365 Marketplace this week…
“You can join others whose applications are listed in the Office 365 Marketplace. It is the online destination, based on the Pinpoint platform, for customers, partners, and Microsoft field to find the applications, solutions, and services that you offer supporting Office 365… …Who is Marketplace For? Office 365 customers to find high-quality partners/apps for Office 365 Partners/solutions approved by Microsoft Customers Ratings & Reviews Rich search/browse capabilities Microsoft partners to publicize their products and services to customers Customer leads Promotion as ‘best partners’ Customer site analytics Microsoft field to locate and promote local partners and solutions Localized User experience Sub ownership on partner nomination and approval, ‘featured partners’…”
“You can join others whose applications are listed in the Office 365 Marketplace. It is the online destination, based on the Pinpoint platform, for customers, partners, and Microsoft field to find the applications, solutions, and services that you offer supporting Office 365…
…Who is Marketplace For?
Office 365 customers to find high-quality partners/apps for Office 365
Microsoft partners to publicize their products and services to customers
Microsoft field to locate and promote local partners and solutions
This roundup is dominated by the Exchange ActiveSync Logo Program announcement as I still have a very Exchange-centric view of the “world”.
Exchange ActiveSync Logo Program The Exchange team announced on their blog this week what they call the “Exchange ActiveSync Logo Program”.
“…You’ve told us that one of your top concerns is the increasing diversity of mobile devices that employees use to access your company resources. While many of these devices use Exchange ActiveSync (EAS) for mobile email, we all know that not all EAS clients are created equal. Exchange ActiveSync policies and features aren’t consistently implemented by licensees, so it can be challenging to find out what’s supported on each device… …Today, we launched the Exchange ActiveSync Logo Program to establish baseline for EAS functionality in mobile email devices . The program is designed for device manufacturers that license the EAS protocol from Microsoft for use in mobile email clients that connect to Exchange… …All Windows Phone 7 and Windows Phone 6.5 devices are compliant, as are Nokia devices running Mail for Exchange 3.0.50, including the Nokia E7, and Apple devices running iOS 4, including the iPhone 4, iPhone 3GS, iPad and iPad 2… …Over time, the program will evolve to require additional features and management policies…”
“…You’ve told us that one of your top concerns is the increasing diversity of mobile devices that employees use to access your company resources. While many of these devices use Exchange ActiveSync (EAS) for mobile email, we all know that not all EAS clients are created equal. Exchange ActiveSync policies and features aren’t consistently implemented by licensees, so it can be challenging to find out what’s supported on each device…
…Today, we launched the Exchange ActiveSync Logo Program to establish baseline for EAS functionality in mobile email devices . The program is designed for device manufacturers that license the EAS protocol from Microsoft for use in mobile email clients that connect to Exchange…
…All Windows Phone 7 and Windows Phone 6.5 devices are compliant, as are Nokia devices running Mail for Exchange 3.0.50, including the Nokia E7, and Apple devices running iOS 4, including the iPhone 4, iPhone 3GS, iPad and iPad 2…
…Over time, the program will evolve to require additional features and management policies…”
A parallel announcement with some additional information and quotes from Nokia was made on the Unified Communications Group team blog as well.
“…In the Exchange ActiveSync Logo program, participants agree to implement a predefined set of EAS policies (or more). You can get a full detailed list of the defined features here. Two of the key features required by the Exchange ActiveSync program are remote wipe and support for Allow/Block/Quarantine (ABQ) strings. Remote wipe gives IT administrators the ability to erase data on a device that has been compromised or lost, so company and personal information isn’t at risk. ABQ strings enable IT admins to identify the mobile device type and model trying to connect with Exchange 2010 in order to validate and enforce appropriate access policies. This means no more worrying about rogue or unsupported devices accessing the network…”
There was also information posted to TechNet, detailing what devices meet the bar today and what the requirements are.
“…The table below lists the FY11 requirements for participation in the EAS Logo Program. Exchange Partner Marketing plans to add additional functional requirements over time to address market needs… …Program Requirements: Must be current EAS licensee Use EAS v14 or later Direct Push email, contacts & calendar Accept, Decline & Tentatively Accept meetings Rich formatted email (HTML) Reply/Forward state on email GAL Lookup Autodiscover ABQ strings provided: device type and device model Remote Wipe Password Required Minimum Password Length Timeout without User Input Number of Failed Attempts…”
“…The table below lists the FY11 requirements for participation in the EAS Logo Program. Exchange Partner Marketing plans to add additional functional requirements over time to address market needs…
…Program Requirements:
As stated, the goal here is to try identify baseline feature set that the Exchange team feels any EAS device should meet and then give IT Pros the ability to quantify the devices that meet that baseline. This also gives EAS licensees implementing mobile devices a clear target feature set to prioritize in their mobile email client development planning.
Windows Azure PaaS vs. IaaS With everyone talking about “cloud” and various different “*aaS” models, it can hard to cut through and see what is really going on. For ISVs or developers in general, understanding the patterns and paths to different models is important. “Planky” gives a great overview of the difference between platform as a service (PaaS) and infrastructure as a service (IaaS) and where PaaS with application virtualization fits in. The key point for me is at the end of his post:
“…PaaS applications are more difficult to deploy because the apps have to be specifically engineered to work as scale-out, multi-instance entities. IaaS applications can “just be”. So the movement of an existing application to IaaS is simpler… …It’s a sort of trade-off. You trade ease-of-deployment, but it bites later when you are wedded to the management of the OS and everything in the stack above it, for the life of that application… …With PaaS, there is initial difficulty in migrating an application to be a good PaaS citizen and that is a one-time piece of work. Once done, you no longer worry about the management of the OS, the middleware, the runtimes etc.”
“…PaaS applications are more difficult to deploy because the apps have to be specifically engineered to work as scale-out, multi-instance entities. IaaS applications can “just be”. So the movement of an existing application to IaaS is simpler…
…It’s a sort of trade-off. You trade ease-of-deployment, but it bites later when you are wedded to the management of the OS and everything in the stack above it, for the life of that application…
…With PaaS, there is initial difficulty in migrating an application to be a good PaaS citizen and that is a one-time piece of work. Once done, you no longer worry about the management of the OS, the middleware, the runtimes etc.”
In summary this resonates with me as a short-view (IaaS) and long-view (PaaS) approach. IaaS allows you to move your application from on-premises to some kind of hosted service infrastructure with minimal code changes – essentially the hardware moves from your datacenter to someone else’s and your code stays the same. So while you get to “the cloud” quicker, you still have to manage the platform stack between your application and the hosted hardware. PaaS moves you up a level and eliminates any need to manage the platform stack – all you care about is your application code. However, PaaS is a rewrite (or at least extensive refactoring) of your application.
Windows Azure Helps Power eBay's iPad Marketplace This is a great example of two key points about Windows Azure. The first being identifying projects to experiment with Azure – a new project evolving new code that may have a great need for scale if it takes off makes a great Azure project. The rewrite for PaaS is not a huge concern because you are writing new code anyway and the great advantage of writing good apps for PaaS (especially in Azure) is the ability to scale out quickly demand spikes at some point. The second key point is that Windows Azure is not only about .NET – eBay uses Java, not .NET – Azure also has support for PHP, Ruby, Python, C++. Read more about interoperability here.
Look at the Windows Azure evidence site for more case studies…
The Exchange Developer Roadmap has been discussed by more authoritative sources before leading up to the release of Exchange 2010. I’d like to revisit this roadmap and take it from where Jason left off, going forward into Exchange Online in Office 365. For enterprise customers this is important to understand – if you are upgrading from Exchange 2003 to 2010 or Online then many applications that touch Exchange today will require an upgrade to the “modern” Exchange APIs. For an ISV looking at these API sets will help you understand what APIs you need to leverage to support the versions of Exchange you’re targeting.
When I talk about this roadmap or evolution of Exchange development, I typically do so by grouping the APIs in six categories:
Let’s take a high-level walk through these groups from Exchange 2003 to Exchange 2010 and see how the APIs evolve over time and how they are different between on-premises and online…
Exchange 2003:
Exchange 2007:
Exchange Online (BPOS):
Exchange 2010:
Exchange Online (Office 365):
I’ll get into more detail about this evolution with a discussion of online service descriptions in the coming weeks. I’ll also talk about how the features and APIs available in each version affect product planning for ISVs that want to support Exchange Online as well as Exchange on-premises.
The focus of this week’s roundup in on Microsoft Online Services. Typically when you hear about “the cloud” in a Microsoft developer discussion someone is getting ready to talk about Azure and its various services. However, in my world I think that Office 365 and BPOS are just as important in this discussion. If for nothing else then they offer a different path to get developers to the cloud.
Changing Patterns of Exchange Integration There’s no doubt that BPOS and now Office 365 changed the game not only for IT admins and end-users but for the ISVs that integrate with Exchange. On the Office 365 blog last month we announced that RIM will have a peripheral cloud-based service of their own for Blackberry customers to connect to Exchange Online. This is a significant example of how IT moving core services like Exchange to the cloud is going to change the way developers integrate with them.
Online Service Descriptions We post service descriptions that go into great detail of all the end-user, administrative, and developer features of the different services that make up a particular offering. Later today I will start publishing a series of posts that look deeper into these service descriptions for Exchange Online to extract key information for Exchange developers. The three major service types are Standard, Dedicated, and Federal and we’ll look at each one. For now, here are the links to the service descriptions:
Evolution of Exchange Development Using the service descriptions above my goal over the next few posts will be to illustrate the evolution of Exchange development from Exchange 2003 to 2010 and into Exchange Online with Office 365. Whether because of a phased migration or business requirements, expect to see many hybrid deployments of Exchange in the near future with some mailboxes online and some on-premises. Understanding the API set available in Exchange Online and figuring out how to build applications that can integrate not only with Exchange on-premises but Exchange Online is very important going forward.
Windows Azure Jump Start The changing pattern for developers who work with Exchange is not only going to be the APIs used to connect to Exchange Online but the platforms they use for their applications. If your customer moves all his or her mailboxes out of their datacenter to the cloud you can bet they ask you about getting your application servers out too. Whether the choice is to use Windows Azure or not, understanding the platforms and paradigms of cloud computing are an essential skill. If you are interesting in Windows Azure, I just finished a great series of videos up on Channel 9 called the Windows Azure Jump Start which I highly recommend for doing just that – jump starting your understanding of Azure and its various services.
First of all this is NOT and April fools joke! This blog actually isn’t dead! Recently (almost a year ago) I switched out of my role in support to a consulting based role working with ISV partners. A bulk of my work is still Exchange and Exchange Online related but a good portion of it is also other things like Windows Phone, Azure, SharePoint, and Lync. Because of that the topics on this blog may start going outside the bounds of Exchange and Outlook development but that’s okay, right?
Weekly Roundup? The plan here is to aggregate interesting topics and articles I’ve come across in the week of work. I’m aiming to do this most Fridays in series I’ll call the Weekly Roundup. Mostly short descriptions with links - easy for me and to the point for you.
Microsoft Exchange RPC Extractor Whether you are doing protocol level work with MAPI, using either Outlook or Exchange’s MAPI provider in a service application, or even writing add-ins for Outlook this tool can be very useful for debugging issues or even learning about how your application communicates with Exchange. From the announcement post on the Exchange API-spotting blog:
The Exchange Interoperability Team is excited to announce the initial release of the Microsoft Exchange RPC Extractor (RPX). RPX is a command-line tool that can parse network captures and interpret remote procedure calls (RPCs) made from a client to Microsoft Exchange Server. RPX uses the information provided in the Microsoft Exchange Server protocol documentation to parse RPCs, remote operations (ROPs) and the parameters for each ROP.
Programming with Exchange Online The Exchange team launched an MSDN landing page devoted to development against Exchange Online as part of Office 365 and BPOS. This is a very important topic and it is important to understand what is and isn’t possible (come back next week for more detail on that topic). The landing page is pretty barren right now outside of a link to one article about using EWS with Exchange Online. Come back to their landing page soon for a series of content on Exchange Online.
Exchange Online vs. Exchange 2010 Again more discussion about Exchange Online, specifically comparing features between Exchange Online in Office 365 (which is based on Exchange 2010) and Exchange 2010 running on-premises. The Office 365 blog has a post from Jon Orton discussing some of the differences at a high level. An important link in the article is to the Office 365 Exchange Online Beta Service Description. This is important to read and I will highlight some key parts in a post next week.
Migrating from an Exchange Client Extension (ECE) to an Outlook add-in On the Outlook integration side the move from Exchange on-premises to Exchange Online thankfully has little impact. However, moving from Outlook 2007 to Outlook 2010 is a different story for some folks. In Outlook 2010 we cut support for the old Exchange Client Extension (ECE) interfaces completely. Steve has a follow up post with some great information on how to manage the transition from ECEs to Outlook add-ins.
Outlook, MAPI, and Virtualization Some great information here if you have a MAPI application utilizing Outlook’s provider and your customer is virtualizing Office applications using App-V and Click-to-Run delivery mechanism. The Outlook team has a post describing how to check the registry to see if Outlook is virtualized. If you need to use MFCMAPI on a machine with virtualized Outlook, read Steve’s blog post for tricking it into running along side Outlook in the virtualized environment.
April 1st 2011 Release of MFCMAPI => MFCMAPI.NET Not much more to say just get to Steve’s blog and check out the amazing update for his MFCMAPI tool.
That’s about all for now…
Understanding throttling policies, their default values, and how they are applied is a key in Exchange Online where they are used to protect connectivity to the online mailboxes. These policies can be applied per user – so a service account can be granted a unique policy apart from other mailbox users in your organization. The Exchange team had a series of posts on throttling.
Note policy settings can be configured separately for the following common development protocols (amongst others): MAPI (policies abbreviated with “RCA” for RPC Client Access as noted by Steve), Exchange Web Services, Exchange ActiveSync. There are four basic kinds of settings for each protocol governed by the these policies: MaxConcurrency, PercentTimeInCAS, PercentTimeInAD, and PercentTimeInMailboxRPC. Exchange Web Services also has a couple unique settings for EWSFastSearchTimeoutInSeconds, EWSFindCountLimit, and EWSMaxSubscriptions. You can read more about these settings in the documentation for Set-ThrottlingPolicy, here’s a list of the EWS policies from that documentation:
EWSFastSearchTimeoutInSeconds
The EWSFastSearchTimeoutInSeconds parameter specifies the amount of time that searches made using Exchange Web Services continue before they time out. If the search takes more than the time indicated by the policy value, the search stops and an error is returned. The default value of this setting is 60 seconds.
EWSFindCountLimit
The EWSFindCountLimit parameter specifies the maximum result size of FindItem or FindFolder calls that can exist in memory on the Client Access server at the same time for this user in this current process. If an attempt is made to find more items or folders than your policy limit allows, an error is returned. However, the limit isn't strictly enforced if the call is made within the context of an indexed page view. Specifically, in this scenario, the search results are truncated to include the number of items and folders that fit within the policy limit. You can then continue paging into your results set via further FindItem or FindFolder calls.
EWSMaxConcurrency
The EWSMaxConcurrency parameter specifies how many concurrent connections an Exchange Web Services user can have against an Exchange server at one time. A connection is held from the moment a request is received until a response is sent in its entirety to the requestor. If users attempt to make more concurrent requests than their policy allows, the new connection attempt fails. However, the existing connections remain valid. The EWSMaxConcurrency parameter has a valid range from 0 through 100 inclusive. To indicate that the number of concurrent connections should be unthrottled (no limit), this value should be set to $null.
EWSMaxSubscriptions
The EWSMaxSubscriptions parameter specifies the maximum number of active push and pull subscriptions that a user can have on a specific Client Access server at the same time. If a user tries to create more subscriptions than the configured maximum, the subscription fails, and an event is logged in Event Viewer.
EWSPercentTimeInAD
The EWSPercentTimeInAD parameter specifies the percentage of a minute that an Exchange Web Services user can spend executing LDAP requests (PercentTimeInAD). A value of 100 indicates that for every one-minute window, the user can spend 60 seconds of that time consuming the resource in question.
EWSPercentTimeInCAS
The EWSPercentTimeInCAS parameter specifies the percentage of a minute that an Exchange Web Services user can spend executing Client Access server code (PercentTimeInCAS). A value of 100 indicates that for every one-minute window, the user can spend 60 seconds of that time consuming the resource in question.
EWSPercentTimeInMailboxRPC
The EWSPercentTimeInMailboxRPC parameter specifies the percentage of a minute that an Exchange Web Services user can spend executing mailbox RPC requests (PercentTimeInMailboxRPC). A value of 100 indicates that for every one-minute window, the user can spend 60 seconds of that time consuming the resource in question.
If your application gets throttled you may see one of the following response codes come back from Exchange (documented here on MSDN). If you think your application is getting throttled by Exchange you can look at the IIS logs on your client access server to confirm and get detailed throttling information related to each request.
ErrorExceededConnectionCount
This error -iIndicates that there are more concurrent requests against the server than are allowed by a user's policy.
ErrorExceededSubscriptionCount
This error indicates that a user's throttling policy maximum subscription count has been exceeded.
ErrorExceededFindCountLimit
This error indicates that a search operation call has exceeded the total number of items that can be returned.
ErrorServerBusy
This error occurs when the server is busy.
This is often overlooked but you should definitely use Autodiscover to get the EWS endpoint (Url) for each mailbox you are accessing. Autodiscover is a process which involves sending requests to a few pre-determined URLs and optionally [edited 9/16/2011 by mstehle for clarification] some DNS and AD queries to identify the Autodiscover service endpoint and then calling the Autodiscover service to get the EWS endpoint. The EWS Managed API wraps this process up neatly into a single method call which gives you no excuse not to use it. Read more in the Autodiscover Best Practices documentation for the EWS Managed API on MSDN.
Typically an application will use Autodiscover on an initial request to a mailbox and then cache the URL for that mailbox because the Autodiscover process can take a while. You definitely don’t want to do this before every request! You also don’t want to cache the URL forever either. It’s good practice to refresh the cached URL for a given mailbox every 24 hours or so and perform Autodiscover immediately following some error responses from EWS detailed here.
“…if you are dealing with multiple mailboxes, you should call Autodiscover once for *each* mailbox you are trying to access. Of course, it is reasonable to cache this information on the client side. However, note that due to mailbox moves/migration, such cached information may end up getting stale, so don't hold onto it too long.
So when *should* you re-autodiscover? As a general practice, we would recommend you calling autodiscover once per day. In addition, if you encounter any of the following failure response codes, you should re-autodiscover: ErrorMailboxMoveInProgress ErrorMailboxStoreUnavailable ErrorNoDestinationCASDueToKerberosRequirements ErrorNoDestinationCASDueToSSLRequirements ErrorNoDestinationCASDueToVersionMismatch ErrorNoRespondingCASInDestinationSite ErrorProxiedSubscriptionCallFailure ErrorProxyCallFailed” 9/16/2011 - mstehle - Updated this list to reflect changes in Exchange 2010 and further research into the subject: ErrorAutoDiscoverFailed ErrorConnectionFailed ErrorIncorrectSchemaVersion ErrorInvalidCrossForestCredentials ErrorInvalidIdReturnedByResolveNames ErrorInvalidNetworkServiceContext ErrorMailboxMoveInProgress ErrorMailboxMoveInProgress ErrorMailboxStoreUnavailable ErrorNameResolutionNoMailbox ErrorNameResolutionNoResults ErrorNotEnoughMemory
So when *should* you re-autodiscover? As a general practice, we would recommend you calling autodiscover once per day. In addition, if you encounter any of the following failure response codes, you should re-autodiscover:
9/16/2011 - mstehle - Updated this list to reflect changes in Exchange 2010 and further research into the subject:
Autodiscover is so important the Exchange team even wrote and recorded a song about it.
The Outlook team announced the availability of new Outlook Social Connector (OSC) providers for Facebook and Windows Live today. The list of providers now includes LinkedIn and MySpace, as well as the aforementioned Facebook and Windows Live. While this is cool from a consumer perspective, the capabilities here shouldn’t be lost on enterprise applicability. What the OSC aims to do is bring data to you based on contextual information in the emails you are viewing in Outlook – in most cases the recipient list of the email you are looking at. The API for creating your own OSC provider is well documented on MSDN. We even have a sample provider available on the MSDN Code Gallery written by the Outlook product team. My colleague, Patrick Creehan, even created a sample managed “proxy provider” which can give you a further jump start to creating your own providers for OSC.
The other nice thing about the OSC is that while it’s a new feature, built right into Outlook 2010, you can also download the connector for Outlook 2003 and 2007. Writing your provider once will cover 99% of the installed base of Outlook users through the same interface. There’s no fork in the deployment path or requirement for your customers to upgrade to Outlook 2010. Just as long as you have a version of Outlook shipped in the last 7 years, you’re good to go!
The OSC is a hugely under estimated integration point for Outlook in the corporate world. Tagging it with the word “social” probably does it an injustice because it isn’t limited to “social” applications. There are all kinds of corporate data points that would be interesting to pull data from into the OSC. Things like CRM systems, bug tracking databases, work item lists, source control systems, SharePoint sites, etc.
So while the demos you see of Facebook and Windows Live connectors look like this:
Imagine that you could also have items like:
“Rachel Drossman checked in Default.aspx to the project CompanyWebSite” “Rachel Drossman opened support incident 10100713123456 owned by Patrick Creehan”
“Rachel Drossman checked in Default.aspx to the project CompanyWebSite”
“Rachel Drossman opened support incident 10100713123456 owned by Patrick Creehan”
The key to making this a compelling integration point is the hyperlinks in the data stream. Clicking on “Default.aspx” could take you to the change history for that file in source control, click on the “CompanyWebSIte” link could take you to that project. Click on the support incident number takes you to the CRM tool for tracking customer issues and opens that particular incident. Think about your internal systems or products and about how richly you can integrate them into Outlook with the OSC. It’s pretty compelling…
I keep recommending these webcasts to people individually so I figured I should mention them here. The EWS team put together a series of six webcasts on called “Exchange 2010 Development” but it really focuses on Exchange Web Services specifically. If you are looking for information on Transport Agents or Powershell there’s not much here unfortunately. However, they go into great detail on essential EWS knowledge. If you are doing any EWS development this series is a must watch.
“Exchange Server 2010 Development (Part 1 of 6): Migrating Applications to Exchange Web Services In this Webcast, Jason Henderson gives an overview of what to consider when migrating applications that rely on Exchange Server and highlights the resources that are available on the Web to help you. Exchange Server 2010 Development (Part 2 of 6): A Deep Dive into Using Autodiscover Service in Exchange Web Services In this Webcast, David Claux provides a deep dive into the Autodiscover service, explains how you—as a developer—can use it to your advantage for your custom Exchange Server application, and highlights the resources that are available on the Web to help you. Exchange Server 2010 Development (Part 3 of 6): A Deep Dive into Impersonation and Delegation in Exchange Web Services In this Webcast, Alice Tang provides a deep dive into which mechanism to use when, explains what to consider when implementing these features, and highlights the resources that are available on the Web to help you. Exchange Server 2010 Development (Part 4 of 6): A Deep Dive into Exchange Web Services Notifications (Push/Pull) In this Webcast, Andrew Salamatov gives an overview of your options to either implement push event notifications or pull notifications in a scalable fashion and highlights the resources that are available on the Web to help you. Exchange Server 2010 Development (Part 5 of 6): A Deep Dive into the Exchange Web Services Managed API In this Webcast, David Claux provides a deep dive into the EWS Managed API and describes how it can help you, even if you develop applications that are not based on the Microsoft .NET Framework. Exchange Server 2010 Development (Part 6 of 6): Best Practices for Building Scalable Exchange Server Applications In this Webcast, Raz Mathias provides an overview of the things to consider when building Exchange Server applications on Microsoft Exchange Server 2007, Exchange 2010, or Exchange Online and describes the resources that are available on the Web to help you. The session primarily focuses on Exchange Web Services APIs.”
In this Webcast, Jason Henderson gives an overview of what to consider when migrating applications that rely on Exchange Server and highlights the resources that are available on the Web to help you.
In this Webcast, David Claux provides a deep dive into the Autodiscover service, explains how you—as a developer—can use it to your advantage for your custom Exchange Server application, and highlights the resources that are available on the Web to help you.
In this Webcast, Alice Tang provides a deep dive into which mechanism to use when, explains what to consider when implementing these features, and highlights the resources that are available on the Web to help you.
In this Webcast, Andrew Salamatov gives an overview of your options to either implement push event notifications or pull notifications in a scalable fashion and highlights the resources that are available on the Web to help you.
In this Webcast, David Claux provides a deep dive into the EWS Managed API and describes how it can help you, even if you develop applications that are not based on the Microsoft .NET Framework.
In this Webcast, Raz Mathias provides an overview of the things to consider when building Exchange Server applications on Microsoft Exchange Server 2007, Exchange 2010, or Exchange Online and describes the resources that are available on the Web to help you. The session primarily focuses on Exchange Web Services APIs.”
This transport agent identifies a message it wants to reject by looking for “[TEST]” in the subject. If it finds a message to reject, it creates a new message to be sent back to the sender and attaches the original message being rejected to the new message. To send the new message back to the sender of the original message it saves the new message to the pickup folder and deletes the original message so it won’t be sent.
Enjoy…
using System; using System.Collections.Generic; using System.Diagnostics; using System.Text; using System.IO; using Microsoft.Exchange.Data.Transport; using Microsoft.Exchange.Data.Transport.Email; using Microsoft.Exchange.Data.Transport.Routing; namespace CustomNDR { public sealed class CustomNDRAgentFactory : RoutingAgentFactory { public override RoutingAgent CreateAgent(SmtpServer server) { return new CustomNDR(); } } public class CustomNDR : RoutingAgent { // Place this text in the subject to test the agent public const string TestToken = "[TEST]"; public const string NdrSubject = "Rejected Message - Original Attached"; public const string OutputPath = @"C:\Users\Administrator\Desktop\CustomNDR\output\"; public const string PickupPath = @"C:\Program Files\Microsoft\Exchange Server\TransportRoles\Pickup\"; public CustomNDR() { LogMessage("CustomNDR{}", "Enter"); this.OnRoutedMessage += new RoutedMessageEventHandler(CustomNDR_OnRoutedMessage); this.OnSubmittedMessage += new SubmittedMessageEventHandler(CustomNDR_OnSubmittedMessage); this.OnResolvedMessage += new ResolvedMessageEventHandler(CustomNDR_OnResolvedMessage); LogMessage("CustomNDR()", "Leave"); } void CustomNDR_OnSubmittedMessage( SubmittedMessageEventSource source, QueuedMessageEventArgs e) { LogMessage("OnSubmittedMessage", "Enter"); try { // Don't process EVERY message... if (e.MailItem.Message.Subject.Contains(TestToken)) { EmailMessage origMsg = e.MailItem.Message; LogMessage("OnSubmittedMessage", String.Concat("Message: ", origMsg.Subject)); if (Directory.Exists(OutputPath)) { // Save a copy of the original message for debug //SaveMessage(origMsg, String.Concat(OutputPath, "Original.eml")); EmailMessage newMsg = EmailMessage.Create(); newMsg.To.Add(new EmailRecipient( origMsg.Sender.DisplayName, origMsg.Sender.SmtpAddress)); newMsg.From = new EmailRecipient("Service Account", "sa@zilladom12.extest.microsoft.com"); newMsg.Subject = NdrSubject; // Setting the contentType to 'message/rfc822' // is the key to avoid an InvalidOperationException // with a message 'Cannot set the property, // the attachment is not an embedded message.' Attachment attach = newMsg.Attachments.Add( "RejectedMessage", "message/rfc822"); attach.EmbeddedMessage = origMsg; // Save a copy of the NDR message for debug //SaveMessage(newMsg, String.Concat(OutputPath, "newMsg.eml")); // Save message to the pickup directory to send it SaveMessage(newMsg, String.Concat(PickupPath, "newMsg.eml")); // Cancel the original message source.Delete(); } else { LogMessage("OnSubmittedMessage", "OutputPath does not exist."); } } } catch (Exception ex) { LogMessage("OnSubmittedMessage", String.Format("EXCEPTION: Type={0}, Message='{1}'", ex.GetType().FullName, ex.Message)); } LogMessage("OnSubmittedMessage", "Leave"); } void CustomNDR_OnResolvedMessage( ResolvedMessageEventSource source, QueuedMessageEventArgs e) { LogMessage("OnResolvedMessage", "Enter"); LogMessage("OnResolvedMessage", "Leave"); } void CustomNDR_OnRoutedMessage( RoutedMessageEventSource source, QueuedMessageEventArgs e) { LogMessage("OnRoutedMessage", "Enter"); LogMessage("OnRoutedMessage", "Leave"); } public static void SaveMessage(EmailMessage msg, string filePath) { try { FileStream file = new FileStream(filePath, System.IO.FileMode.Create); msg.MimeDocument.WriteTo(file); file.Close(); } catch { LogMessage("SaveMessage", String.Format("Failed to save message, {0}, to {1}.", msg.Subject, filePath)); throw; } } public static void LogMessage(string methodName, string message) { try { StringBuilder traceMessage = new StringBuilder(); traceMessage.Append(System.DateTime.Now.ToString("s")); traceMessage.Append("|"); traceMessage.Append(methodName); traceMessage.Append("|"); traceMessage.Append(message); traceMessage.Append("\r\n"); System.Diagnostics.Debug.WriteLine(traceMessage.ToString()); File.AppendAllText( String.Concat(OutputPath, "log.txt"), traceMessage.ToString()); } catch (Exception ex) { Debug.WriteLine(String.Format("Failed to log message, {0}, to 'log.txt' in {1}.", message, OutputPath)); System.Diagnostics.Debug.WriteLine(String.Format("Exception: {0}", ex.Message)); } } } }
EWSEditor 1.6.1 is now available for download at the EWSEditor Code Gallery project site!
API coverage is a major focus of the 1.6.* releases of EWSEditor. The 1.6.1 release adds an OOF Settings and Availability form to this end. There were several bugs addressed in this release was well as some changes in the error dialog and about information. These changes will make the information displayed and logged by EWSEditor more useful.
Here is the change list from the download page for this release…
Issues BUG: Untrapped exception when using a self signed certificate on Exchange 2010 BUG: NullReferenceException in ServiceDialog BUG: Autodiscover URL cleared out BUG: ConvertFormToExtendedPropDef makes too many assumptions about control state BUG: Contents grid for attachments should refresh after deleting an attachment BUG: Version dialog says 1.5.0.2. Contrast with Filever output BUG: Double click TreeViewNode opens wrong folder Features FEATURE: OOF Settings Form FEATURE: Add availability form Tasks DCR: EWS Managed API dialog warning should have download link DCR: About EWSEditor doesn't give the EWSEditor website DCR: Distribute EWS API binary as part of release DCR: Simplify copying an exception to the clipboard from the ErrorDialog DCR: F1 should bring up the About dialog. DCR: The AboutDialog should have links to blog content and project site DCR: New Error dialog with "copyable" text.
Issues BUG: Untrapped exception when using a self signed certificate on Exchange 2010 BUG: NullReferenceException in ServiceDialog BUG: Autodiscover URL cleared out BUG: ConvertFormToExtendedPropDef makes too many assumptions about control state BUG: Contents grid for attachments should refresh after deleting an attachment BUG: Version dialog says 1.5.0.2. Contrast with Filever output BUG: Double click TreeViewNode opens wrong folder
Features FEATURE: OOF Settings Form FEATURE: Add availability form
Tasks DCR: EWS Managed API dialog warning should have download link DCR: About EWSEditor doesn't give the EWSEditor website DCR: Distribute EWS API binary as part of release DCR: Simplify copying an exception to the clipboard from the ErrorDialog DCR: F1 should bring up the About dialog. DCR: The AboutDialog should have links to blog content and project site DCR: New Error dialog with "copyable" text.
In my introduction of EWSEditor I said I’d try to get an update out in January of 2010 – now it is late February and there is still no update. What’s up with that?.. Well, life gets busy but I’ve also been working on improvements to ExRCA’s EWS tests which you’ll see soon. I’m also finding that implementing new features takes time and combined with fixing bugs I probably over-committed in this next release of EWSEditor. What I will try to do moving forward is streamline my release process, be more strategic how about what features I add and when, and do more updates with a smaller amount of changes. There are tons of features I have in mind and it’s tempting to try to get them all done in a single release. Instead I’ll focus on getting each new feature published in a release as I finish it.
You can see what changes are coming using the advanced view of the Issue Tracker on the project site. I’m trying to keep this up to date moving forward. When each release is posted, you’ll be able to easily see what is new and what was fixed. Please so use the Issue Tracker and Discussions to provide feedback if you have any.
EWSEditor 1.5 has over 600 downloads so far! Come back and check out 1.6 when it releases in the next few days!
Over the past year I’ve been working with the new Exchange Web Services Managed API and I have to say, it’s a wonderful thing – especially compared to working with the Visual Studio generated proxy classes for Exchange Web Services. While working with Exchange Web Services (EWS) early in the Exchange 2007 release it became apparent to me that an editor tool in the spirit of MFCMAPI built on top of EWS might be useful. At the time I started working on such an editor and based it off the Visual Studio generated proxy classes. To my delight I was soon introduced to an API that the product team was working on to make my life (and that of any other EWS developer using .NET languages) much easier – the EWS Managed API.
I immediately started work on converting my editor code from proxy classes to this new API. This process was about 75% deleting code and 25% writing new EWS Managed API code. I was replacing hundreds of lines of proxy class code with half as much (or less) EWS Managed API code. Over the coming months I explored the features of the API and was able to quickly add new functionality to the editor because I could focus on UI code rather than wordy proxy class code.
Out of all of this work comes EWSEditor! This initial public release is called version 1.5 because it has been used internally for a while by my team. There are still features I’m working on and basic API coverage that will come together over time. It’s a work in progress but still very useful in its current state so I wanted to get it out to the public. Please feel free to send me suggestions, comments, bugs, etc. There is an Issue Tracker and Discussions page on the project site – feel free to use them.
From the project site, here are the goals of EWSEditor…
“1. Demonstrate the Exchange Web Services Managed API functionality and simplicity to developers through its source code. 2. Demonstrate the Exchange Web Services SOAP traffic used to perform actions initiated through an explorer user interface. 3. Assist non-developers in debugging and understanding Exchange stores by exploring items, folders, and their properties in depth. “
The plan right now is to do an update every two months (next one will be in January). Since this is the first public release there might be an interim release if some blocking issue come up. Available for download are release notes which I’ll add to with each release to track the changes over time and give an overview of what is new. Here are the notes from the 1.5 release…
“1.5 Release – 11/6/2009 The first public release of EWS Editor! The basic feature set is still be flushed out but it is still a very useful tool. There are three feature areas of EWS Editor: General UI, Support Tools, and API Coverage. The focus of this release was to establish the UI design and flow of the application, solidify some useful support tools, and illustrate the direction of the application. There are some gaps in CRUD tasks across item and folder properties and items themselves. The major focus of upcoming releases will be to fill in these gaps before moving on to new features.”
“1.5 Release – 11/6/2009
The first public release of EWS Editor! The basic feature set is still be flushed out but it is still a very useful tool. There are three feature areas of EWS Editor: General UI, Support Tools, and API Coverage. The focus of this release was to establish the UI design and flow of the application, solidify some useful support tools, and illustrate the direction of the application.
There are some gaps in CRUD tasks across item and folder properties and items themselves. The major focus of upcoming releases will be to fill in these gaps before moving on to new features.”
If your interested, download the source or just the binary and try it out. Here are some the highlighted features from the release notes…
Exchange Service Profiles Exchange Service Profiles describe not only the connection information for calls specified in the ExchangeService class but also the root folder to use in the tree view of EWS Editor. Multiple ExchangeService objects can be displayed at one time using unique configurations. This allows folders on multiple servers and server versions to be displayed at one time or displaying the same folders using different credentials. Exchange Service Profiles can be saved to an XML file which contains the configuration information (sans specified passwords) so that it can be reloaded easily. If a profile requires credentials then a prompt will appear when loading the Services Profile to enter the credentials. View properties of ExchangeServices, Folders, and Items The PropertyDetailsGrid display first class properties for all nodes of the tree view starting with the root, ExchangeService node and all the way to the folder contents form, displaying first class properties for Items in a folder. Under the View menu the PropertySet used to retrieve item or folder data can be configured to customize which schema properties and extended properties are displayed in the PropertyDetailsGrid. Extended Property Lookup A number of known extended MAPI properties have been indexed in EWS Editor. Extended properties can be added to the PropertyDetailsGrid through a look up using a known constant name for the property such as PR_SUBJECT, PidTagSubject, etc. An Extended Property Lookup tool provides a way to quickly get the property information for a known constant. Request and response logging While EWS Editor is running, all requests and responses are logged to a file. The Chatter Log tool is used to view the history of requests and responses.
Exchange Service Profiles describe not only the connection information for calls specified in the ExchangeService class but also the root folder to use in the tree view of EWS Editor. Multiple ExchangeService objects can be displayed at one time using unique configurations. This allows folders on multiple servers and server versions to be displayed at one time or displaying the same folders using different credentials.
Exchange Service Profiles can be saved to an XML file which contains the configuration information (sans specified passwords) so that it can be reloaded easily. If a profile requires credentials then a prompt will appear when loading the Services Profile to enter the credentials.
The PropertyDetailsGrid display first class properties for all nodes of the tree view starting with the root, ExchangeService node and all the way to the folder contents form, displaying first class properties for Items in a folder. Under the View menu the PropertySet used to retrieve item or folder data can be configured to customize which schema properties and extended properties are displayed in the PropertyDetailsGrid.
Extended Property Lookup
A number of known extended MAPI properties have been indexed in EWS Editor. Extended properties can be added to the PropertyDetailsGrid through a look up using a known constant name for the property such as PR_SUBJECT, PidTagSubject, etc. An Extended Property Lookup tool provides a way to quickly get the property information for a known constant.
While EWS Editor is running, all requests and responses are logged to a file. The Chatter Log tool is used to view the history of requests and responses.
From the Exchange Team blog:
“Today we released an updated version of the Exchange Remote Connectivity Analyzer. For those of you not familiar with this site, it is a Web-based tool that helps you troubleshoot connectivity issues. The tool simulates several client logon and mail flow scenarios. When a test fails, many of the errors have troubleshooting tips to assist you in correcting the problem. For more information, see our previous blog post here. … Additional tests Exchange Web Services - This allows you to perform connectivity testing for Exchange Web Services client such as Entourage. Developers can also use the Service Account Verification test to ensure things are configured and working properly for access with an alternate account or Exchange Impersonation.”
“Today we released an updated version of the Exchange Remote Connectivity Analyzer. For those of you not familiar with this site, it is a Web-based tool that helps you troubleshoot connectivity issues. The tool simulates several client logon and mail flow scenarios. When a test fails, many of the errors have troubleshooting tips to assist you in correcting the problem. For more information, see our previous blog post here.
…
Additional tests
Brad Hughes came up with this awesome tool and I’ve been working with him to add these EWS tests to ExRCA. There are two basic tests that you can do at this time with Exchange Web Services: 1) Test the ability of an account to perform basic Exchange Web Services tasks like Synchronization, Notification, Availability, and OOF or 2) Test the ability of a service account to access a mailbox through delegate access or Exchange Impersonation. The first set of tests may be more useful to Exchange Administrators testing for Entourage client connectivity and as well as Availability and OOF which are used by Outlook too. The Service Account Access test is a quick way to test and diagnose issues with service accounts accessing other mailboxes.
Both of these tests should be run against a test mailbox with an empty Inbox and Calendar folder because they will attempt to create and delete test items. During the execution of the test ExRCA looks to ensure the Calendar and Inbox of the specified mailbox are empty before running.
Prior to Exchange 2007 SP1 an article was published with some specific guidance related to handling time zones in calendar item tasks. Contrary to Best Practices for Using Exchange Web Services for Calendaring Tasks, specifying just a MeetingTimeZone TimeZoneName when creating a CalendarItem appears to work in Exchange 2007 SP1 and later. The best practices says not to submit the TimeZoneName in MeetingTimeZone because it will be ignored, though there is a hint that this might not apply to Exchange 2007 SP1:
“Do not supply the optional TimeZoneName element when you create calendar items. In the initial release version of Exchange 2007, the TimeZoneName element is ignored on incoming requests.”
However, take the following request which properly creates a CalendarItem in the Eastern time zone:
<t:CalendarItem>
<t:ItemClass>IPM.Appointment</t:ItemClass>
<t:Subject>Appointment in Eastern Time</t:Subject>
<t:Start>2009-06-26T09:00:00.000</t:Start>
<t:End>2009-06-26T09:30:00.000</t:End>
<t:MeetingTimeZone TimeZoneName="Eastern Standard Time">
</t:MeetingTimeZone>
</t:CalendarItem>
From the best practices, the following statement intends to confirm that TimeZoneName is not ignored in Exchange 2007 SP1 and can be used by itself to define a time zone:
“In Exchange Server 2007 Service Pack 1 (SP1), BaseOffset is an optional element, and supports MeetingTimeZones that specify the TimeZoneName only.”
This is quite true in fact, were in Exchange 2007 pre-SP1 specifying the offset elements was a requirement and TimeZoneName was ignored; in Exchange 2007 post-SP1 the TimeZoneName is actually the preferred method for declaring a time zone. Furthermore, offset and transition values should only be set when specifying a custom time zone. Otherwise, standard time zones should be specified using TimeZoneName which is the name of the time zone as it appears in the registry key name on the Exchange CAS server. Then the Exchange server will pull the transition and offset information from the registry for the time zone you specified. Here is an image showing where the registry keys are:
Bottom line, with Exchange 2007 SP1 don’t specify time zone offset and transition values for known time zones – use the TimeZoneName instead. This will help your application work seamlessly with any updates to known time zone definitions in the future.
Earlier I linked to a post by Henning Krauses which discusses searching for a meeting using the UID and GlobalObjectId properties. The point of UID is to provide a unique identifier for a meeting across the calendars each attendee to the same meeting. Henning gave some expert advise for using GlobalObjectId instead of UID in a FindItem request to locate instances of a recurring meeting in different user’s calendars. As noted in his article, in Exchange 2007 pre-SP2 the UID property is built from GlobalObjectId – he even shows how to convert from UID to GlobalObjectId.
Using GlobalObjectId poses a problem however…If you were to create a recurring appointment and invite one attendee for only one instance of that recurring appointment that attendee ends up with only the one exception instance of the parent recurring appointment in their calendar. This is called an “orphaned” appointment. This type of appointment’s GlobalObjectId has additional information in it related to the exception date (for more information look at PidLidGlobalObjectId in MS-OXOCAL). The bottom line here is that this orphaned instance in this one attendee’s calendar will have a GlobalObjectId, and therefore UID, which doesn’t match the related appointments in the other attendee’s and organizer’s calendar. Henning’s code won’t work in this specific scenario…
So what now? Is this a bug in Exchange? Is there another property Henning could use? The answer to both questions is, yes!
There is another property, CleanGlobalObjectId, which was defined just for this scenario. If you look at the documentation for this property, the remarks confirm that this property specifically addresses the issue described above:
“The format of this property is the same as that of LID_GLOBAL_OBJID ( PidLidGlobalObjectId). The value of this property must be equal to the value of LID_GLOBAL_OBJID, except the YH, YL, M, and D fields must be zero. All objects that refer to an Instance of a recurring series (including an orphan instance), as well as the recurring series itself, will have the same value for this property.”
So all Henning needs to do in his sample is change it to use the CleanGlobalObjectId instead of GlobalObjectId. Now, it would be logical to assume that Exchange should base the UID property off of the CleanGlobalObjectId too instead of GlobalObjectId. In fact, we’ve done just that. In Exchange 2007 SP2 UID is based on the CleanGlobalObjectId instead of GlobalObjectId. Because SP2 just came out and many customers may wait to install it because of the schema changes you’ll want to keep the workaround above in mind when working with GlobalObjectId and UID in Exchange Web Services.
A while ago Steve posted information about how to turn of various types of “crawling” in Outlook via named properties that can be set on a store to tell Outlook whether or not it is okay to “crawl” the store in different scenarios. There are cases where you might have tons of folders in a store and you don’t want Outlook to enumerate all these folders because it would impact performance. I was recently asked if these properties could be set via a simple VB script. Turns out it is pretty straight forward to set this property via the PropertyAccessor in Outlook’s object model.
The following script will work with Outlook 2007 and greater. It is simply a sample script which can be used to set the CrawlSourceSupportMask to enable or disable Outlook crawling a store to look for Contact, Task, and Calendar folders in an opened store. You could easily modify this script to set ArchiveSourceSupportMask if you needed to – this disables/enables Outlook crawling open stores looking for folders that need to be archived.
Option Explicit Main() Sub Main On Error Resume Next Dim oApplication 'As Outlook.Application Set oApplication = CreateObject("Outlook.Application") If Err.number <> 0 Then DisplayError "Unable to get Outlook application object, " & _ "make sure Outlook 2007 is installed on this computer." Exit Sub End If Dim oSession 'As Outlook.Namespace Set oSession = oApplication.Session If Err.number <> 0 Then DisplayError "Unable to get current Outlook session, make sure " & _ "Outlook 2007 is running." Exit Sub End If MsgBox "Choose an Outlook message store to configure.", _ 1, _ "Configure Outlook Do Not Crawl" Dim oFolder 'As Outlook.Folder Set oFolder = oSession.PickFolder If oFolder Is Nothing Then Exit Sub End If If Err.number <> 0 Then DisplayError "Unable to get Folder." Exit Sub End If Dim oStore 'As Outlook.Store Set oStore = oFolder.Store If Err.number <> 0 Then DisplayError "Unable to get Store." Exit Sub End If Dim choice choice = MsgBox ("Do you want Outlook to crawl the message store you selected?", _ 4, _ "Configure Outlook Do Not Crawl") Dim CrawlSourceSupportMask CrawlSourceSupportMask = "http://schemas.microsoft.com/mapi/string/" & _ "{00062008-0000-0000-C000-000000000046}/CrawlSourceSupportMask" Dim propValue propValue = oStore.PropertyAccessor.GetProperty(CrawlSourceSupportMask) If Err.number = -2147221233 Then MsgBox "CrawlSourceSupportMask is not currently set, click OK to create it and set it." Err.Clear ElseIf Err.number <> 0 Then DisplayError "Unable to get CrawlSourceSupportMask property." Exit Sub End If If choice = 6 Then oStore.PropertyAccessor.SetProperty CrawlSourceSupportMask, CLNG(1) ElseIf choice = 7 Then oStore.PropertyAccessor.SetProperty CrawlSourceSupportMask, CLNG(0) End If If Err.number <> 0 Then DisplayError "Failed to set CrawlSourceSupportMask." Exit Sub End If If choice = 6 Then MsgBox "Success! Do Not Crawl has been enabled on this store." ElseIf choice = 7 Then MsgBox "Success! Do Not Crawl has been disabled on this store." End If End Sub Sub DisplayError(strMessage) MsgBox strMessage & vbCrlf & vbCrlf & _ "Error Information" & vbCrlf & _ "Number: " & Err.number & vbCrlf & _ "Description: " & Err.Description, ,"Error!" End Sub
Option Explicit
Main()
Sub Main
On Error Resume Next
Dim oApplication 'As Outlook.Application
Set oApplication = CreateObject("Outlook.Application")
If Err.number <> 0 Then
DisplayError "Unable to get Outlook application object, " & _
"make sure Outlook 2007 is installed on this computer."
Exit Sub
End If
Dim oSession 'As Outlook.Namespace
Set oSession = oApplication.Session
DisplayError "Unable to get current Outlook session, make sure " & _
"Outlook 2007 is running."
MsgBox "Choose an Outlook message store to configure.", _
1, _
"Configure Outlook Do Not Crawl"
Dim oFolder 'As Outlook.Folder
Set oFolder = oSession.PickFolder
If oFolder Is Nothing Then
DisplayError "Unable to get Folder."
Dim oStore 'As Outlook.Store
Set oStore = oFolder.Store
DisplayError "Unable to get Store."
Dim choice
choice = MsgBox ("Do you want Outlook to crawl the message store you selected?", _
4, _
"Configure Outlook Do Not Crawl")
Dim CrawlSourceSupportMask
CrawlSourceSupportMask = "http://schemas.microsoft.com/mapi/string/" & _
"{00062008-0000-0000-C000-000000000046}/CrawlSourceSupportMask"
Dim propValue
propValue = oStore.PropertyAccessor.GetProperty(CrawlSourceSupportMask)
If Err.number = -2147221233 Then
MsgBox "CrawlSourceSupportMask is not currently set, click OK to create it and set it."
Err.Clear
ElseIf Err.number <> 0 Then
DisplayError "Unable to get CrawlSourceSupportMask property."
If choice = 6 Then
oStore.PropertyAccessor.SetProperty CrawlSourceSupportMask, CLNG(1)
ElseIf choice = 7 Then
oStore.PropertyAccessor.SetProperty CrawlSourceSupportMask, CLNG(0)
DisplayError "Failed to set CrawlSourceSupportMask."
MsgBox "Success! Do Not Crawl has been enabled on this store."
MsgBox "Success! Do Not Crawl has been disabled on this store."
End Sub
Sub DisplayError(strMessage)
MsgBox strMessage & vbCrlf & vbCrlf & _
"Error Information" & vbCrlf & _
"Number: " & Err.number & vbCrlf & _
"Description: " & Err.Description, ,"Error!"
Fellow developer support engineer, Patrick Creehan, has any interesting post about the delta between the documentation of DeleteItem calls and the actual behavior involving including the ChangeKey in the ItemId of the item you want to delete. In theory the ChangeKey would be required for DeleteItem requests to ensure that you know you have evaluated the latest version of the item and decided to delete it. If you pass an ItemId with a stale ChangeKey, you should get a error indicating this isn’t the latest version of the item and you can retrieve it to make sure you still want to delete it. This is how an UpdateItem request works. As Patrick’s post indicates, DeleteItem doesn’t work the same way UpdateItem works – it just ignores the ChangeKey and does the delete no matter what. Patrick has a workaround to provide similar functionality in case you need it.
The Exchange API team announced, they’ve posted a beta SDK for Exchange 2010 on MSDN. In their post they highlight the most notable change in the structure of this SDK:
“…For earlier product releases, all Exchange developer documentation is included in a single SDK. For Exchange 2010, documentation for each technology area is published in a separate SDK, making it quicker and easier for you to find information that you need. The following SDKs are available online for Exchange 2010 Beta: Exchange 2010 Beta Web Services SDK June 2009 Exchange 2010 Beta Transport Agents SDK June 2009 Exchange 2010 Beta Backup and Restore SDK June 2009…”
“…For earlier product releases, all Exchange developer documentation is included in a single SDK. For Exchange 2010, documentation for each technology area is published in a separate SDK, making it quicker and easier for you to find information that you need. The following SDKs are available online for Exchange 2010 Beta:
Henning Krause posted a couple interesting articles that go along with my earlier, performance themed EWS posts (part 1 & part 2). His first post is about processing items in a folder using the EWS Managed API, he walks through some of missteps I see customer make when they complain about how “slow” EWS is – as he points out it often comes down to choosing the right tool for the job and synchronization is often over looked by novice EWS developers who choose to loop through an entire folder looking for changes instead. His second post is more about limiting the requested PropertySet to increase the performance of your EWS code – something I have pointed out earlier with GetItem and FindItem calls but it is good to reinforce this concept in SyncFolderItem calls as well.
Speaking of GetItem vs. FindItem calls – Henning has a third post which shows you how to get the message body with a FindItem request even though technically you can’t request the “item:body” schema property in a FindItem’s PropertySet. His post points out an important concept which is that schema properties (or “first class properties” as they are sometimes called) are tied back to extended properties which are the “raw values”. Often times certain limitations are applied to the schema properties because they calculations can be expensive or unavailable at a certain time – however in some cases you can get around this by using and understanding the correlating extended properties.
Jason Nelson posted a couple items (round 1 and round 2) on the Exchange team blog about named property mapping detailng the history and problems with this mapping and upcoming changes in Exchange 2007 SP2 and Exchange 2010. Most notable from the “round 2” post is that in Exchange 2007 SP2 and Exchange 2010 “…no x-headers are ever promoted to individual properties if a client has not already requested (and mapped) them. Not even authenticated submissions can create new named property mappings.” This could pose a problem if your application relies on these headers to do processing, if you are using an Exchange API with property access like EWS, MAPI, CDO 1.21, WebDAV, or Outlook 2007+ object model then fear not, “…x-headers are still stored in PR_TRANSPORT_HEADERS and still accessible to MAPI clients but they are not individual properties.”
However, if your application uses IMAP the story is different…
“Exchange2007 does not contain an STM file - it doesn't save the original mime content. Messages are converted to MAPI. IMAP has the ability to search based on header values, but if these are not promoted, the result is that the message is not contained in the results. If a client has previously mapped t he header in question (a MAPI client) then messages delivered after this will have the x-header promoted as an individual property.”
I kept forgetting about this so maybe blogging it will help me remember. As this thread confirms – you can’t call GetUserOofSettings, SetUserOofSettings, or GetUserAvailability when using Exchange Impersonation. If you try to do this you’ll get an error that the Service Account is not the mailbox owner.
The Exchange API team has a new post to explaining the differences between using Exchange Impersonation vs. Delegate Access to access an Exchange mailbox using Exchange Web Services. I’ve seen first hand that there is a gap in understanding the difference between the two and when to use one versus the other. This post goes a long way to address some of the confusion.
An important note that some people miss is the differentiation between Windows and Exchange impersonation – they’re not the same thing and more importantly, they aren’t even related…
“Exchange Impersonation is different than Windows Impersonation. Windows Impersonation is an operating system concept that requires you to set Kerberos constrained delegation. Exchange Impersonation is a simpler authorization mechanism that is designed for use only within Exchange Web Services (EWS). For more information about Windows Impersonation, see Client Impersonation on MSDN.”
Conversely, the posts describes delegate access as…
“Delegate access is used in scenarios in which there needs to be a one-to-one relationship between users. One common application of delegate access is the sharing of calendars between users, such as when an admin manages an executive’s calendar, or a when handful of individuals working on a project need to coordinate calendars… …Individual users can grant and remove delegate access to their own mailboxes through several mailbox clients, such as Microsoft Outlook, Outlook Web Access, or Exchange Web Services-based clients. A mailbox owner does not need administrator rights to grant another user delegate access to their mailbox.”
“Delegate access is used in scenarios in which there needs to be a one-to-one relationship between users. One common application of delegate access is the sharing of calendars between users, such as when an admin manages an executive’s calendar, or a when handful of individuals working on a project need to coordinate calendars…
…Individual users can grant and remove delegate access to their own mailboxes through several mailbox clients, such as Microsoft Outlook, Outlook Web Access, or Exchange Web Services-based clients. A mailbox owner does not need administrator rights to grant another user delegate access to their mailbox.”
…To be clear, delegate access can be granted by an administrator on an entire mailbox (but not to specific folders within the mailbox) using the Add-MailboxPermission cmdlet but as the above statement points out individuals can also grant delegate access for other users to access specific folders in their mailbox or the entire mailbox.
A major difference between impersonation and delegation is that as far as Exchange Web Services and Outlook Web Access are concerned there is no way to assign a single delegate access to multiple mailboxes expect by establishing the delegate relationship for each individual mailbox. I’ve talked about this before, the Exchange team describes it this way…
“For delegate access, there is no option to set up a single delegate for multiple mailboxes. A relationship must be established for each user who needs to access a given mailbox… …You must explicitly grant delegate access for any new users who are added.”
“For delegate access, there is no option to set up a single delegate for multiple mailboxes. A relationship must be established for each user who needs to access a given mailbox…
…You must explicitly grant delegate access for any new users who are added.”
…This is a great post and a worthwhile read but from working with many customers to help them understand these concepts, I’d like to add some additional information and emphasize some key points…
Understanding the Requests
To emphasize a side point in the blog post there are three methods of mailbox to access a mailbox: Exchange Impersonation, Delegate Access, and Direct Logon. The article doesn’t provide examples of what the XML looks like in each type of access request using Exchange Web Services. For understanding, I’ve provided them below…
Direct Logon <GetFolder> <FolderShape> <t:BaseShape>AllProperties</t:BaseShape> </FolderShape> <FolderIds> <t:DistinguishedFolderId Id="inbox"/> </FolderIds> </GetFolder> Delegate Access <GetFolder> <FolderShape> <t:BaseShape>AllProperties</t:BaseShape> </FolderShape> <FolderIds> <t:DistinguishedFolderId Id="inbox"> <t:Mailbox> <t:EmailAddress> someoneelse@contoso.com </t:EmailAddress> </t:Mailbox> </t:DistinguishedFolderId> </FolderIds> </GetFolder> Exchange Impersonation <soap:Header> <t:ExchangeImpersonation> <t:ConnectingSID> <t:PrimarySmtpAddress> someone@contoso.com </t:PrimarySmtpAddress> </t:ConnectingSID> </t:ExchangeImpersonation> </soap:Header> <soap:Body> <GetFolder> <FolderShape> <t:BaseShape>AllProperties</t:BaseShape> </FolderShape> <FolderIds> <t:DistinguishedFolderId Id="inbox"/> </FolderIds> </GetFolder> </soap:Body>
Direct Logon
<GetFolder> <FolderShape> <t:BaseShape>AllProperties</t:BaseShape> </FolderShape> <FolderIds> <t:DistinguishedFolderId Id="inbox"/> </FolderIds> </GetFolder>
Delegate Access
<GetFolder> <FolderShape> <t:BaseShape>AllProperties</t:BaseShape> </FolderShape> <FolderIds> <t:DistinguishedFolderId Id="inbox"> <t:Mailbox> <t:EmailAddress> someoneelse@contoso.com </t:EmailAddress> </t:Mailbox> </t:DistinguishedFolderId> </FolderIds> </GetFolder>
Exchange Impersonation
<soap:Header> <t:ExchangeImpersonation> <t:ConnectingSID> <t:PrimarySmtpAddress> someone@contoso.com </t:PrimarySmtpAddress> </t:ConnectingSID> </t:ExchangeImpersonation> </soap:Header> <soap:Body> <GetFolder> <FolderShape> <t:BaseShape>AllProperties</t:BaseShape> </FolderShape> <FolderIds> <t:DistinguishedFolderId Id="inbox"/> </FolderIds> </GetFolder> </soap:Body>
…The example above is for explicit delegate access. You can also access a mailbox using implicit delegate access by specifying a FolderId which links to another mailbox. All Ids returned by EWS embed their mailbox information in them so requesting them without explicitly specifying a mailbox will also work.
Putting It All Together
The terms used here come from the way Exchange Impersonation (also called Server-to-Server or S2S Authentication) is explained in the Inside Exchange Web Services book. The book describes three types of accounts that come into play when accessing a mailbox: the Service account, the Act As account, and the Mailbox account. Understanding how these accounts are affected by different mailbox access types is important. The Service account is the account used to generate the XML requests and authenticate to the virtual directory, the Act As account is the account which will be used to authorize actions taken against a mailbox, and the Mailbox account is the actual resource you are trying to access. In the grid below suppose you have an EWS application which runs as a user called ApplicationAccount, here is how the different access types affect each account context…