• Home
  • Topics
    • Office 365
    • Teams
    • SharePoint Online
    • Exchange 2019
    • Exchange 2016
    • Exchange 2013
    • Hybrid
    • Certificates
    • PowerShell
    • Migration
    • Security
    • Azure
  • Blog
  • Podcast
  • Webinars
  • Books
  • About
  • Videos
    • Interview Videos
    • How To Guide Videos
  • Subscribe
    • Facebook
    • Twitter
    • RSS
    • YouTube

Practical 365

You are here: Home / Exchange Server / Searching Message Tracking Logs by Time and Date Range

Searching Message Tracking Logs by Time and Date Range

September 20, 2012 by Paul Cunningham 17 Comments

I’ve previously written about message tracking in Exchange Server as well as some tips on how to search message tracking logs using PowerShell.

In this article I will demonstrate a few different ways that you can specify time and date ranges for message tracking log searches. This is a useful technique because it can speed up your searches by minimizing the amount of log data that the search inspects.

As an example of this speed difference, here is the result of Get-MessageTrackingLog for all logs on a single server.

1
2
3
[PS] C:\>Measure-Command {Get-MessageTrackingLog -ResultSize Unlimited}
 
TotalSeconds      : 161.8412674


In contrast, here is a search of only the last 24 hours of message tracking logs.

1
2
3
[PS] C:\>Measure-Command {Get-MessageTrackingLog -Start (Get-Date).AddHours(-24) -ResultSize Unlimited}
 
TotalSeconds      : 8.235824


If you’re wondering about that “AddHours(-24)” bit don’t worry, we’ll get to that shortly.

You can see that in a very large environment you will save yourself a lot of time by knowing how to narrow your message tracking log searches with time and date ranges.

Table of Contents

  • Get-MessageTrackingLog Time/Date Range Parameters
  • Specifying Relative Time/Date Ranges using Get-Date
  • Searching Message Tracking Logs for a Single Day
  • Searching Between Two Specific Times/Dates
  • Searching Between a Fixed and a Relative Time/Date Range
  • Filtering Search Results using Where-Object
  • Summary

Get-MessageTrackingLog Time/Date Range Parameters

There are two parameters for specifying time and date ranges when running the Get-MessageTrackingLog cmdlet.

  • -Start – the point in time to start returning log entries. If omitted the search will begin at the first entry of the oldest message tracking log file on the server.
  • -End – the point in time to stop returning log entries, up to but not including the time/date specified. If omitted the search will end at the last entry of the latest message tracking log file on the server.

Both parameters accept values in the System.DateTime format, meaning mm/dd/yyyy hh:mm:ss. An example of a valid date would be “9/19/2012”.

1
Get-MessageTrackingLog -Start 9/19/2012


Another example would be “9/19/2012 13:00:00”. Quotes need to be used when specifying both a date and time.

1
Get-MessageTrackingLog -Start "9/19/2012 13:00:00"

Specifying Relative Time/Date Ranges using Get-Date

Often you will find yourself in situations where you want to search the logs for a period of time without having to work out the exact start or end time for the search.

For example, you may wish to search only the last hour of logs because somebody has asked you to help troubleshoot a lost email that they only sent within the last hour.

In these situations the Get-Date cmdlet can be used to provide relative time/date ranges. This is actually how I perform most of my own searches.

On its own Get-Date returns a DateTime object (and outputs a human-friendly version of it to your shell).

1
2
3
[PS] C:\>Get-Date
 
Thursday, 20 September 2012 10:35:05 PM


We also get several methods that are of use to us in this situation.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[PS] C:\>get-date | Get-Member
 
   TypeName: System.DateTime
 
Name                 MemberType     Definition
----                 ----------     ----------
Add                  Method         System.DateTime Add(System.TimeSpan value)
AddDays              Method         System.DateTime AddDays(double value)
AddHours             Method         System.DateTime AddHours(double value)
AddMilliseconds      Method         System.DateTime AddMilliseconds(double value)
AddMinutes           Method         System.DateTime AddMinutes(double value)
AddMonths            Method         System.DateTime AddMonths(int months)
AddSeconds           Method         System.DateTime AddSeconds(double value)
AddTicks             Method         System.DateTime AddTicks(long value)
AddYears             Method         System.DateTime AddYears(int value)


