In Exchange Server environments where mailbox audit logging is used there may be a need to regularly generate reports of mailbox audit log data. I’ve written a PowerShell script, Get-MailboxAuditLoggingReport.ps1 to perform this task.

Although mailbox audit log reports can be created in the Exchange Admin Center the interface is not as fast to use as PowerShell, and it can’t be scheduled to run automatically for regular reports like a script can.

This script will generate a report of the mailbox audit log entries for a specified mailbox, for a period of time (the last 24 hours by default), and save the full results to CSV as well as a summary of the data to a HTML file. The script can also be used to send the results via email with the CSV data attached.

mailbox-audit-log-report-example

This script is available on the TechNet Script Gallery and Github. Comments are welcome below. If you find a bug please consider raising it as an issue on Github.

About the Author

Paul Cunningham

Paul is a former Microsoft MVP for Office Apps and Services. He works as a consultant, writer, and trainer specializing in Office 365 and Exchange Server. Paul no longer writes for Practical365.com.

Comments

  1. Asim

    thanks a lot Paul, this is a very helpfull script

  2. mark

    Hi Paul,

    Seems i cant get the email to send, running in 365, it mentions the Send-MailMessage cmdlet is obsolete can we get around this?

    Thanks
    Mark

  3. Warren

    Hello Paul

    Real fan of the site, you are the reason i have improved my mastery of all things server in the last 2 years, keep up the great articles.

    I have a quick Question does this report work of Office365 exchange online or is there perhaps an alternative script you could recommend based on a similar scenario below.

    The scenario is that we have a high priority mailbox with delegates assigned. Mails are sent by these delegates daily and the senior manager wants to keep a closer eye on who is sending these mails. We unfortunately cannot assign mail signatures to these mails due to company branding, internal policy and some concerns from the POPI act that have cropped up from legal. The tracking is critical for KPI’s for the assigned delegates as well as reviewing customer\Vendor interactions with the team.

    So its present a bit of a headache to try and find the right solution as the one method i found doesn’t supply date\time, mail subject and delegate who sent the mail over the last 24 hours. I would like to assist this manager but Ive struggled to setup something around this that will work, let alone autonomously.

    Would appreciate any advise you could offer or perhaps nudge me into the right direction with this as im eager to learn, rather than be spoon fed on issues.

  4. SJ

    Hi Paul,

    I would like to get a report for last two months. Is it possible to change the hours mentioned in the script. I did try to change the hours to 2000. It gives no audit logs. Whereas for last 36 hours, it shows the report.

    can you please advise ?

  5. Nicolas Carson

    Do you have a modified version of this script that would work with exchange 2016 with the New-MailboxauditLogSearch command? I am trying to update this script now to the new command myself but if there is a new version already I would appreciate the help.

  6. barth

    Big thanks Paul.
    Yes, I’m using your script.
    I have been able to filter out what I need by piping your script to:
    “Where-Object {$_.FolderPathName -notlike “*\Drafts*” -and $_.operation -ne “SendAs” -and $_.operation -ne “Update” -and $_.Operation -ne “Create”}”

    Thanks once again and have a great weekend 😉

  7. Gary Jackson

    I love this! How would we modify it so it could run against multiple mailboxes and and provide that in the report rather than having to run it many times with different users?

    Thanks again,
    Gary

    1. Avatar photo
      Paul Cunningham

      Yes. If you look into how to make the -Mailbox parameter take pipeline input, and using begin/process/end, you could process multiple mailboxes at once. Whether you output all that to a single report file or one file per mailbox I’ll leave up to you, as I’m not sure which would be best.

      1. Gary

        Could we do this against a group possibly this way as well?

        1. Avatar photo
          Paul Cunningham

          Almost anything is possible. Write some logic that expands the group membership into a list of mailboxes, then loops through the list to retrieve each mailbox’s audit log entries.

          1. barth

            Thanks so much for the wonderful job. I’m trying to find a means to exclude the “\Drafts” folder in the log.
            This is because messages previously saved in the Draft folder and sent afterwards are considered as Delete operation

          2. Avatar photo
            Paul Cunningham

            The audit settings are mailbox-wide, so you can’t exclude a folder from audit logging. But in your reporting, whether you’re using my script or something else, you could just add some logic to exclude entries matching that folder.

  8. Yuksel BASTAN

    hi @ all,
    theer is great work from Paul in this link :
    https://github.com/cunninghamp/Get-MailboxAuditLoggingReport.ps1

    but i have a question for this script. Is it possible to add a funtion that shows me the mail adres to whom our personal send the mail? i mean i want to add a line too for MailTo . I tryed ” $reportObj | Add-Member NoteProperty -Name “Mail To” -Value $entry.MailTo ” but didnt worked.

    foreach ($entry in $auditlogentries)
    {
    $reportObj = New-Object PSObject
    $reportObj | Add-Member NoteProperty -Name “Mailbox” -Value $entry.MailboxResolvedOwnerName
    $reportObj | Add-Member NoteProperty -Name “Mailbox UPN” -Value $entry.MailboxOwnerUPN
    $reportObj | Add-Member NoteProperty -Name “Timestamp” -Value $entry.LastAccessed
    $reportObj | Add-Member NoteProperty -Name “Accessed By” -Value $entry.LogonUserDisplayName
    $reportObj | Add-Member NoteProperty -Name “Operation” -Value $entry.Operation
    $reportObj | Add-Member NoteProperty -Name “Result” -Value $entry.OperationResult
    $reportObj | Add-Member NoteProperty -Name “Folder” -Value $entry.FolderPathName
    if ($entry.ItemSubject)
    {
    $reportObj | Add-Member NoteProperty -Name “Subject Lines” -Value $entry.ItemSubject
    }
    else
    {
    $reportObj | Add-Member NoteProperty -Name “Subject Lines” -Value $entry.SourceItemSubjectsList
    }

    $report += $reportObj
    }

    thank you very much.

  9. Tariq

    Hi

    can you plz verify the smtp setting, its with $ or without $ coz with dollor its giving errors.

    $smtpsettings = @{
    To = $MailTo
    From = $MailFrom
    Subject = $reportemailsubject
    SmtpServer = $MailServer
    }

  10. Richard

    Hi l have ran this before with no issues but now l receive the error below. I do not think i have ran this since updating to CU12. Anyone else come across this?

    Search-MailboxAuditLog : The Exchange Web Service endpoint for LegacyDn: /o=******** Exchange Organization/ou=Exchange
    Administrative Group (*************)/cn=Recipients/cn=4b622569157f4dac90322e6a92e, RecipientType: UserMailbox,
    RecipientTypeDetails: RoomMailbox, Selected Mailbox: Display Name: ******************, Mailbox Guid:
    7d1ebae6-35c7-4450-a5d3-916120726501, Database: 18b0b34b-70e0-4b11-907f-5436aaf41fa3, Location: ServerFqdn:
    ********.*********.***, ServerVersion: 1941996698, DatabaseName: ****************,
    HomePublicFolderDatabaseGuid: 00000000-0000-0000-0000-000000000000 could not be found.
    At C:Program FilesMicrosoftExchange ServerV15scriptsGet-MailboxAuditLoggingReport.ps1:139 char:20
    + $auditlogentries = Search-MailboxAuditLog -Identity $identity -LogonTypes Delega …
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : NotSpecified: (:) [Search-MailboxAuditLog], FailedToFindEwsEndpointException
    + FullyQualifiedErrorId : [Server=************,RequestId=adde4884-a7e6-4561-ad6f-d22502055aea,TimeStamp=05/09/20
    16 10:51:50] [FailureCategory=Cmdlet-FailedToFindEwsEndpointException] 56002926,Microsoft.Exchange.Management.Syst
    emConfigurationTasks.SearchMailboxAuditLog

  11. Rob

    Hi Paul, any chance you have the same for Admin Audit logs?
    Would be very handy to schedule both of these weeklymonthly.
    Thanks

  12. Simon

    Hello, i use your script to check the access to a mailbox from a “delegate”
    First i use this command:
    Set-Mailbox -Identity “HD Settimo” -AuditDelegate Folderbind -AuditEnabled $true
    Then i run your script
    D:scriptGet-MailboxAuditLoggingReport.ps1 -mailbox “HD Settimo”
    The script run Well , but the result is not corret
    For example, i access with my user to a “help desk mailbox” (i have full access), but the result in AuditLogEntries.html is not correct

    I access at 18:34 but in the file the time recorded is 18:12.
    If i access again, and re.run the script the time remain 18:12

    Thanx for your help, best regards

    Simone

  13. Wilbert

    Is it possible to add the date of affected appointment?
    We have a lot of appointments with the same subject. Therefore it would be nice to know the date (and if possible start time) of the appointment that is changed.

  14. Robert

    Do you have a version of this for Exchange Online?

  15. Suzanne Bejsovec

    We enabled Owner audit for all actions. To get that to show in the reports I had to remove the ‘-LogonTypes Delegate’ from this line in your script:

    $auditlogentries = Search-MailboxAuditLog -Identity $identity -LogonTypes Delegate -StartDate (Get-Date).AddHours(-$hours) -ShowDetails

  16. AMGHAR

    Hello,

    Can we generte an xml report?? thanks in advance

  17. Ahmad

    I’m gettting results, but the subject is not showing.
    how can i get the subject of the email in the log?

    1. Avatar photo
      Paul Cunningham

      It works fine in my environments, so I’m not sure why it isn’t for you.

      What are the operations that aren’t showing subject lines?

  18. kjstech

    Hmm, well if I specify the email server’s IP address it works. Problem solved. I was specifying the FQDN and when that didn’t work, just the server’s name.

    Now, can we make a simular powershell command that will output administrative auditing to an html / csv, that could be emailed? The users thing is great, but we don’t want to have to click compliance management > auditing > run the admin audit log report… every day.

    Thanks!

  19. kjstech

    I’d like to put this in task scheduler to email a daily report to key IT and CIO users for auditing purposes. However I cannot get the email function to work. I can get it to generate the html and csv file on the C: drive of the Exchange server, but when I specify -SendEmail, -MailFrom, -MailTo and -MailServer switches, I get this error.

    Send-MailMessage : Service not available, closing transmission channel. The server response was: 4.3.2 Service not
    available
    At C:scriptsGet-MailboxAuditLoggingReport.ps1:199 char:6
    + Send-MailMessage @smtpsettings -Body $htmlreport -BodyAsHtml -Encoding ([Sy …
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : InvalidOperation: (System.Net.Mail.SmtpClient:SmtpClient) [Send-MailMessage], SmtpExcept
    ion
    + FullyQualifiedErrorId : SmtpException,Microsoft.PowerShell.Commands.SendMailMessage

  20. Paul

    Hi Paul,

    Great work, love the site it is massively useful. Can I run the audit script across all mailboxes or do you have specify a mailbox?

    Thanks,
    Paul.

  21. Eissa

    Hi Paul,

    Is there a way to exclude some logs,
    For example, if the mailbox accessed by specific user do not include it in the report.
    Am asking for that because we have a specific account which use for mailboxes archiving and in need to exclude this account form appearing in the logs.

  22. Hisham Mezher

    Good Day Paul,

    I first want to thank you for all the information and scripts you provide, love your work.

    regarding the Get-MailboxAuditLoggingReport.ps1 i want to know how can I schedule this to run for like 20 shared mailboxes each to be sent to the mailbox owner.

    Let us know please,

    Thanks a lot for your feedback.

    Regards;
    Hisham

  23. Mario

    Hello Paul,
    I want to run this Script on Exchange 2010.

    Is this Script only for Exchange 2013.

    The erreo Message is:
    Der Operator “<" will be not yet supported

    Thanks for help.

    1. Avatar photo
      Paul Cunningham

      It should work. If you tried to download the script from Github I’d say you accidentally got a bunch of HTML code from the Github website mixed in there.

  24. Akshay

    HELLLLLLLLLLO PAUL

    FIRTS OF ALLL YOUR BLOGS ARE SAVIORS MANY TIMES WHEN M CLUE LESS; THANK YOU VERY MUCH FOR ALL YOUR WORK THAT YOU SHARE WITH US

    QUESTION:-
    i am trying to list all mailboxes which are on exchange 2013 i have a mix environment with 2007 … m sorry if m asking something very basic but m not able to figure out since i only know that they will have a different admin display version

    1. Avatar photo
      Paul Cunningham

      On the 2013 server if you run Get-MailboxDatabase it should only return Exchange 2013 databases, So you can pipe that into Get-Mailbox to see just the Exchange 2013 mailboxes.

      Eg, Get-MailboxDatabase | Get-Mailbox

  25. Lubos

    Hello,

    Can you help me. I need to find out who created the mailbox on Exchange Server 2010. What is the appropriate command shell in power. Thanks for the help.

    1. Avatar photo
      Paul Cunningham

      You’ll need to look at searching the Admin Audit Log, which is different to the Mailbox Audit Log, but easy to find information about.

  26. Nino Iaccarino

    Hi, sorry about that.

    Basically, if I run the command and specify a user I know definitely has audit entries, no results are returned.

    When I ran it without specifying a user, I could see in the exported csv the same user but with the entries I was expecting.

    It seems when I specify a user in the command, it returns 0 results even if there are results.

    1. Avatar photo
      Paul Cunningham

      How do you know they definitely have audit entries? What are you basing that on? Manual searches? Folder statistics?

  27. Nino Iaccarino

    I am also not having much luck and I’m not sure what I am doing wrong ? I have enabled auditing on my account just to see some results, but I don’t get any. I should have at least something logged ? This is what my account looks like.

    AuditEnabled : True
    AuditLogAgeLimit : 90.00:00:00
    AuditAdmin : {Update, Move, MoveToDeletedItems, SoftDelete, HardDelete, FolderBind, SendAs, SendOnBehalf, Create}
    AuditDelegate : {Update, SoftDelete, HardDelete, SendAs, Create}
    AuditOwner : {Update, Move, MoveToDeletedItems, SoftDelete, HardDelete, Create}

    I ran the command without specifying a user, and I do get something output to the auditlogentries.html
    and the output does have some details about a particular user.

    Mailbox

    Mailbox UPN

    Timestamp

    Accessed By

    Operation

    Result

    Folder

    Subject Lines

    info ’emailaddress’ 11/05/2015 11:16:02 AM First Name Last Name SoftDelete Succeeded Inbox

    I then run the command against her, and then I get:

    [PS] C:scripts>.Get-MailboxAuditLoggingReport.ps1 -Mailbox ‘username’ -Hours 200
    Searching ‘username’ for last 200 hours.
    No audit log entries found.
    Finished.

    So, it looks as though Exchange is logging correctly (as auditing is enabled) but the command isn’t outputting the info :/

    Help !!

    1. Avatar photo
      Paul Cunningham

      Specifying a mailbox is required, that switch should be mandatory. I’ll fix that in the script.

      Other than that, you’ve obfuscated too much for me to even begin to grasp what you’re seeing. The script only does the hard work of a normal audit log search, so you should go do some manual searches via PowerShell or the Exchange Admin Center to compare results.

  28. Buch

    Could you please add to script possibility to find audit log information for list of mailboxes and for all mailboxes, that have audit enabled, for example like that:
    Get-Mailbox -ResultSize unlimited | where {($_.AuditEnabled -eq $true)}

  29. MS

    Is there any specific reason why we are loading Microsoft.Exchange.Management.PowerShell.E2010 PSSnapin in Exchange 2010 environment? I remember reading article on blogs.technet.com about that not being needed.

    Thanks.

    1. Avatar photo
      Paul Cunningham

      Not sure what you mean… the script relies on Exchange cmdlets so it won’t work if the cmdlets aren’t available.

  30. Rocky

    I confirmed “AuditEnabled” is set to “True” on all my mailboxes in my Exchange 2013 Organization but when I run the script, it states that there is “No audit log entries found”.

    .Get-MailboxAuditLoggingReport.ps1 -Mailbox testuser -Hours 48 -SendEmail -MailFrom ExchangeAuditReport@crabel.com -MailTo testuser@crabel.com -MailServer mail

    I ran this on my Win8.1 box that has the Exchange 2013 management tools. I then tried to run the script on a CAS box and same result:

    Searching testuser for last 48 hours.
    No audit log entries found.
    Finished.

    Why wouldn’t there be any log entries found????

    1. Markus

      Paul – I’m seeing the same results (no audit log entries found). We have the settings in place for Admin, Delegate, and Owner auditing.

      1. pradeep sharma

        Markus i am also facing same issue. what you have done to fix this issue ? while running this PS file i am getting error message “File skipped because it was already present from “Microsoft.PowerShell”.” and then after command is getting finished with result “No audit log entries found.
        Finished.”

        1. Sid

          To all that keep seeing “No audit log entries found”:

          I too had the same issue. The script by default only checks for the LogonTypes of “Delegate”. In my case there was no activity done by a delegate and that’s why it kept showing up with “No audit log entries found”.

          So all you need to do is change the -LogonTypes parameter to “Owner” or “Admin”, whoever you are trying to audit. In my case it was Owner. This should be done in line 139 of the script:

          $auditlogentries = Search-MailboxAuditLog -Identity $identity -LogonTypes Owner -StartDate (Get-Date) .AddHours (-$hours) -ShowDetails

Leave a Reply