Email message traces in Office 365

A very common need these days is to do an email message trace. This can be done the old way in the Exchange Online Admin center or the new way via Mail Flow in the Security and Compliance center.


You simply enter the details and then run a search.


and the output looks like the above, where you can also drill in and get more detail.


As with all things Office 365, you can achieve the exact same thing using PowerShell as I have shown above. The code to achieve this is quite straight forward but I have uploaded it to my GitHub repo to save you the trouble:

Where PowerShell comes into its own is when you need to a variety of tasks, perhaps an investigation of a breach. Using PowerShell you can easily dump all the information to CSV for further analysis rather than having to root it out in the web interface.

Reporting mailbox logins

Before much of what is covered here is possible you need to ensure you have enabled all the logging in your Office 365 tenant. I’ve covered how to do that here:

Enabling Office 365 mailbox auditing

Enable mailbox auditing in Exchange Online

Enable activity auditing in Office 365

Once you have done that you will be able to track what’s going on in your tenant much better.

In the situation of a compromised mailbox, a bad actor has control of it using legitimate credentials. This eliminates looking for failed logins, because there won’t be any. It also makes the finding the bad actor tougher because their access is most likely mixed in with the legitimate user.

The place to start is to run an audit log search as I have detailed here:

Searching the Office 365 activity log for failed logins


However, as I mentioned, we can no longer search for failed logins, we need to use a different search criteria. I would suggest that you instead run a search using the attribute “User signed in to mailbox” as shown above. That will produce something like shown for all users. Problem with this is that times and dates are in UTC not local time and it is cumbersome to manipulate in a web page. You can of course manipulate by exporting the results to a spreadsheet for more control.


Unsurprisingly, I feel PowerShell offers a much better solution to check the logs and report as you can see above. The script to do this I have made freely available at my Github repo here:

Basically, it will search the Audit log for Exchange Items that are Mailbox logins and send that output to a nice table via the Out-Grid command. As you can see, using Out-Grid you can now easily sort by time by clicking the column heading, and thanks to the script, the times are local not UTC!

By default, the script will check the last 48 hours but you can easily modify that to suit your needs by either entering the scope in hours or entering a start and end date in the variables at the top of the script.

With this output I can now look for suspect IPs that login into the mailbox and begin hunting from there. However, remember, all of this relies on you enable your auditing BEFORE you need it. So, if you haven’t enabled it, go do it now! You’ll find scripts to enable the logs also in my Office 365 repo here:

Monitor outbound spam as well


Hopefully everyone is well aware of the need to protect Office 365 email from inbound spam, however what are you doing about outbound spam?

Hopefully, no bad actor gains access to your environment BUT if they did and they started using you accounts to send spam email how would know?


For this reason, I suggest that it is a good idea to go into the Exchange Administration console, select Protection, then Outbound spam. Edit the default policy (that’s really your only option), then select outbound spam protection on the left hand side. Then I suggest you should enable the option to send an email when there is a suspicious outbound email to somewhere that is monitored.

That obviously, won’t stop outbound spam but it should at least give you a heads up that it is happening.

Updated script to now check for Sweep


The bad actors out there are clever and they’ll use any means at their disposal. Normally, when a user is successfully phished the first thing bad actors do is manipulate the email handling rules of the mailbox to hide their activity.

Unfortunately, there are quite a lot of different ways to forward email in Office 365 including via the mailbox and via Outlook client rules. It was brought to my attention that there is in fact another way that forwarding can be done, using the Sweep function. You can read more about this ability at:

Organize your inbox with Archive, Sweep and other tools in

Sweep rules only run once a day but do provide a potential way for bad actors to hide their activity, however as it turned out Sweep was in fact being exploited by bad actors inside a compromised mailbox.

I have therefore updated my publicly available PowerShell script at:

That will now also check and report on any Sweep rules in finds in mailboxes as well as any other forwards configured in the tenant.

Let me know if you find any other methods that this doesn’t cover and I’ll look at incorporating those as well.

Enabling modern authentication in Office 365 script

Just a quick note to let you know that I have uploaded another short script to make life a bit easier. This one will enable modern authentication in a tenant for Exchange Online and Skype for Business Online (it is already on for SharePoint Online).

Modern authentication basically prevents multiple logins when using multi factor authentication for desktop apps like Outlook and Skype for Business client. You can read more about this here:

How modern authentication works for Office 2013 and Office 2016 client apps

Enabling modern authentication will also impact older clients like Office 2010, so enable it on your tenant with the understanding that when you do you really should be running the latest version of Office on all desktops.

That said, you can find my script here:

Note, that you’ll need to have connected to Exchange Online and Skype for Business online in PowerShell for the script to execute correctly.

PowerShell script to check Outlook mail rules


After I finished the recent PowerShell script to check for Exchange style mailbox forwards I received some motivate from Robert Pearman to develop a script to also go and check what the Outlook rules are doing for Office 365 mailboxes.

Taking what Robert provided I decided to extend my initial script to report on what I consider suspect Outlook mail rules. Here’s my thinking:

– Firstly there are going to potentially be lots and lots of Outlook rules when you look across all mailboxes in Office 365, so I decided to focus on actions that one could deem to more suspicious than others. I settled on the following rule actions as ones to check: forward to, redirect to, copy to folder, delete message, forward as attachment to and send text message notification to.

–  Turns out you can create an Outlook rule that forwards, redirects and fowards as an attachment messages to alternate email addresses. A bad party could set this up to send themselves emails from a compromised mailbox.

– If a rule copies rather than moves a message then that to me is also suspicious. Why would you want two copies of the same email message in different locations in your inbox unless you aren’t in full full control of the inbox and someone is squirrelling away messages to a location the owner never created?

– If a rule deletes a message then there is a chance that a bad actor is trying to prevent the mailbox owner from seeing something.

– If a rule notifies someone via SMS that may be the fingerprint of a bad actor trying to keep tabs on a mailbox.

I will also admit, that there are plenty of situations where the above situations are the results of legitimately configured inbox rules. However, for the reasons I have indicated, I believe the actions to warrant the most inspection.

As you can see from the above image, the script will do what it did before and check the mailbox rules to see if there are any forwardings as before but now the script will also dig through each mailbox and throw up warnings when a suspect rule is enabled or disabled for a user.

Once you have located any suspect rules, you can then start digging further to see whether there is a business justification for such. If not, then you may have a compromised mailbox on your hands.

You’ll find the updated script at:

and remember to keep coming back as I’ll continue to update and extend it over time. if you have any feedback on this script of suggestion for things you’d like to see please let me know so I can look at developing them. Thanks again to Robert Pearman for this input on this.

Enabling Office 365 mailbox auditing

You may not be aware that by default Office 365 mailbox auditing isn’t turned on. Don’t believe me? Well check out this article, especially the first paragraph:

Enable mailbox auditing in Office 365

which says:

In Office 365, you can turn on mailbox audit logging to log mailbox access by mailbox owners, delegates, and administrators. By default, mailbox auditing in Office 365 isn’t turned on. That means mailbox auditing events won’t appear in the results when you search the Office 365 audit log for mailbox activity. But after you turn on mailbox audit logging for a user mailbox, you can search the audit log for mailbox activity. Additionally, when mailbox audit logging is turned on, some actions performed by administrators, delegates, and owners are logged by default.

If you want to check your own tenant then connect to Exchange Online with PowerShell and run this command:

get-mailbox | select userprincipalname,auditenabled

You’ll probably see that all the mailboxes don’t have auditing enabled.

To enable auditing, simply run this command:

Get-Mailbox -ResultSize Unlimited | Set-Mailbox -AuditEnabled $true

and then run the first command again to verify it is now enabled for all mailboxes.

You also need to appreciate that out of the box, not all items are audited and you may need to adjust these options, also using PowerShell. The options you can audit for are:

Mailbox auditing actions

I’ll cover how to set these in an upcoming article.

Configuring an Office 365 SPAM filtering policy with PowerShell

I recently wrote an article that shows you how to configure the spam policy in Office 365 using the web interface. If you missed that you can find it here:

Configuring an Office 365 SPAM filtering policy

Doing this multiple times via the web interface is a lot of work. A better approach is to use PowerShell. So once, how have connected to Exchange Online PowerShell, run these two commands:

$policyparams = @{
“name” = “Configured Policy”;
‘Bulkspamaction’ =  ‘movetojmf’;
‘bulkthreshold’ =  ‘7’;
‘highconfidencespamaction’ =  ‘movetojmf’;
‘inlinesafetytipsenabled’ = $true;
‘markasspambulkmail’ = ‘on’;
‘increasescorewithimagelinks’ = ‘off’
‘increasescorewithnumericips’ = ‘on’
‘increasescorewithredirecttootherport’ = ‘on’
‘increasescorewithbizorinfourls’ = ‘on’;
‘markasspamemptymessages’ =’on’;
‘markasspamjavascriptinhtml’ = ‘on’;
‘markasspamframesinhtml’ = ‘on’;
‘markasspamobjecttagsinhtml’ = ‘on’;
‘markasspamembedtagsinhtml’ =’on’;
‘markasspamformtagsinhtml’ = ‘on’;
‘markasspamwebbugsinhtml’ = ‘on’;
‘markasspamsensitivewordlist’ = ‘on’;
‘markasspamspfrecordhardfail’ = ‘on’;
‘markasspamfromaddressauthfail’ = ‘on’;
‘markasspamndrbackscatter’ = ‘on’;
‘phishspamaction’ = ‘movetojmf’;
‘spamaction’ = ‘movetojmf’;
‘zapenabled’ = $true

new-hostedcontentfilterpolicy @policyparams

The first basically sets up an array of all the parameters you are going to see into the spam policy. It makes it easier to adjust if you need to.

The second command creates a new policy based off this array that will be called ‘Configured Policy’.

However, after running these two commands you aren’t quite done yet because you have created the policy BUT you actually need to create a rule that uses this policy to do that use the following:

$ruleparams = @{
‘name’ = ‘Configured Recipients’;
‘hostedcontentfilterpolicy’ = ‘Configured Policy’;
## this needs to match the above policy name
‘recipientdomainis’ = ‘’;
## this needs to match the domains you wish to protect in your tenant
‘Enabled’ = $true

New-hostedcontentfilterrule @ruleparams

You’ll need to ensure the policy names match as noted and you include the domains you wish to protect.


Once this has been completed, if you go and look in your Exchange Admin area, under protection and spam filter, you should see a new policy called ‘Configured Recipients’ that was created by the above script commands.

Save the script away and run it as many times as you need. That should make life easier!