I tend to use the AddHours and AddDays methods the most. Here is an example of Get-Date on its own, and then Get-Date using the AddHours method to subtract one hour.

1
2
3
4
5
6
7
[PS] C:\>Get-Date
 
Thursday, 20 September 2012 10:35:05 PM
 
[PS] C:\>(Get-Date).AddHours(-1)
 
Thursday, 20 September 2012 9:35:18 PM


So now let’s combine that with the Get-MessageTrackingLog -Start parameter to search the message tracking logs only for the last hour.

1
Get-MessageTrackingLog -Start (Get-Date).AddHours(-1)


Pretty simple stuff right? So let’s look at some more examples.

Remember as we go through each of these examples that you may need to use “-ResultSize Unlimited” for searches that are expected to return more than 1000 results. As a general rule I use it on all searches just to save time.

Searching Message Tracking Logs for a Single Day

In this scenario you might be tempted to specify the same value as both the start and end date, but this will return an error.

1
2
3
4
[PS] C:\>Get-MessageTrackingLog -Start 9/17/2012 -End 9/17/2012 -ResultSize unlimited
The search time range was incorrectly specified. The End and Start parameter values can't be the same.
    + CategoryInfo          : InvalidArgument: (:) [], LocalizedException
    + FullyQualifiedErrorId : 7A353D3


The correct method is to specify the next day as the end date, remembering that the time/date value used for -End is excluded from the results.

1
[PS] C:\>Get-MessageTrackingLog -Start 9/17/2012 -End 9/18/2012 -ResultSize unlimited


In the above example only log entries occurring between 9/17/2012 00:00:00 and 9/17/2012 23:59:59 will be returned. Obviously another way of achieving that is to specify those exact hours/minutes/seconds in your search.

1
[PS] C:\>Get-MessageTrackingLog -Start "9/17/2012 00:00:00" -End "9/17/2012 23:59:59" -ResultSize unlimited


That is more typing for the exact same result, so you may as well stick to the more efficient method of simply specifying the date on its own.

Searching Between Two Specific Times/Dates

As a follow on from the previous example it should by now be clear that you can search between any precise start and end times.

Just remember that the hh:mm:ss can be either 24-hour time or AM/PM. If you do not specify AM/PM and enter an ambiguous time such as “11:59:59” then the time will be interpreted as AM.

For example, this will search to 11:59:59 PM.

1
[PS] C:\>Get-MessageTrackingLog -Start "9/17/2012 00:00:00" -End "9/17/2012 11:59:59 PM" -ResultSize unlimited


And this will search to 11:59:59 PM, because the time is specified using 24-hour format.

1
[PS] C:\>Get-MessageTrackingLog -Start "9/17/2012 00:00:00" -End "9/17/2012 23:59:59" -ResultSize unlimited


But this will search to 11:59:59 AM, because ambiguous times will default to AM.

1
[PS] C:\>Get-MessageTrackingLog -Start "9/17/2012 00:00:00" -End "9/17/2012 11:59:59" -ResultSize unlimited

Searching Between a Fixed and a Relative Time/Date Range

You may also wish to combine fixed and relative time/date values in your search.

For example, a search of all messages starting from noon on 17th September and ending 8 hours later.

1
[PS] C:\>Get-MessageTrackingLog -Start "9/17/2012 12:00:00" -End (Get-Date "17/9/2012 12:00:00").AddHours(8) -ResultSize unlimited


This may seem a bit of a strange example, but the reason I’m using it is to demonstrate one little gotcha with DateTime values.

On my server the regional settings as set to “English (Australia)” for time, meaning the format is dd/mm/yyyy instead of the US mm/dd/yyy.

This means that I need to use US format for Get-MessageTrackingLog, but Australian format for Get-Date.

But I can avoid this confusion and also save a little typing by capturing the start date in a variable first, that I can then re-use in my Get-MessageTrackingLog command, because once the DateTime object has been capture in a variable the regional settings become irrelevant and each cmdlet is able to interpret it correctly regardless.

1
2
3
[PS] C:\>$date = Get-Date "17/9/2012 12:00:00"
 
