Cmdlet Extension Agents (Part 3)

If you would like to read the other parts in this article series please go to:


In the first two parts of this article series, we had a look at what the cmdlet extension agents are, how the Scripting agent works and how we can use it to automatically create an archive when a new mailbox is created. In this third and final part, we will see how to further extend this agent to configure certain mailbox properties such as ActiveSync, IMAP, Single Item Recovery, etc. We will also see how to automatically send a welcome e-mail and an example for the Validate API.

Single Item Recovery, ActiveSync, POP3, IMAP and Location

Let us assume that besides automatically enabling a mailbox for archiving when one is created, we want to also enable Single Item Recovery and disable ActiveSync, POP3 and IMAP. Additionally we also want to set extra user properties such as Country, City and the Company attributes.

However, this time we do not want to just consider the scenario when new mailboxes are created, but also when an administrator mailbox-enables an existing user. As such, we want to extend the cmdlets New-Mailbox and Enable-Mailbox. To do so, we update the Cmdlets attribute of the Feature tag to include both these cmdlets.

<?xml version="1.0" encoding="utf-8" ?>

<Configuration version="1.0">

<Feature Name="MailboxProvisioning" Cmdlets="New-Mailbox,Enable-Mailbox">

<ApiCall Name="OnComplete">

If($succeeded) {

$mbx = $provisioningHandler.UserSpecifiedParameters["Name"]

If ((Get-Mailbox $mbx).ArchiveDatabase -eq $null) {

$mbxDatabase= (Get-Mailbox $mbx).Database

$arcDatabase= $mbxDatabase -ireplace "M", "A"

Enable-Mailbox $mbx -Archive -ArchiveDatabase $arcDatabase


Set-Mailbox $mbx -SingleItemRecoveryEnabled $True

Set-CASMailbox $mbx -ActiveSyncEnabled $False -ImapEnabled $False -POPEnabled $False

Set-User $mbx -CountryOrRegion “United Kingdom” -City “London” -Company “Lets Exchange”





This example is very similar to the previous one, with only a few differences:

  • We now extended the cmdlets New-Mailbox and Enable-Mailbox instead of just New-Mailbox;
  • After checking or creating an archive, we enable Single Item Recovery for the mailbox specified ($mbx) by using the Set-Mailbox cmdlet;
  • We then disable ActiveSync, IMAP and POP client access for this mailbox as well using the Set-CASMailbox cmdlet;
  • Finally we set the attributes CountryOrRegion, City and Company for the user using the Set-User cmdlet.

The configuration file, after adding this code to the one from our previous example, looks like this:

Figure 3.1:
Configuration File to Configure Mailbox

Because all this code is part of our mailbox provisioning process and applies to both New-Mailbox and Enable-Mailbox cmdlets, we keep it all inside the same Feature tag.

Before testing, let us check how the mailbox Test1 was configured in regards to these features and attributes before we added this code to our configuration file:

Figure 3.2:
Configuration File Pre-Check

As we can see, ActiveSync, IMAP and POP were enabled by default and the CountryOrRegion, City and Company attributes were not populated. Now that we further extended our Scripting agent, let us create a new mailbox and check these features and attributes again:

Figure 3.3:
Configuration File to Configure Mailbox - Test

Once again, our code automatically configured these features to what we wanted them to be!

Although only in small/medium companies every user will be in the exact same location, this example serves the purpose of showing that you can basically do anything with the Scripting agent.


Another useful example could be related to permissions. Some small organizations have requirements that state that members of the ServiceDesk group should have FullAccess permissions to everyone’s mailbox in order to be able to easily troubleshoot any problems with them. As such, we could easily add the following code in order to automatically assign permissions when creating a new mailbox:

Add-MailboxPermission $mbx –User IT –AccessRights FullAccess –InheritanceType All

Obviously I would also recommend enabling Mailbox Audit Logging to ensure that if any of these users abuse their permissions, their actions can be audited:

Set-Mailbox $mbx -AuditEnabled $True –AuditLogAgeLimit 90.00:00:00 -AuditDelegate Update, MoveToDeletedItems, SoftDelete, HardDelete, SendAs, SendOnBehalf, Create

Once again, we can simply add this code to our existing MailboxProvisioning Feature tag in the configuration file:

Figure 3.4:
Configuration File to Configure Mailbox Permissions

Welcome E-mail

Some organizations like to send users a welcome message when they first join the company. This is usually achieved through 3rd-party products or even manually from HR or their Line Manager, for example. However, it is possible to achieve the same using the Scripting agent and automatically send a welcome e-mail whenever a new mailbox is created.

To do so, we first need to create an HTML file with the message template that we will use to send to new users. You can use most HTML templates as long as they are supported by Outlook – remember that Outlook does not support all HTML code tags. The easiest way is probably to compose a new e-mail in Outlook and then save is as a HTML file:

Figure 3.5:
Welcome E-mail Template

We now need to copy the template to every Exchange server (for the same reasons we need the Scripting agent’s configuration file in all servers), and add some simple code to our script to send the e-mail when a mailbox is created:

$DisplayName = $provisioningHandler.UserSpecifiedParameters["DisplayName"]

$emailAddress = $mbx + "@letsexchange.com"

$emailMsg = [String] (Get-Content ("C:\Scripts\WelcomeEmail.htm"))

$emailMsg = $emailMsg -Replace "UserName", $DisplayName

Send-MailMessage -From "welcome@letsexchange.com" -To $emailAddress –Bcc "hr@letsexchange.com" -SMTPserver "smtp.letsexchange.com" -Subject "Welcome!" -Body $emailMsg -BodyAsHTML

Here is what this script does:

  • We first store the details from the mailbox such as the DisplayName and e-mail address in two different variables: $DisplayName and $emailAddress respectively;
  • Then, we read the content from the e-mail template from the “C:\Scripts\WelcomeEmail.htm” file and store it in the variable $emailMsg which will become the body of the e-mail. We then use the replace function to replace “UserName” in the template with the correct user’s display name;
  • Then all there is left to do is send the e-mail to the user. In this example, we also Bcc the HR department so they have a record of the e-mail sent.

However, let us suppose that we do not want an e-mail to be sent when a mailbox is created for an already existing user (when the Enable-Mailbox cmdlet is used). In this case, we can place the above code in a new Feature tag that only applies to the New-Mailbox cmdlet (note that variables from the first Feature tag are available to the second Feature tag such as the $mbx variable for example):

Figure 3.6:
Configuration File to Send Welcome E-mail

When a new mailbox is created, the Scripting agent will be invoked and it will run code within the MailboxProvisioning Feature tag, where we configure all different features of the mailbox and the user account, followed by our new code in the Welcome E-mail Feature which sends the e-mail to the user. If the Enable-Mailbox cmdlet is run, only the MailboxProvisioning Feature will be invoked as the Welcome E-mail Feature does not have this cmdlet in its Cmdlets list.

The welcome e-mail will then be automatically sent to the user when the mailbox is created (note that the display name was successfully updated):

Figure 3.7:
Welcome E-mail Received by User

Validate API

So far we only focused on the OnComplete API, but we can also use any of the other 3 APIs: ProvisionDefaultProperties, UpdateAffectedIConfigurable or Validate.

The Validate API can be useful to validate any parameters of a cmdlet when this is run. For example, we can validate that the IP address an administrator adds to a certain Receive Connector is within a certain authorised range, or even ensure that no Test-* cmdlets are run between 8AM and 6PM.

A basic example of the use of the Validate API could be to force administrators to use the DisplayName parameter when creating a mailbox. To achieve this we would add the following code to our configuration file:

<Feature Name="MailboxProvisioning" Cmdlets="New-Mailbox,Enable-Mailbox">

<ApiCall Name="Validate">

<!-- Proceed only if -DisplayName is specified-->

If ($provisioningHandler.UserSpecifiedParameters["DisplayName"] -eq $null) {

New-Object -Type Microsoft.Exchange.Data.ProvisioningValidationError -ArgumentList ("Please specify a DisplayName for the mailbox!", [Microsoft.Exchange.Data.ExchangeErrorCategory]::Client)




This way, if an administrator tried to create a mailbox without specifying a value for the DisplayName parameter, he/she would receive the error message we used in the code above:

Figure 3.8:
Welcome E-mail Received by User

This might be a useless example because when creating a mailbox through the Exchange Administration Center, administrators are forced to specify a DisplayName anyway, but you get the point.


In this article series, we talked about and demonstrated how to use Cmdlet Extension Agents in Exchange 2013 to extend the functionality of any cmdlet. Specifically, we saw how to improve the mailbox provisioning process by automatically configuring mailbox features and settings such as archiving, ActiveSync, IMAP, Single Item Recovery and automatically send a welcome e-mail to new users.

If you would like to read the other parts in this article series please go to: