Powershell script to report on total send/received e-mails in Exchange


Update: 2017-08-16 – I have published a new version of this script here


This is a simple PowerShell script that pulls all of the send/received e-mails from the Message Tracking log in Exchange 2010 and counts the unique header IDs.

It’s fairly accurate but I don’t think it’s 100% bang on. My testing showed the numbers generated to be off by about 10%.

This script was built for generic mailboxes but should work on individual mailboxes as well.


I have a scheduled task configured on one of our Exchange servers that runs this every Monday morning and provide me the stats on a generic mailbox for the previous week (Monday – Sunday).

16 thoughts on “Powershell script to report on total send/received e-mails in Exchange

  1. This will give you the accurate number you are looking for. I used your code as a base and adjusted to filter on EventID as well as making it report daily. We were also only concerned with received emails. With some of the changes I also needed to add the exchange snapins prior to executing any other work. Works like a charm, thanks to the starting point.


    Add-PSSnapin Microsoft.Exchange.Management.PowerShell.E2010
    $nl = [Environment]::NewLine




    $emailFrom = “Email.Stats@yourdomain.local”
    $emailTo = “”
    $subject = “Daily e-mail report for $mailbox for $startDateFormatted”
    $smtpServer = “smtpServer”

    $receiveCount = Get-TransportServer | Get-MessageTrackingLog -Recipients $mailbox -Start “$startDateFormatted 00:00:01” -End “$EndDateFormatted 23:59:59” -EventID “receive” | Measure-Object

    #$sendCountString = $sendCount.count
    $receiveCountString = $receiveCount.count

    $body = “Mailbox stats for: $mailbox $nl
    Report date: $startDateFormatted $nl
    Total e-mails received: $receiveCountString”

    $smtp = new-object Net.Mail.SmtpClient($smtpServer)
    $smtp.Send($emailFrom, $emailTo, $subject, $body)

    • Paul –

      At the risk of asking a dumb question, what is the reason/need to “add the exchange snapins prior to executing any other work”?

      I ask because I am a nube to EMS usage, so don’t know the reason for this. Is there something not in place with a “standard” Exchange (2010 in my case) installation?

      Thanks for not throwing something sharp at the new guy on the block :-)


      • Adding the lines in means you can run the script from a regular PowerShell prompt instead of having to call the EMS instead.

        EMS is just PowerShell that automatically the Exchange Snapins for you

        • Thanks Eric, I was able to get this script tweaked and working wonderfully!

          As a follow-up question, is it possible to EXCLUDE from the daily count any emails that are EITHER from a specific sender’s address OR with maybe a specific term in the subject line?

          Thanks again for your expert help,


          • I’m actually working on a v2 of this script right now for Exchange 2016 which will more accurately count only outbound e-mail AND allow for an exclusion list. I’ll make a new blog post and link it in this one once I’m done.

            I’m hoping to be done in a week or less.

        • I tried this, but I just don’t seem to be getting it right…

          $receiveCount = Get-TransportServer | Get-MessageTrackingLog -Recipients $mailbox -Start “$startDateFormatted 00:00:01” -End “$EndDateFormatted 23:59:59” -EventID “receive” | Measure-Object | Where-Object {$_.Sender -NotMatch “UnwantedSenderEmailAddress.com”}

    • Yes actually. We’re using this script to count how many e-mails people send in 24 hours:

      # Users who sent more than 'x' e-mails yesterday
      # Created by: Eric Schewe
      # Created on: 2015-09-02

      # Set the minimum sent e-mails count you care about. Anyone who sends more than this number will appear in the report
      $minimumEmails = 500

      #How we define yesterday
      $startTime = (get-date -Hour 00 -Minute 00 -Second 00).AddDays(-1)
      $endTime = (get-date -Hour 23 -Minute 59 -Second 59).AddDays(-1)

      #E-mail stuff
      #Multiple e-mail addresses should be in this format ", "
      $to = ""
      $from = "no-reply@my.exchange.server"
      $subject = "Staff who sent over $minimumEmails e-mails for $startTime to $endTime"
      $smtpServer = ""

      $yesterdayStats = Get-TransportServer | Get-MessageTrackingLog -Start $startTime -End $endTime -EventID "SEND" -ResultSize Unlimited | Group-Object -Property Sender | %{ New-Object psobject -Property @{Sender=$_.Name;Recipients=($_.Group | Measure-Object RecipientCount -Sum).Sum}} | Where-Object {$_.Recipients -gt $minimumEmails} | Sort-Object -Descending Recipients | Format-Table -AutoSize Sender,Recipients | Out-String

      if ($yesterdayStats.Contains("Sender")) {

      $smtp = new-object Net.Mail.SmtpClient($smtpServer)
      $smtp.Send($from, $to, $subject, $yesterdayStats)


      Just change $minimumEmails to 1 and you should see everyone in the report.

        • I think you just need to change this line:

          $endTime = (get-date -Hour 23 -Minute 59 -Second 59).AddDays(-1)


          $endTime = (get-date -Hour 23 -Minute 59 -Second 59).AddDays(-30)

          That should do the last 30 days. It’s going to take a long time though….

  2. Hi Eric,


    Thank you for sharing this script. We have a multipal domain like a.com,b.com and c.com and I want to get the report domain wide so how can i segregate it.

  3. Hi,

    I am getting below exception while running the script .please help



    Exception calling “Send” with “4” argument(s): “The parameter ‘to’ cannot be an empty string.
    Parameter name: to”
    At C:\Users\deepak_e\Desktop\MessageStats.ps1:63 char:11
    + $smtp.Send <<<< ($emailFrom, $emailTo, $subject, $body)
    + CategoryInfo : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : DotNetMethodException

  4. Hi All,

    I tried

    $startTime = (get-date -Hour 01 -Minute 00 -Second 00).AddDays(-1)
    $endTime = (get-date -Hour 23 -Minute 59 -Second 59).AddDays(-180)

    but I get

    The search time range was incorrectly specified. The End and Start parameter values can’t be the same.

    Any ideas?


Leave a Reply

Your email address will not be published. Required fields are marked *