[PS] C:\>Get-MessageTrackingLog -Start $date -End $date.AddHours(8) -ResultSize unlimited


This habit also gives you the advantage of a fixed point in time if you were running multiple searches moving through the logs hour by hour as I sometimes do.

1
2
3
4
5
[PS] C:\>Get-MessageTrackingLog -Start $date.AddHours(-2) -End $date.AddHours(-1) -ResultSize unlimited
 
[PS] C:\>Get-MessageTrackingLog -Start $date.AddHours(-3) -End $date.AddHours(-2) -ResultSize unlimited
 
[PS] C:\>Get-MessageTrackingLog -Start $date.AddHours(-4) -End $date.AddHours(-3) -ResultSize unlimited

Filtering Search Results using Where-Object

As a final example remember that a good practice is to capture your message tracking log search results into a variable so that you can quickly and easily filter those results down further without needing to re-run your search.

1
[PS] C:\>$msgs = Get-MessageTrackingLog -Start 9/17/2012 -End 9/18/2012 -ResultSize unlimited


You can then simply use Where-Object to return more specific time/date ranges from the data already captured in that variable, using the TimeStamp value.

For example, where in the previous command I collected all message tracking log entries for the 17th September, I can now filter that down to only those entries that were written between 14:00 and 14:05.

1
[PS] C:\>$msgs | Where-Object {$_.TimeStamp -gt "9/17/2012 14:00:00" -and $_.TimeStamp -lt "9/17/2012 14:05:00"}


When using comparison operators against DateTime values remember that -gt (greater than) means “after/later than” and -lt (less than) means “before/earlier than”.

Summary

As you can see when you become familiar with the use of time/date ranges you can perform very fast, very precise message tracking log searches on your Exchange Servers using PowerShell.

Exchange Server Exchange 2007, Exchange 2010, Exchange 2013, Message Tracking, PowerShell

