Number of E-mails Sent and Received by one User

Have you ever needed to check how many e-mails a particular user sent and received in a day? Or maybe in a week or in a month? The following script will help you achieve this:

[Int] $intSent = $intRec = 0

Get-TransportServer | Get-MessageTrackingLog -ResultSize Unlimited -Start “10/01/2012” -End “11/01/2012” -Sender “[email protected]” -EventID RECEIVE | ? {$_.Source -eq “STOREDRIVER”} | ForEach { $intSent++ }

Get-TransportServer | Get-MessageTrackingLog -ResultSize Unlimited -Start “10/01/2012” -End “11/01/2012” -Recipients “[email protected]” -EventID DELIVER | ForEach { $intRec++ }

Write-Host “E-mails sent:    “, $intSent

Write-Host “E-mails received:”, $intRec

19 thoughts on “Number of E-mails Sent and Received by one User”

  1. Thanks for the article.
    It does not count internal email though. I can log into the users mailbox and see some internal emails but the count is 0. How can I include internally sent emails too?
    Thanks

    1. Hi David,

      It does count internal emails. For example, any email received by a user (either from an internal or external sender) will have an entry with a EventID of DELIVER. Then, you can differentiate between internal or external sender by looking at the sender’s email address domain if you want to.
      If your search is not returning any results, make sure the -Start and -End parameters are correct, and ensure you actually have Message Tracking Log data for those dates.

      Best regards,
      Nuno

  2. Thank you for the reply.
    Can you please explain the eventIDs RECEIVED and DELIVER and why you don’t us the SEND eventID?
    Thank you very much!!

    1. Hi David,
      SEND is when a message was sent by SMTP between transport services. On the other hand, RECEIVE is when messages are received by the SMTP receive component of the transport service or from the Pickup or Replay directories (source: SMTP), or a message was submitted from a mailbox to the Mailbox Transport Submission service (source: STOREDRIVER). This is why I use both RECEIVE and STOREDRIVER to check when a user sends an email. If you wanted to track emails sent by applications, for example, you could indeed use SEND instead.
      DELIVER is when a message is delivered to a local mailbox, so this is the best method to use to track emails that were actually delivered to a mailbox.
      Hope this helps.

      Regards,
      Nuno

  3. I tried your suggestion but no matter the time period or user it always returns values of zero (0) for both sent and received.

    1. I am assuming you have Message Tracking Log enabled and logs for the time period you are searching? Also, have you made sure the time/date is in the correct format (dd/mm/yyyy vs mm/dd/yyyy)?
      What do you get if you run:

      Get-TransportServer | Get-MessageTrackingLog -ResultSize Unlimited -Sender “[email protected]” -EventID RECEIVE | ? {$_.Source -eq “STOREDRIVER”}

  4. add-pssnapin Microsoft.Exchange.Management.PowerShell.E2010
    $e=0;
    $i=0;
    $recexternal=0;
    $recinternal=0;
    [email protected](“[email protected]”)
    Foreach($user in $array)
    {

    $sender=get-transportserver | Get-MessageTrackingLog -ResultSize unlimited -Sender $user

    $sender |%{

    if(($_.source -eq “SMTP”) -and ($_.EventId -eq “SEND”)){$e++}
    if(($_.source -eq “STOREDRIVER”) -and ($_.eventid -eq “DELIVER” )){$i++}

    }
    $recipient=get-transportserver | Get-MessageTrackingLog -ResultSize unlimited -recipients $user

    $reipient |%{

    if(($_.source -eq “SMTP”) -and ($_.EventId -eq “RECEIVE”)){$recexternal++}
    if(($_.source -eq “STOREDRIVER”) -and ($_.eventid -eq “DELIVER” )){$recinternal++}

    }
    }
    write-host “$user has sent $i emails internally”
    write-host “$user has sent $e emails externally”

    Write-host “$user has received $recexternal emails from outside organization”
    Write-host “$user has received $recinternal emails from inside the organization `n”

    I created the above script however $recexternal and $recinternal always shows zero
    $i and $e shows correct values

  5. hello, I used your script and tried extending it from 1/1/2018 to 1/31/2019 and I am getting same Sent and Received email totals…what do I need to change or update on this code below? THanks

    Get-TransportServer | Get-MessageTrackingLog -ResultSize Unlimited -Start “10/01/2012” -End “11/01/2012” -Sender “[email protected]” -EventID RECEIVE | ? {$_.Source -eq “STOREDRIVER”} | ForEach { $intSent++ }

    Get-TransportServer | Get-MessageTrackingLog -ResultSize Unlimited -Start “10/01/2012” -End “11/01/2012” -Recipients “[email protected]” -EventID DELIVER | ForEach { $intRec++ }

    Write-Host “E-mails sent: “, $intSent

    Write-Host “E-mails received:”, $intRec

    1. Hi Bob,

      Do you have Message Tracking Logs configured to retain logs for 1 year?
      The code is correct as long as the EventID wasn’t changed. Have you tried with different dates (try for the past 7 days for example).

      Regards,
      Nuno

  6. I believe its set at 360. Again, I modified date range for month long and I would tally for each month Oct, Nov, Dec, Jan… I ran below script and no totals for sent and received show…

    Get-TransportServer | Get-MessageTrackingLog -ResultSize Unlimited -Start “10/01/2018” -End “10/31/2018” -Sender “@mycompany.com” -EventID RECEIVE | ? {$_.Source -eq “STOREDRIVER”} | ForEach { $intSent++ }
    Get-TransportServer | Get-MessageTrackingLog -ResultSize Unlimited -Start “10/1/2018” -End “10/31/2018” -Recipients “@mycompany.com” -EventID DELIVER | ForEach { $intRec++ }
    Write-Host “E-mails sent: “, $intSent
    Write-Host “E-mails received:”, $intRec

    ————————————————————————————–
    Ideally I would like to run script for 10/1/2018 – 01/31/2019 sent and received email totals so I do have to do each month individually but when I ran 10/1 1/31 I get same totals so something isn’t jiving, please advise. Thanks

  7. I did use this script but idk where you put the begin and end date found at https://gallery.technet.microsoft.com/office/PowerShell-Generate-Email-da50c582

    param (
    [Parameter(Mandatory=$False,HelpMessage=”Specifies the month for which the report will be run (1-12 for Jan-Dec)”)]
    [ValidateNotNullOrEmpty()]
    [int]$ReportMonth = 0,

    [Parameter(Mandatory=$False,HelpMessage=”Specifies the start date for the generated report”)]
    [ValidateNotNullOrEmpty()]
    [string]$StartDate,

    [Parameter(Mandatory=$False,HelpMessage=”Specifies the end date for the generated report”)]
    [ValidateNotNullOrEmpty()]
    [string]$EndDate,

    [Parameter(Mandatory=$False,HelpMessage=”The file to which the user stats will be exported. {D} is replaced by report date”)]
    [string]$UserStatsExport = “user_stats_{D}.csv”,

    [Parameter(Mandatory=$False,HelpMessage=”The file to which the user stats will be exported. {D} is replaced by report date”)]
    [string]$OrgStatsExport = “org_stats_{D}.csv”
    )

    # Set date/time variables for report run. If month not specified, we assume last month
    $today = get-date
    if (![String]::IsNullOrEmpty($StartDate))
    {
    # We have a date specified – if no end date, we use yesterday
    $ReportStartDate = [DateTime]::Parse($StartDate)
    if ($EndDate -eq $Null)
    {
    $ReportEndDate = $today.AddDays(-1)
    }
    else
    {
    $ReportEndDate = [DateTime]::Parse($EndDate)
    }
    $reportDate = “$($ReportStartDate.ToShortDateString()) to $($ReportEndDate.ToShortDateString())”
    $reportDate = $reportDate -replace “/”,”-”
    }
    else
    {
    # No specific date specified, so we’ll create a monthly report
    $ReportYear = $today.Year
    if ( $ReportMonth -lt 1 )
    {
    $ReportMonth = $today.AddMonths(-1).Month
    }
    if ($ReportMonth -gt $today.Month) { $ReportYear– }

    $ReportStartDate = New-Object System.DateTime($ReportYear, $ReportMonth, 1, 0,0,0) # First day of report month
    $ReportEndDate = $ReportStartDate.AddMonths(1) # We stop on the first day of the next month (i.e. at 00:00:00)
    $reportDate =”$($ReportStartDate.ToString(“MMMM”)),$ReportYear”
    }

    $rundate = $($today.AddDays(-1)).tolongdatestring()
    Write-Host “Creating report: $reportDate” -ForegroundColor Green

    # Work out the output filename (based on report start date)
    if ($ReportMonth -gt 0)
    {
    $outfile_date = $ReportStartDate.tostring(“yyyy_MM”)
    }
    else
    {
    $outfile_date = $ReportStartDate.tostring(“yyyy_MM_dd”)
    }
    $outfile = “$outfile_date.email_stats.csv”

    # Retrieve our local domains
    $accepted_domains = Get-AcceptedDomain |% {$_.domainname.domain}
    [regex]$dom_rgx = “`(?i)(?:” + (($accepted_domains |% {“@” + [regex]::escape($_)}) -join “|”) + “)$”

    # Get a list of hub transport and mailbox servers (we query all these for tracking logs)
    $hts = get-exchangeserver |? {($_.serverrole -match “hubtransport”) -or ($_.serverrole -match “mailbox”)} |% {$_.name}

    # Now initialise our variables (hash tables) to collect the stats
    $all_user_stats = @{}
    $org_stats = @{}

    # This function gives some user feedback while processing
    function time_pipeline {
    param ($increment = 1000)
    begin{$i=0;$timer = [diagnostics.stopwatch]::startnew()}
    process {
    $i++
    if (!($i % $increment)){Write-host “`rProcessed $i in $([int]$timer.elapsed.totalseconds) seconds…” -nonewline}
    $_
    }
    end {
    write-Host “`rProcessed $i log records in $([int]$timer.elapsed.totalseconds) seconds. ”
    Write-Host ” Average rate: $([int]($i/$timer.elapsed.totalseconds)) log recs/sec.”
    }
    }

    $internal_msgids = @()

    foreach ($ht in $hts)
    {
    Write-Verbose “Executing get-messagetrackinglog -Server $ht -Start “”$reportStartDate”” -End “”$reportEndDate”” -resultsize unlimited”
    $trackingdata = get-messagetrackinglog -Server $ht -Start “$reportStartDate” -End “$reportEndDate” -resultsize unlimited
    $trackingdata | time_pipeline |% {

    if ($_.source -eq “STOREDRIVER”)
    {
    # Directionality is only logged in Exchange 2013. For 2010, we need to work it out
    $directionality = $_.Directionality
    if ($directionality -eq $Null)
    {
    $directionality = “Incoming”
    if ($_.Sender -match $dom_rgx)
    {
    $directionality = “Originating”
    }
    }

    if ($directionality.Equals(“Incoming”) -and $_.eventid.Equals(“DELIVER”))
    {
    # This is an external message being delivered internally

    # Update the user stats
    ForEach ($rcpt in $_.Recipients)
    {
    $userstats = $all_user_stats[$rcpt]
    if ($userstats -eq $Null)
    {
    $userstats = @{}
    }
    $userstats[“Messages received (total)”] += 1
    $userstats[“Messages received (external)”] += 1
    $userstats[“Bytes received (total)”] += $_.TotalBytes
    $userstats[“Bytes received (external)”] += $_.TotalBytes
    $all_user_stats[$rcpt] = $userstats
    }

    # Update the org stats
    $org_stats[“Messages received (total)”] += 1
    $org_stats[“Messages received (external)”] += 1
    $org_stats[“Bytes received (total)”] += $_.TotalBytes
    $org_stats[“Bytes received (external)”] += $_.TotalBytes
    }
    elseif ($directionality.Equals(“Originating”))
    {
    # This message originated internally – it’s either an internal message, or an outgoing one
    if ($_.Sender.Equals(“[email protected]”))
    {
    # Ignore these messages
    }
    else
    {
    if ($_.EventId.Equals(“DELIVER”))
    {
    # This is an internal message being delivered internally

    ForEach ($rcpt in $_.Recipients)
    {
    # Update received stats
    $userstats = $all_user_stats[$rcpt]
    if ($userstats -eq $Null)
    {
    $userstats = @{}
    }
    $userstats[“Messages received (total)”] += 1
    $userstats[“Messages received (internal)”] += 1
    $userstats[“Bytes received (total)”] += $_.TotalBytes
    $userstats[“Bytes received (internal)”] += $_.TotalBytes
    $all_user_stats[$rcpt] = $userstats
    }
    # Update the org stats
    $org_stats[“Messages received (total)”] += 1
    $org_stats[“Messages received (internal)”] += 1
    $org_stats[“Bytes received (total)”] += $_.TotalBytes
    $org_stats[“Bytes received (internal)”] += $_.TotalBytes

    # Update sent stats (i.e. here we retrieve the sender and update accordingly)
    $userstats = $all_user_stats[$_.Sender]
    if ($userstats -eq $Null)
    {
    $userstats = @{}
    }
    $userstats[“Messages sent (total)”] += 1
    $userstats[“Messages sent (internal)”] += 1
    $userstats[“Bytes sent (total)”] += $_.TotalBytes
    $userstats[“Bytes sent (internal)”] += $_.TotalBytes
    $all_user_stats[$_.Sender] = $userstats

    # Update the org stats
    $org_stats[“Messages sent (total)”] += 1
    $org_stats[“Messages sent (internal)”] += 1
    $org_stats[“Bytes sent (total)”] += $_.TotalBytes
    $org_stats[“Bytes sent (internal)”] += $_.TotalBytes
    }
    elseif ($_.EventId.Equals(“RECEIVE”))
    {
    # This is an internal message that has been submitted to transport
    # If the recipients are not internal, then we track this as internal message being sent externally

    $userstats = $all_user_stats[$_.Sender]
    if ($userstats -eq $Null)
    {
    $userstats = @{}
    }
    ForEach ($rcpt in $_.Recipients)
    {
    if (!($rcpt -match $dom_rgx))
    {
    $userstats[“Messages sent (total)”] += 1
    $userstats[“Messages sent (external)”] += 1
    $userstats[“Bytes sent (total)”] += $_.TotalBytes
    $userstats[“Bytes sent (external)”] += $_.TotalBytes
    $all_user_stats[$_.Sender] = $userstats

    # Update the org stats
    $org_stats[“Messages sent (total)”] += 1
    $org_stats[“Messages sent (external)”] += 1
    $org_stats[“Bytes sent (total)”] += $_.TotalBytes
    $org_stats[“Bytes sent (external)”] += $_.TotalBytes
    }
    }
    }
    }
    }
    }
    }
    }

    # Now we have all the data, we export to file

    $OrgStatsExport = $OrgStatsExport -replace “{D}”, $reportDate
    $UserStatsExport = $UserStatsExport -replace “{D}”, $reportDate

    # Export organisation data
    Write-Host “Exporting organisation stats to: $OrgStatsExport” -ForegroundColor Green
    $headers = “”
    $stats = “”
    ForEach ($field in $org_stats.Keys)
    {
    $headers += “,””$field”””
    $stats += “,$($org_stats[$field])”
    }

    if ($headers.Length -gt 0)
    {
    $headers.SubString(1) | Out-File $OrgStatsExport
    $stats.SubString(1) | Out-File $OrgStatsExport -Append
    }

    # Export user data
    $user_stats_fields = @(“Messages received (total)”,”Messages sent (total)”,”Bytes received (total)”,”Bytes sent (total)”,”Messages received (external)”,
    “Messages sent (external)”,”Bytes received (external)”,”Bytes Sent (external)”,”Messages received (internal)”,”Messages sent (internal)”,
    “Bytes received (internal)”,”Bytes Sent (internal)”)

    Write-Host “Exporting user stats to: $UserStatsExport” -ForegroundColor Green
    $headers = “””User””,”””
    $headers += $user_stats_fields -join “””,”””
    $headers += “”””
    $headers | Out-File $UserStatsExport
    ForEach ($user in $all_user_stats.Keys)
    {
    $stats = “””$user”””
    ForEach ($field in $user_stats_fields)
    {
    if ($all_user_stats[$user].ContainsKey($field))
    {
    $stats += “,””$($all_user_stats[$user][$field])”””
    }
    else
    {
    $stats += “,””0″””
    }
    }
    $stats | Out-File $UserStatsExport -Append
    }

    Write-Host “Run time was $(((get-date) – $today).totalseconds) seconds.”

  8. Hi,

    I tried script you say that works, but when I run this for onprem Exch 2010, I get no totals for either Sent/Received. Below is script with me adding the company email addresses.

    [Int] $intSent = $intRec = 0
    Get-TransportServer | Get-MessageTrackingLog -ResultSize Unlimited -Start “10/01/2018” -End “10/31/2018” -Sender “[email protected]” -EventID RECEIVE | ? {$_.Source -eq “STOREDRIVER”} | ForEach { $intSent++ }
    Get-TransportServer | Get-MessageTrackingLog -ResultSize Unlimited -Start “10/01/2018” -End “10/31/2018” -Recipients “[email protected]” -EventID DELIVER | ForEach { $intRec++ }
    Write-Host “E-mails sent: “, $intSent
    Write-Host “E-mails received:”, $intRec

    1. Hi John,

      Have you tried running a more basic/wide search like:
      Get-TransportServer | Get-MessageTrackingLog -ResultSize Unlimited -Start “20/03/2019” -Recipients “[email protected]” -EventID DELIVER

      And checked the result? I assume you have Message Tracking Logs configured to retain the logs for the period you are searching?

      Regards,
      Nuno

  9. Hi John,

    Have you tried running a more basic/wide search like:
    Get-TransportServer | Get-MessageTrackingLog -ResultSize Unlimited -Start “20/03/2019” -Recipients “[email protected]” -EventID DELIVER

    And check the result? I assume you have Message Tracking Logs configured to retain the logs for the period you are searching?

    Regards,
    Nuno

  10. Thx for those commands, but I have a question, why I get different numbers using the eventID and no using it? what’s the difference? thanks again!

Leave a Comment

Your email address will not be published.

This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

Scroll to Top