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:

Nuno Mota

Nuno Mota is an Exchange MVP working as a Microsoft Messaging Specialist for a financial institution. He is passionate about Exchange, Lync, Active Directory, PowerShell, and Security. Besides writing his personal Exchange blog, LetsExchange.blogspot.com, he regularly participates in the Exchange TechNet forums and is the author of the book “Microsoft Exchange Server 2013 High Availability.”

Published by
Nuno Mota

Recent Posts

How human resources became a technology powerhouse

When you think of technology, you don’t often think of human resources. But HR is now a leader in utilizing…

4 hours ago

Facebook patches WhatsApp remote code execution vulnerability

Facebook found and patched a vulnerability in its WhatsApp service. While Facebook says no users were compromised, the event is…

7 hours ago

Need Exchange reports? Use PowerShell to create them

Exchange does not have the capability natively to create reports. But don’t let that stop you. Power up PowerShell and…

9 hours ago

Visual Studio Code for IT pros: Refresh your Docker container skills

Docker and containers are an exciting new frontier for many IP pros. Here’s a primer on how to use Visual…

12 hours ago

ISO 27001 certification: Your step-by-step guide

ISO 27001 certification demonstrates that your business is serious about security. Here’s a roadmap to getting certified — and why…

1 day ago

Will SIM swapping be the Achilles heel of multifactor authentication?

Multifactor authentication is often touted as the answer to insecure passwords. But SIM swapping attacks are showing that no security…

1 day ago