Comments

  1. Simon says

    January 6, 2022 at 11:30 am

    Hi Paul,

    I just wanted to say I have googled “exchange message tracking logs practical 365” many times over the years to get the date bit right, here I am again in 2022 =) …your Exchange info is invaluable, thank you for sharing!

    If it helps anyone, adding | Out-GridView is a handy option, you can then copy/paste the raw data into Excel. A great way to sort and filter after the fact.

    Get-MessageTrackingLog -Start (Get-Date).AddHours(-24) -ResultSize Unlimited | Out-GridView

    Cheers 🍺
    Simon
    https://www.howdoiuseacomputer.com/

    Reply
  2. Zeeshan says

    February 21, 2020 at 5:35 am

    Thank you great article could you please help me changing the timestamp to yyyy/MM/DD

    Reply
  3. Manfred says

    August 30, 2017 at 10:54 pm

    Dear Paul,
    thx very much for this tutorial.
    Is there any Chance you could also post the command for my topic:
    find all mails (inbound or outbound) from date XXX to ZZZ “afterhours”. (time range 1800 ’til 0600).
    If it is possible!

    Thx
    Kory

    Reply
  4. Kapil says

    April 19, 2017 at 3:33 am

    Hi Paul,

    I have changed the path of message tracking logs from one drive to another drive on the same MBX exchange 2013 server. After changing the path I restarted transport service, it generated new tracking log files but old logs where not moved to the new location. So I manually copied all the logs and indexing folder from old location to new location and again restarted the server. Now I am able to do message tracking of old mails but when I put “-End” in message tracking command there is no result and when I remove -End from command I get the tracking events for old mails. For new mails after changing the path works fine. Unable to understand the issue. Please guide on this issue.

    Reply
    • Paul Cunningham says

      April 19, 2017 at 11:15 am

      Without seeing the command you’re running I can’t offer any suggestions.

      Reply
      • Kapil K says

        April 19, 2017 at 1:57 pm

        Hi Paul,

        I checked by using below command

        Get-MessageTrackingLog -Server -Start “4/5/2017” -End “4/6/2017”

        But If I use Get-MessageTrackingLog -Server -Start “4/5/2017”, then it shows the proper output

        Reply
  5. Jim says

    April 6, 2016 at 11:52 pm

    When I include the Timestamp field in the format-table output, I often find that rows are out of order even though I am sorting the Timestamp field. They are apparently out of order because it is only resolving the time to hh:mm:ss, not hh:mm:ss.000 syntax. Is there a way to get the Timestamp column to show the latter syntax to get the rows in the correct order?

    Reply
  6. Brad says

    February 18, 2014 at 12:46 am

    Paul,

    I have a client that is asking me to show the number of time each of their Mail Contacts were “Sent To” in the past 6 months & 3 months. My thought was to pull all the recipient email addresses for a certain period of time and then compare this with their list of Contacts.

    Do you know of a way to pull all the recipient addresses into a .csv file for a period of time?

    Reply
  7. Pravin says

    October 3, 2013 at 1:13 pm

    I have to generate spam report with the message tracking logs, i am able to get the report with count, with per day but in the report i am not able to put the Date. can you help me in this.

    I have ran below command.

    Get-TransportServer -identity hub1 |Get-MessageTrackingLog -EventID send -Recipients spam@abc.com -Start (Get-Date).AddDays(-1) -End (Get-Date) -Resultsize unlimited | Group-Object ClientHostname

    It is giving me below output.

    Count Name Group
    —– —- —–
    125 Hub1 {Microsoft.Exchange.Management.TransportLogSearchTasks.MessageTrackingEvent,

    i want in this report just Date which will give me the date, count, server.

    Thanks in advance.

    Reply
  8. dosh says

    October 4, 2012 at 8:45 pm

    back in the days of exchange 2003, one did not have to bother with such scripting as message tracking was more user friendly – I still regret having to upgrade to 2010.
    Why did 2010 developers decided to make things more difficult?

    Reply
  9. Marietta says

    October 1, 2012 at 11:50 pm

    I agree, this is a really great article. I haven’t seen this much information in a while. I have been using time tracking software for a while. This seems like it will save a lot of time! Thanks so much for sharing.

    Reply
  10. Ios. says

    September 26, 2012 at 1:51 pm

    Great article, as always, Thanks Paul.

    Only this morning I was playing with the MTL in 2010 and came up with the following which may be of help to others. It’s very basic, no error checking, but when saved as a .ps1 script, lets you grab the last x minutes of logs across all transport servers. The key issue I was trying to solve was that when searching multiple transport servers at the same time, you’d get all of the results from the first server, then all from the 2nd, etc.., which when you’re looking for a particular time, can be a pain. It isn’t pretty, and I probably wouldn’t use it where there are more than a couple of hub servers, but it works :

    [PS] C:Scripts>.Get-MTLLastMins.ps1 15
    #copy the rest to a script
    param([int]$mins=60); #default to 60mins if no number added
    Write-Host “Last $mins minutes of MessageTrackingLog across all Transport Servers.”
    Get-TransportServer | Get-MessageTrackingLog -Start (Get-Date).AddMinutes(-$mins) -Resultsize unlimited | Select-Object TimeStamp,EventId,Source,@{Name=”MessageSubject”;Expression={($_.MessageSubject).substring(0,25)}},@{Name=”Sender”;Expression={($_.Sender).substring(0,30)}},@{Name=”ClientHost”;Expression={($_.ClientHostname).substring(0,14)}},@{Name=”ServerHost”;Expression={($_.ServerHostName)}},Recipients | Sort TimeStamp | ft
    #end of script

    Reply
  11. Turbomcp says

    September 22, 2012 at 9:57 pm

    Thanks
    interesting as always
    very much appreciated Paul

    Reply
  12. Sherlon Martina says

    September 21, 2012 at 10:49 am

    Great article. this will save a lot of time.

    Reply

Leave a Reply Cancel reply

You have to agree to the comment policy.

Recent Articles

  • Turn On MFA: Real-World Example of Fraud, Domain Stealing, and the Nearly Lost House Deposit
  • Changes in Microsoft 365 Apps Channels and Why You Should Care
  • A New Tool to Manage Exchange-related Attributes Without Exchange Server
  • Microsoft Launches Group Ownership Governance Policy
  • Making the Case for Identity Governance in Azure Active Directory

Copyright © 2022 Quadrotech Solutions AG · Disclosure · Privacy Policy
Alpenstrasse 15, 6304 Zug, Switzerland