The case of the disappearing e-mail…

One of my customers was running into an odd case of disappearing e-mails.
They have an on-premise Exchange 2010 mail server on which they have a Shared mailbox to which all employees have access.

Now all of a sudden mails that are moved/copied TO this shared mailbox mysteriously disappear…

First thing that came to mind: Rules!

Bring in the Shell

First of all I needed to check if there weren’t any Server side rules which were configured, which you can easily do with the following command:

Blank result told me that if it was going to be Rules, it would have to be Client Side Rules…. great…

I had informed the customer of this and it would be up to them to have the users check their Client Side Rules [if needed disable them temporarily] in order to find the culprit.
The customer took it one step further and went past all the users’ desks [luckily ‘only’ around 30’ish people] and checked the Rules himself, but unfortunately nothing.

Back to the drawing board

First of all I confirmed the 2 next issues:

  1. The mailbox is actually a proper Shared Mailbox and not a Resource Mailbox by mistake
  2. What happens to e-mail directly sent to the mailbox?
    Well, I had sent 2 test emails to the mailbox and left them in the Inbox for 2 days to see if perhaps someone’s Client Side Rules would get triggered..
    [Un]Fortunately these mails were not moved/removed, so something else must be causing this…

Knowing these bits, I needed to drill down to the specific mailbox and find out exactly what was happening there.

The magic word is….

But of course, if you audit folders etc. , why can’t you audit mailboxes?

It turns out, you can, and quite detailed as well!

Using my best friend Google, I looked up the details on what to use and how to use it.
Yes, I know, perhaps I should’ve used the built in

but I personally prefer to use Google to point me in the right direction and then let the built-in Help function show me how to customize the usage of said command.

This TechNet article told me everything I needed, the command I required was as simple as ever

But what is audited by default? What are the default settings for the auditing?

This shows me the following:

  • AuditingEnabled
    Well, this should be rather clear 🙂
    Default value = False
  • AuditLogAgeLimit
    How long should the Audit Log live before it’s recycled?
    As the Audit Log is contained within the actual mailbox, you want to limit this, as it takes up space depending on how much you want to have audited
    Default value = 90 days
  • AuditAdmin
    Which actions performed by Administrators should be logged?
    Default value = Update, Move, MoveToDeletedItems, SoftDelete, HardDelete, FolderBind, SendAs, SendOnBehalf, Create
  • AuditDelegate
    Which actions performed by a Delegate should be logged?
    Default value = Update, SoftDelete, HardDelete, SendAs, Create
  • AuditOwner
    Which actions performed by the Mailbox owner should be logged?
    Default value = nothing

Great, but I would prefer if I saw a little more details for Delegates to I can report this back to the customer.
This TechNet article explains exactly what action means what, so you can easily tell if it’s interesting for your auditing or not.

Ok, so this is what I set up to configure both auditing and the actions I wanted audited

Testing your code

Ok, I’ve added auditing, now what?

I need to be able to check my audit logs and see if specific actions get reported the way I want them to.
What I did was as follows:

  1. I created a subfolder under Inbox called Test
  2. I moved my first test message to the newly created folder
  3. I copied my second test message to the newly created folder
  4. I removed my original second test message

Great, these are basically the actions I need to have checked.

I can now search the logs using this command:

Because the output can be a bit much to sift through, I save the details to a variable first

and I’ll sift through the values to see what I would like to have reported back to me.

Now to be honest, while running through this I had also found this GREAT article by Paul Cunningham, an Exchange Server MVP which basically had all my wishes pre-made.
While I love playing around with PowerShell to find the perfect solution, I have to take into account that the customer is experiencing an issue that needs addressing, so I used Paul’s script to get the report I wanted.

Automate the reporting

Now I have auditing configured and reporting on my audit, I have to make sure I get this report on a regular basis so I can track the culprit down.

Since this customer has a Windows 2008R2 Server running, setting up Scheduled Tasks with PowerShell was not yet properly implemented, so for this time I’ll manually add the Scheduled Task following the steps in my Scheduled Tasks – PowerShell Scripts with Parameters post [conveniently posted BEFORE this article 😉 ] and run it once to confirm that it runs as it should and doesn’t produce errors.

The trap is set, now we wait!

As this is an actual issue I’m experiencing right now, I’ll let you know the results when I know them, but you can already use the above techniques for your own troubleshooting.


Happy scripting!


Scheduled Tasks – PowerShell Scripts with Parameters

Perhaps a very “simple” issue, but I noticed that when looking for this it took me longer than expected to find the result I had in mind.

The issue at hand

I  have a script which requires various parameters to be provided so that I can run it.
When running the command through an active console session it would look like this:

As you can see, this can be quite the pain,  but if I get this configured properly can re-use this at various customers.

The solution

Now I won’t bore you with all the Scheduled Tasks Wizard screen, as there is only 1 screen that’s important for all of this:
The Start a Program screen

What you need to fill in to make sure you get PowerShell to run the script you require, using the parameters you want it to use.

  • Program/Script
    Full path to PowerShell executable [while some people have gotten it to work with just PowerShell, this should ALWAYS work]
  • Add arguments (optional)

    for example
  • Start in (optional)
    Not required

That’s it!

Extra Tip

While this should be all that’s required to make sure it runs properly, I found a tip that might prove quite useful when troubleshooting issues with Scheduled Tasks:

In the Add arguments (optional) section, if you add

after your full script path + parameters, it will properly include the last exit code under the Last Run Results column, making troubleshooting that much easier.


Happy scripting 🙂



Migrating scheduled tasks from 2008 to 2012+

Today I was busy with a customer who needed to migrate some Scheduled Tasks from his Windows Server 2008 to his new Windows Server 2012 R2 machine.

Slight issue, there were 139!! Scheduled Tasks [generating reports and sending them to various sources].
There’s no way I was going to do this manually, so let’s start up my favourite tool for the job: PowerShell!

I immediately ran into the first issue:
There are no PowerShell cmdlets for Windows 2008 concerning Scheduled Tasks, so you’re limited to the built in command SchTasks, however this can be a troublesome parsing etc. .

Bring on the magical solution to all of your problems: SEARCHING!
I’m sure someone else has run into this problem before I did and I was proven right.

A great set of functions to obtain Scheduled Task info from Windows Server 2003/2008 machines!

Because Windows Server 2012 and up does have these cmdlets, surely I could simply import the results and I’m done right? Wrong….

Unfortunately the customer had multiple Scheduled Tasks with the same name, but with different actions linked to it, along with the fact that while some Tasks were not enabled, they did need to be copied over to make sure they could re-enable them at a later date if needed.

Time to start PowerShell Studio [or ISE]!

 The Solution

Exporting the data

First of all I needed to make a slight change on the Get-ScheduledTasks function I had downloaded.

When running the code, I ran into an error on line 93, which didn’t recognize the [ordered] type adapter, as this is from PowerShell 3.0 and up [which doesn’t come default on a Windows 2008 server].
So a quick change is in order [line 93]:

Should be

Simple as that!

Now I can export this result to a .CSV file and import this on my workstation to play around with the data and get what I want.


Importing the data for manipulation

First we will need to import the .CSV file into my workstation:

Now in order to see what data I have available I’ll just check the properties of one of the tasks defined:

This calls the first entry of the $tasks variable [PowerShell starts counting from 0 up] and displays it’s Members [Properties, Methods, etc.].
It shows me that I have various properties which I need in order to create a new Scheduled Task, including the entire XML code as it was configured on the Windows 2008 Server.


Using the XML entry I can simply register a new Scheduled Task with minimal configuration!

This will create the new Scheduled Tasks in a subfolder called Contoso and let’s the tasks be Run As the specified User.
Do note that in order to use the XML property, it needs to read the XML file as a single string, not as an XML file.
Otherwise you would have used:

Disabling currently disabled tasks

As mentioned, currently disabled tasks need to be migrated, but also configured as disabled tasks.
Because all the properties have been exported over, this isn’t a big issue.

Just add the following line within your foreach loop:


Almost there… but not quite yet…

Unfortunately I had noticed that when creating the Scheduled Tasks on my test machine, that the amount of tasks created wasn’t identical to the amount of tasks I had in my $tasks variable.

The cause was that Windows Server 2012 no longer allows for duplicate Task Names, which means that you will get an error when importing that says

This meant that I needed to look into WHAT the task was doing and change the TaskName property accordingly.
I had asked the customer the syntax used [custom made application] and he provided me with the following information:

If it has an Action parameter of -D, the report will be sent through email.
If it has an Action parameter of -p, a PDF report will be generated instead.

Ok, great!
Depending on the Action parameter, I could check whether or not the Scheduled Task was to create a Mail or PDF.
My plan was to simply check the Action parameter and add “Mail – ” or “PDF  -” to the Task Name

Unfortunately the customer had forgotten to mention that this still gave me 3 issues:

  1. There were reports which are neither Mail nor PDF’s
  2. Some Scheduled Tasks are all Mail reports with the same Task Name, but each have different recipients.
  3. Some Scheduled Tasks are Mail reports with the same Task Name, same recipient, but generates the report based on another template.

So I needed to check the Action parameter to see exactly what was in it:

Ok, so I can see the email address clearly and the title can be found at the end between quotes.

Extracting the exact report title

I know that the report title is the bit between quotes, so I can simple split the string of text at the quotes and find the first block of text after the first quote

If the Subject happened to be empty [or a single word, hence missing the quotes], I would keep the Subject the same as the current Task Name

The biggest problem here was that the report title sometimes contained invalid characters, such as >,  +, :, / or %, which would completely screw up the rest of my code when Registering the Scheduled Task.

So a little clean up was required.

I’m no star with Regular Expressions, so I used a cheat sheet 🙂
Another great site in order to test out Regular Expressions can be found here.

Extracting email address

Now in the Action parameter, the email address was also defined, but I needed to extract this first in order to use it later on to create a new Task Name.

This produced the following code to get a Task’s email address:


The Code

All in all, it took a while, but I’ve learnt quite a bit again and I hope you will too.
Here’s the final code used to make sure it’s as clean and correct as possible

Happy Scripting! 🙂