diff --git a/Security/ExchangeExtendedProtectionManagement/index.html b/Security/ExchangeExtendedProtectionManagement/index.html index 982a387903..2ecd767b94 100644 --- a/Security/ExchangeExtendedProtectionManagement/index.html +++ b/Security/ExchangeExtendedProtectionManagement/index.html @@ -3283,6 +3283,10 @@
Download the latest release: ExchangeExtendedProtectionManagement.ps1
The Exchange Extended Protection Management is a script to help automate the Extended Protection feature on the Windows Authentication Module on Exchange Servers. Prior to configuration, it validates that all servers that we are trying to enable Extended Protection on and the servers that already have Extended Protection enabled have the same TLS settings and other prerequisites that are required for Extended Protection to be enabled successfully.
+Tip
+The Exchange Server Extended Protection documentation can be found on the Microsoft Learn platform: Configure Windows Extended Protection in Exchange Server
+The user must be in Organization Management
and must run this script from an
elevated Exchange Management Shell (EMS) command prompt.
This project contains scripts for supporting and troubleshooting Microsoft Exchange Server.
"},{"location":"#popular-scripts","title":"Popular Scripts","text":"Script Docs Download HealthChecker.ps1 Docs Download ExchangeExtendedProtectionManagement.ps1 Docs Download SetupAssist.ps1 Docs Download SourceSideValidations.ps1 Docs Download Test-AMSI.ps1 Docs Download"},{"location":"Emerging-Issues/","title":"Emerging Issues for Exchange On-Premises","text":"This page lists emerging issues for Exchange On-Premises deployments, possible root cause and solution/workaround to fix the issues. The page will be consistently updated with new issues found and reflect current status of the issues mentioned.
Updated on Update causing the issue Issue Workaround/Solution 11/23/2023 November 2023 Security Update for Exchange 2016, Exchange 2019 Some customers may find queue viewer crashing with error \"Failed to enable constraints. One or more rows contain values violating non-null, unique, or foreign-key constraints\" The error can occur if the Exchange server auth certificate has expired. Solution is to renew the Exchange server auth certificate manually or by using this script 10/12/2023 All versions of August 2023 Security Update for Exchange 2016, Exchange 2019 Users in account forest can't change expired password in OWA in multi-forest Exchange deployments after installing any version of August 2023 Security Update for Exchange servers Note The account forest user will be able to change the password after they sign in to Outlook on the web if their password is not yet expired. The issue affects only account forest users who have passwords that are already expired. This change does not affect users in organizations that don't use multiple forests. ** Update on 10/12/2023 ** Follow steps on this article 8/15/2023 Non-English August 2023 Security Update for Exchange 2016, Exchange 2019 When you install the Microsoft Exchange Server 2019 or 2016 August 2023 Security Update (SU) on a Windows Server-based device that is running a non-English operating system (OS) version, Setup suddenly stops and rolls back the changes. However, the Exchange Server services remain in a disabled state. The latest SUs have been released that do not require a workaround to install. If you used a workaround to install KB5029388, it is highly recommend to uninstall the KB5029388 to avoid issues down the line. For more information please check out this KB. 6/15/2023 January 2023 Security Update for Exchange 2016, Exchange 2019 When you try to uninstall Microsoft Exchange Server 2019 or 2016 on servers, that had January 2023 Security Update for Exchange Server installed at any point, the Setup fails with following error message: [ERROR] The operation couldn't be performed because object '' couldn't be found on ''. Install Exchange Security Update June 2023 or higher to resolve the issue. Check this KB for more details 6/15/2023 Extended protection enabled on Exchange server Changing the permissions for Public Folders by using an Outlook client will fail with the following error, if Extended Protection is enabled:The modified Permissions cannot be changed.
Install Exchange Security Update June 2023 or higher Security Update and create the setting override mentioned in this KB 3/16/2023 Outlook client update for CVE-2023-23397 released These vulnerabilities affect Exchange Server. Exchange Online customers are already protected from the vulnerabilities addressed in these SUs and do not need to take any action other than updating Exchange servers in their environment, and if applicable, installing the security update for Outlook on Windows described on the link on the right.More details about specific CVEs can be found in the Security Update Guide (filter on Exchange Server under Product Family).Awareness: Outlook client update for CVE-2023-23397 releasedThere is a critical security update for Microsoft Outlook for Windows that is required to address CVE-2023-23397. To address this CVE, you must install the Outlook security update, regardless of where your mail is hosted (e.g., Exchange Online, Exchange Server, some other platform). Please check this page for FAQs about the Outlook CVE-2023-23397 3/14/2023 February 2023 Security Update for Exchange 2016, Exchange 2019, Exchange 2013 After installing February 2023 security update, customers are seeing EWS application pool crash with Event ID 4999 with following error E12IIS, c-RTL-AMD64, 15.01.2507.021, w3wp#MSExchangeServicesAppPool, M.Exchange.Diagnostics, M.E.D.ChainedSerializationBinder.EnforceBlockReason, M.E.Diagnostics.BlockedDeserializeTypeException, 437c-dumptidset, 15.01.2507.021. The issue is causing connectivity issues to EWS based clients (Outlook for Mac) Update on 3/14/2023 The issue is fixed in March 2023 security update for Exchange servers Please follow the steps in this KB 3/14/2023 February 2023 Security Update for Exchange 2016, Exchange 2019, Exchange 2013 Some customers are reporting issues with Outlook/OWA add-ins, like add-in not listing in EAC or with the Get-App command. Additionally, they may notice EWS application pool crash with Event ID 4999 in the application log of the Exchange server. Update on 3/14/2023 The issue is fixed in March 2023 security update for Exchange servers 3/14/2023 January 2023 Security Update for Exchange 2016, Exchange 2019 The Exchange toolbox may start crashing on launch after certificate Serialization for PowerShell is enabled. The error noticed is \"Deserialization fails: System.Reflection.TargetInvocationException\". The issue happens only on Exchange 2016 and Exchange 2019 Update on 3/14/2023 The issue is fixed in March 2023 security update for Exchange servers - - - - 1/24/2023 January 2023 Security Update for Exchange 2016, Exchange 2019 After installing January 2023 security update and enabling certificate signing for serialization of PowerShell, you may find various Exchange commands and scripts (example: RedistributeActiveDatabases.ps1) that use deserialization failing with the error similar to : Error: \"Cannot convert the value of type.....to type\" Use this script to update the auth certificate 1/24/2023 January 2023 Security Update for Exchange 2016, Exchange 2019 RecoverServer will fail at pre-requisites check with following error: \"Exchange Server version Version 15.1 (Build 2507.17) or later must be used to perform a recovery of this server.\" Update on 02/23/2023 The issue has been fixed in February 2023 Security Update for Exchange servers, however, the following workaround still needs to be used for servers that are on January 2023 Security Update Workaround Use the steps in this article 1/24/2023 January 2023 Security Update for Exchange 2016 installed on Windows 2012 R2, other versions are not affected The Exchange services in Automatic start-up mode will not start after reboot of the server. The services start successfully if started manually Update on 02/23/2023The issue has been fixed in February 2023 Security Update for Exchange servers 1/24/2023 January 2023 Security Update for Exchange 2016, Exchange 2019 Transport header shows the older version of server once January 2023 SU is installed (the build shown seems to be the build of the last CU) The issue will be addressed in upcoming security update Updated on 11/8/2022
Issue Possible reason Workaround/Solution Zero-day vulnerabilities reported in Microsoft Exchange Server, CVE-2022-41040 and CVE-2022-41082 N/A Install November 2022 Exchange Server Security Updates to address the vulnerabilityUpdated on 5/11/2022
Issue Possible reason Workaround/Solution After installing March 2022 Security Update For Exchange Server 2013, 2016, 2019, the Microsoft Exchange Service Host service may crash repeatedly with Event ID 7031 in system log and Event ID 4999 in application log. Event ID 4999 Watson report about to be sent for process id: 4564, with parameters: E12IIS, c-RTL-AMD64, 15.01.2375.024, M.Exchange.ServiceHost, M.Exchange.Diagnostics, M.E.D.ChainedSerializationBinder.LoadType, M.E.Diagnostics.BlockedDeserializeTypeException, c0e9-DumpTidSet, 15.01.2375.024. The issue can occur if there are any expired certificates present on or any certificates nearing expiry on the server Install May 2022 Exchange Server Security Updates to resolve the issueUpdated on 3/16/2022
Issue Possible reason Workaround/Solution After installing March 2022 Security Update For Exchange Server 2013, 2016, 2019, the Microsoft Exchange Service Host service may crash repeatedly with Event ID 7031 in system log and Event ID 4999 in application log. Event ID 4999 Watson report about to be sent for process id: 4564, with parameters: E12IIS, c-RTL-AMD64, 15.01.2375.024, M.Exchange.ServiceHost, M.Exchange.Diagnostics, M.E.D.ChainedSerializationBinder.LoadType, M.E.Diagnostics.BlockedDeserializeTypeException, c0e9-DumpTidSet, 15.01.2375.024. The issue can occur if there are any expired certificates present on or any certificates nearing expiry on the server Update 3/16/2022 Follow the steps from KB 5013118 to resolve the issue"},{"location":"Emerging-Issues/#old-issues","title":"Old Issues","text":""},{"location":"Emerging-Issues/#email-stuck-in-transport-queues","title":"Email Stuck in Transport Queues","text":"Issue Possible reason Workaround/Solution You may observe emails building up in the transport queues of Exchange Server 2016 and Exchange Server 2019. The issue does not impact Exchange 2013 servers.Following events may be noticed in the application log: Log Name: ApplicationSource: FIPFSLogged: 1/1/2022 1:03:42 AM Event ID: 5300 Level: Error Computer: server1.contoso.comDescription: The FIP-FS \"Microsoft\" Scan Engine failed to load. PID: 23092, Error Code: 0x80004005.Error Description: Can't convert \"2201010001\" to long. Log Name: Application Source: FIPFS Logged: 1/1/2022 11:47:16 AM Event ID: 1106 Level: Error Computer: server1.contoso.com Description: The FIP-FS Scan Process failed initialization. Error: 0x80004005. Error Details: Unspecified error. The problem relates to a date check failure with the change of the new year and it not a failure of the AV engine itself. This is not an issue with malware scanning or the malware engine, and it is not a security-related issue. The version checking performed against the signature file is causing the malware engine to crash, resulting in messages being stuck in transport queues. Run this script on each Exchange server in your organization. You can run this script on multiple servers in parallel. Check this article for detailed steps."},{"location":"Emerging-Issues/#november-2021-security-update","title":"November 2021 Security Update","text":"Following are the known issues after installing November 2021 Security Updates for Exchange On-Premises servers
Issue Possible reason Workaround/Solution Hybrid OWA Redirect is broken after application of November SU for Exchange 2013/2016 and 2019. Users using Exchange 2016 and 2019 server will see error \":-( Something went wrong. We can't get that information right now. Please try again later. Exchange 2013 users will see error \"External component has thrown an exception.\" Some On-Premises environments, that are not using FBA, may also see cross-site OWA redirection fail with similar errors. After installing November SU, the OWA redirection URL for hybrid users is providing an encoded URL for &., causing the redirect to fail Update 1/12/2022 The OWA redirection issue is fixed in January 2022 security updates. Please install the relevant update to fix the issue. Alternatively, you can also use the workarounds provided in KB article 5008997"},{"location":"Emerging-Issues/#september-cumulative-updates","title":"September Cumulative Updates","text":"Following are the known issues after installing September 2021 Cumulative Updates for Exchange On-Premises servers
Issue Possible reason Workaround/Solution After installing the September 2021 CU, the Microsoft Exchange Transport Services will continue to crash. You can see the following message for the 4999 crash eventWatson report about to be sent for process id: 10072, with parameters: E12IIS, c-RTL-AMD64, 15.02.0986.005, MSExchangeDelivery, M.Exchange.Transport, M.E.T.AcceptedDomainTable..ctor, System.FormatException, 28d7-DumpTidSet, 15.02.0986.005.
Having a Wild Card Only (*) Accepted Domain Set on an Internal Relay. This is an open relay and is very bad to have set. Remove the Accepted Domain that is set to *
and properly configure an anonymous relay on a receive connector or change to an External Relay. More Information: Allow anonymous relay on Exchange servers"},{"location":"Emerging-Issues/#july-2021-security-updatecumulative-updates","title":"July 2021 Security Update/Cumulative Updates","text":"Following are the known issues after installing July 2021 Security Updates/Cumulative Updates for Exchange On-Premises servers
Issue Possible reason Workaround/Solution OWA/ECP stops working after installing July Security Update with following error: ASSERT: HMACProvider.GetCertificates:protectionCertificates.Length<1 The issue occurs if OAuth certificate is missing or expired Follow steps on this article to re-publish the Oauth certificate. Do note it takes up to an hour for certificate to change place OWA/ECP stops working when accessed from load balanced URL, but works if directly accessed from the server URL The root cause for the issue is under investigation Follow steps in this article to fix the issue PrepareAD with Exchange 2016 CU21/Exchange 2019 CU10 error: Used domain controller dc1.contoso.com to read object CN=AdminSDHolder,CN=System,DC=Contoso,DC=COM. [ERROR] Object reference not set to an instance of an object. The issue is under investigation Follow steps in this article to fix the issue PrepareSchema in environments that have empty root AD domain July Security Update for Exchange 2013 have shipped schema changes and needs Exchange role installed for PrepareSchema, this makes it difficult for environments that have Exchange 2013 as the highest installed Exchange server and do not have an Exchange server installed in the same AD site as that of root AD domain. Option 1 Introduce a new server that meets system requirements for Exchange 2013 Management tools, in the root AD domain. Install just the Exchange 2013 Management Tools role on this server. Install the July security fix, perform Schema update. Option 2 PrepareSchema using Exchange 2016 21/Exchange 2019 CU10 media, as the CU's have the changes. However, once Exchange 2016/2019 media is used to perform schema update, you will need to continue using Exchange 2016/2019 media in the future as well. The Schema Version number for Exchange 2013 environment remains on 15312, even after installing SU and performing PrepareSchema This is expected behavior. The schema version is going to remain 15312 after installing Security Update and performing PrepareSchema After installing Exchange 2016 CU21/Exchange 2019 CU10, the values added to custom attributes using EAC are not retained. The scenario works fine in Exchange 2016 CU20/Exchange 2019 CU9 The issue is under investigation Workaround 1: Use EAC from Internet Explorer Workaround 2: Add the values using Exchange Management Shell"},{"location":"Admin/Clear-MailboxPermission/","title":"Clear-MailboxPermission","text":"Download the latest release: Clear-MailboxPermission.ps1
Attempting to Add-MailboxPermission or Remove-MailboxPermission sometimes fails with the following message:
The ACL for object is not in canonical order (Deny/Allow/Inherited) and will be ignored.
This indicates that the ACEs that make up the ACL do not follow canonical ordering, which generally means denies before allows, and explicit before inherited. When the mailbox security descriptor is in this state, the cmdlets can no longer modify it.
This script can be used to return it to a working state. The script does this by clearing all permissions and resetting it to the default permissions that a brand new mailbox would have.
"},{"location":"Admin/Clear-MailboxPermission/#common-usage","title":"Common Usage","text":"The easiest way to use the script is to pipe the affected mailboxes to it:
Get-Mailbox joe@contoso.com | .\\Clear-MailboxPermission.ps1
Note the script also supports -WhatIf and -Confirm. It will prompt for confirmation by default.
"},{"location":"Admin/CrossTenantMailboxMigrationValidation/","title":"CrossTenantMailboxMigrationValidation","text":"Download the latest release: CrossTenantMailboxMigrationValidation.ps1
"},{"location":"Admin/CrossTenantMailboxMigrationValidation/#description","title":"DESCRIPTION","text":"This script offers the ability to validate users and org settings related to the Cross-tenant mailbox migration before creating a migration batch and have a better experience.
It will help you on:
The script will prompt you to connect to your source and target tenants for EXO and AAD as needed You can decide to run the checks for the source mailbox and target MailUser (individually or by providing a CSV file), for the organization settings described above, collect the source information and compress it to a zip file that can be used by the target tenant admins, or use the collected zip file as a source to validate the target objects and configurations against it.
Additionally, the script provides a version check feature that will check if there's a newer version available on CSS-Exchange repository and will download it if so. If for some reason the version cannot be checked, the build check will be skipped and the existing file will be used.
"},{"location":"Admin/CrossTenantMailboxMigrationValidation/#pre-requisites","title":"PRE-REQUISITES:","text":"This will allow you to skip the version check and run the existing local version of the script. This parameter is optional.
"},{"location":"Admin/CrossTenantMailboxMigrationValidation/#scriptupdateonly","title":"ScriptUpdateOnly","text":"This will allow you to check if there's a newer version available on CSS-Exchange repository without performing any additional checks, and will download it if so. This parameter is optional.
"},{"location":"Admin/CrossTenantMailboxMigrationValidation/#checkobjects","title":"CheckObjects","text":"This will allow you to perform the checks for the Source Mailbox and Target MailUser objects you provide. If used without the \"-CSV\" parameter, you will be prompted to type the identities.. If used with the '-SourceIsOffline' you also need to specify the '-PathForCollectedData' parameter
"},{"location":"Admin/CrossTenantMailboxMigrationValidation/#csv","title":"CSV","text":"This will allow you to specify a path for a CSV file you have with a list of users that contain the \"SourceUser, TargetUser\" columns. An example of the CSV file content would be:
SourceUser, TargetUser\nJdoe@contoso.com, Jdoe@fabrikam.com\nBSmith@contoso.com, BSmith@fabrikam.com\n
If Used along with the 'CollectSourceOnly' parameter, you only need the 'SourceUser' column.
"},{"location":"Admin/CrossTenantMailboxMigrationValidation/#checkorgs","title":"CheckOrgs","text":"This will allow you to perform the checks for the source and target organizations. More specifically the organization relationship on both tenants, the migration endpoint on target tenant and the existence of the AAD application needed.
"},{"location":"Admin/CrossTenantMailboxMigrationValidation/#sdp","title":"SDP","text":"This will collect all the relevant information for troubleshooting from both tenants and be able to send it to Microsoft Support in case of needed.
"},{"location":"Admin/CrossTenantMailboxMigrationValidation/#logpath","title":"LogPath","text":"This will allow you to specify a log path to transcript all the script execution and it's results. This parameter is mandatory.
"},{"location":"Admin/CrossTenantMailboxMigrationValidation/#collectsourceonly","title":"CollectSourceOnly","text":"This will allow you to specify a CSV file so we can export all necessary data of the source tenant and mailboxes to migrate, compress the files as a zip file to be used by the target tenant admin as a source for validation against the target. This parameter is mandatory and also requires the '-CSV' parameter to be specified containing the SourceUser column.
"},{"location":"Admin/CrossTenantMailboxMigrationValidation/#pathforcollecteddata","title":"PathForCollectedData","text":"This will allow you to specify a path to store the exported data from the source tenant when used along with the 'CollectSourceOnly' and 'SDP' parameters transcript all the script execution and it's results. This parameter is mandatory.
"},{"location":"Admin/CrossTenantMailboxMigrationValidation/#sourceisoffline","title":"SourceIsOffline","text":"With this parameter, the script will only connect to target tenant and not source, instead it will rely on the zip file gathered when running this script along with the 'CollectSourceOnly' parameter. When used, you also need to specify the 'PathForCollectedData' parameter pointing to the collected zip file.
"},{"location":"Admin/CrossTenantMailboxMigrationValidation/#examples","title":"EXAMPLES","text":""},{"location":"Admin/CrossTenantMailboxMigrationValidation/#example-1","title":"EXAMPLE 1","text":".\\CrossTenantMailboxMigrationValidation.ps1 -CheckObjects -LogPath C:\\Temp\\LogFile.txt\n
This will prompt you to type the source mailbox identity and the target identity, will establish 2 EXO remote powershell sessions (one to the source tenant and another one to the target tenant), and will check the objects.
"},{"location":"Admin/CrossTenantMailboxMigrationValidation/#example-2","title":"EXAMPLE 2","text":".\\CrossTenantMailboxMigrationValidation.ps1 -CheckObjects -CSV C:\\Temp\\UsersToMigrateValidationList.CSV -LogPath C:\\Temp\\LogFile.txt\n
This will establish 2 EXO remote powershell sessions (one to the source tenant and another one to the target tenant), will import the CSV file contents and will check the objects one by one.
"},{"location":"Admin/CrossTenantMailboxMigrationValidation/#example-3","title":"EXAMPLE 3","text":".\\CrossTenantMailboxMigrationValidation.ps1 -CheckOrgs -LogPath C:\\Temp\\LogFile.txt\n
This will establish 4 remote powershell sessions (source and target EXO tenants, and source and target AAD tenants), and will validate the migration endpoint on the target tenant, AAD applicationId on target tenant and the Organization relationship on both tenants.
"},{"location":"Admin/CrossTenantMailboxMigrationValidation/#example-4","title":"EXAMPLE 4","text":".\\CrossTenantMailboxMigrationValidation.ps1 -SDP -LogPath C:\\Temp\\LogFile.txt -PathForCollectedData C:\\temp\n
This will establish 4 remote powershell sessions (source and target EXO tenants, and source and target AAD tenants), and will collect all the relevant information (config-wise) so it can be used for troubleshooting and send it to Microsoft Support if needed.
"},{"location":"Admin/CrossTenantMailboxMigrationValidation/#example-5","title":"EXAMPLE 5","text":".\\CrossTenantMailboxMigrationValidation.ps1 -SourceIsOffline -PathForCollectedData C:\\temp\\CTMMCollectedSourceData.zip -CheckObjects -LogPath C:\\temp\\CTMMTarget.log\n
This will expand the CTMMCollectedSourceData.zip file contents into a folder with the same name within the zip location, will establish the EXO remote powershell session and also with AAD against the Target tenant and will check the objects contained on the UsersToProcess.CSV file.
"},{"location":"Admin/CrossTenantMailboxMigrationValidation/#example-6","title":"EXAMPLE 6","text":".\\CrossTenantMailboxMigrationValidation.ps1 -SourceIsOffline -PathForCollectedData C:\\temp\\CTMMCollectedSourceData.zip -CheckOrgs -LogPath C:\\temp\\CTMMTarget.log\n
This will expand the CTMMCollectedSourceData.zip file contents into a folder with the same name within the zip location, will establish the EXO remote powershell session and also with AAD against the Target tenant, and will validate the migration endpoint on the target tenant, AAD applicationId on target tenant and the Organization relationship on both tenants.
"},{"location":"Admin/CrossTenantMailboxMigrationValidation/#example-7","title":"EXAMPLE 7","text":".\\CrossTenantMailboxMigrationValidation.ps1 -CollectSourceOnly -PathForCollectedData c:\\temp -LogPath C:\\temp\\CTMMCollectSource.log -CSV C:\\temp\\UsersToMigrate.csv\n
This will connect to the Source tenant against AAD and EXO, and will collect all the relevant information (config and user wise) so it can be used passed to the Target tenant admin for the Target validation to be done without the need to connect to the source tenant at the same time.
"},{"location":"Admin/Find-AmbiguousSids/","title":"Find-AmbiguousSids","text":"Download the latest release: Find-AmbiguousSids.ps1
Useful when Exchange throws NonUniqueRecipientException
, but doesn't log the objects causing it.
Find-AmbiguousSids.ps1\n [-GCName <string>]\n [-IgnoreWellKnown <bool>]\n [-Verbose]\n
"},{"location":"Admin/Find-AmbiguousSids/#examples","title":"Examples","text":"Find all ambiguous SIDs:
.\\Find-AmbiguousSids.ps1\n
Find all ambiguous SIDs while not ignoring the well-known ones, such as Everyone and other SIDs that always appear in multiple places:
.\\Find-AmbiguousSids.ps1 -IgnoreWellKnown $false\n
Show each object being checked:
.\\Find-AmbiguousSids.ps1 -Verbose\n
"},{"location":"Admin/Get-EASMailboxLogs/","title":"Get-EASMailboxLogs","text":"Download the latest release: Get-EASMailboxLogs.ps1
Used for when you need to get EAS Mailbox Logging over a long period of time. It will collect the logs and re-enable the Active Sync Logging enabled to avoid it being disabled after 72 hours.
"},{"location":"Admin/Get-EASMailboxLogs/#syntax","title":"Syntax","text":"Get-EASMailboxLogs.ps1\n [-Mailbox <string[]>]\n [-OutputPath <string>]\n [-Interval <int>]\n [-EnableMailboxLoggingVerboseMode <bool>]\n
"},{"location":"Admin/Get-EASMailboxLogs/#examples","title":"Examples","text":"The following example collects logs for two mailbox every hour:
.\\Get-EASMailboxLogs.ps1 -mailbox @(\"jim\",\"zeke\") -OutputPath C:\\EASLogs -interval 60\n
The following example collects logs for a mailbox:
.\\Get-EASMailboxLogs.ps1 -Mailbox \"jim\" -OutputPath c:\\EASLogs\n
The following example enables Verbose Logging on the current on premise server and collects logs for a mailbox:
.\\Get-EASMailboxLogs.ps1 -Mailbox \"jim\" -OutputPath c:\\EASLogs -EnableMailboxLoggingVerboseMode $true\n
"},{"location":"Admin/Get-SimpleAuditLogReport/","title":"Get-SimpleAuditLogReport","text":"Download the latest release: Get-SimpleAuditLogReport.ps1
Exchange admin audit logs are not readily human readable. All of the data needed to understand what Cmdlet has been run is in the data but it is not very easy to read. Get-SimpleAuditLogReport will take the results of an audit log search and provide a significantly more human readable version of the data.
It will parse the audit log and attempt to reconstruct the actual Cmdlet that was run.
"},{"location":"Admin/Get-SimpleAuditLogReport/#common-usage","title":"Common Usage","text":"$Search = Search-AdminAuditLog
$search | C:\\Scripts\\Get-SimpleAuditLogReport.ps1
Download the latest release: MonitorExchangeAuthCertificate.ps1
The MonitorExchangeAuthCertificate.ps1
PowerShell script can help you to manage the Auth Certificate used by multiple security features in Exchange Server. The script can be used to renew an already expired Auth Certificate or repair an invalid Auth Configuration in which the current Auth Certificate isn't available on all Exchange Servers running the Mailbox or Client Access Server (CAS) role. It can also manage rotation of the Auth Certificate to ensure a smooth transition to a new Auth Certificate.
The script comes with a manual execution mode and an automation mode that works using the Windows Task Scheduler.
"},{"location":"Admin/MonitorExchangeAuthCertificate/#requirements","title":"Requirements","text":"To run the script, you must be a member of the Organization Management
role group. The script must be run from an elevated Exchange Management Shell (EMS) command prompt on an Exchange Server running the Mailbox role. The script cannot be run on an Exchange Management Tools-only machine.
Each run of the script is logged to the following directory: <ExchangeInstallPath>\\Logging\\AuthCertificateMonitoring
The naming syntax of the log file is: <AuthCertificateMonitoringLog>_<Timestamp>.txt
NOTE: If the <ExchangeInstallPath>
directory doesn't exists, the log file will be written to the following directory: <$env:TEMP>\\Logging\\AuthCertificateMonitoring
The following syntax runs the script in validation-only mode. It will show you the required Auth Certificate renewal action that would be performed if the script is executed in renewal mode.
PS C:\\> .\\MonitorExchangeAuthCertificate.ps1\n
The following syntax executes the script in renewal mode with user interaction. The required Auth Certificate renewal action will be performed, and the administrator might see prompts that need to be confirmed before the script continues:
PS C:\\> .\\MonitorExchangeAuthCertificate.ps1 -ValidateAndRenewAuthCertificate $true\n
If you respond with 'Y', then the script will run in unattended mode and will not prompt you again.
It's recommended to recycle the WebApp Pools when the active Auth Certificate is replaced. You should respond with 'Y'.
It's not recommended to replace the internal transport certificate with the newly created Auth Certificate. You should respond with 'N'.
The following syntax executes the script in renewal mode without user interaction. The required Auth Certificate renewal action will be performed. In unattended mode the internal SMTP certificate is replaced with the new Auth Certificate and then set back to the previous one. The script also restarts the MSExchangeServiceHost
service and the MSExchangeOWAAppPool
and MSExchangeECPAppPool
WebApp Pools when the primary Auth Certificate has been replaced.
NOTE: The script creates a new internal transport certificate if the previously configured one wasn't found on the machine where the script is run.
PS C:\\> .\\MonitorExchangeAuthCertificate.ps1 -ValidateAndRenewAuthCertificate $true -Confirm:$false\n
The following syntax runs the script in renewal mode without user interaction. We only take the Exchange servers into account if they are reachable and will perform the renewal action if required.
PS C:\\> .\\MonitorExchangeAuthCertificate.ps1 -ValidateAndRenewAuthCertificate $true -IgnoreUnreachableServers $true -Confirm:$false\n
The following syntax executes the script in renewal mode without user interaction. The renewal action will be performed even when an Exchange hybrid configuration is detected.
NOTE: You must re-run the Hybrid Configuration Wizard (HCW) after the active Auth Certificate has been replaced.
PS C:\\> .\\MonitorExchangeAuthCertificate.ps1 -ValidateAndRenewAuthCertificate $true -IgnoreHybridConfig $true -Confirm:$false\n
The following syntax executes the script in scheduled task mode. In this mode, the script performs the following steps:
NOTE: It doesn't matter what you type into the Username
box, so you can enter, for example abc
. Make sure to use a password that complies with the password guidelines of your organization.
PS C:\\> .\\MonitorExchangeAuthCertificate.ps1 -ConfigureScriptToRunViaScheduledTask -Password (Get-Credential).Password\n
NOTE: The ConfigureScriptToRunViaScheduledTask
parameter can be combined with the IgnoreHybridConfig
and IgnoreUnreachableServers
parameter.
Auth Certificate Management
, which has the following roles assigned: View-Only Configuration
, View-Only Recipients
, Exchange Server Certificates
, Organization Client Access
SystemMailbox{b963af59-3975-4f92-9d58-ad0b1fe3a1a3}@contoso.local
Auth Certificate Management
Exchange Role Group<ExchangeInstallPath>\\Scripts
SystemMailbox{b963af59-3975-4f92-9d58-ad0b1fe3a1a3}@contoso.local
userThe following syntax runs the script in Active Directory (AD) account creation mode which can be useful when Exchange runs in AD Split Permissions mode. An AD administrator with sufficient permissions to create a user in AD (e.g., a Domain Admin) can run the script in this mode to create the SystemMailbox{b963af59-3975-4f92-9d58-ad0b1fe3a1a3}@contoso.local
account. The account can then be passed by the Exchange administrator via AutomationAccountCredential
parameter as outlined in the next example.
In this mode, the script can be executed from an elevated PowerShell command prompt (no EMS required) running on a non-Exchange Server machine with the ActiveDirectory PowerShell module installed, as it only uses cmdlets which are coming with this module.
NOTE: We recommend creating a user account in the same domain where Exchange was installed. You can specify the domain by using the ADAccountDomain
parameter.
PS C:\\> .\\MonitorExchangeAuthCertificate.ps1 -PrepareADForAutomationOnly -ADAccountDomain \"root.local\"\n
The following syntax executes the script in scheduled task mode, but it doesn't create the SystemMailbox{b963af59-3975-4f92-9d58-ad0b1fe3a1a3}@contoso.local
user account. Instead, the account passed via AutomationAccountCredential
parameter is used. Should a renewal action be performed, then email notifications will be sent to John.Doe@contoso.com\"
.
PS C:\\> .\\MonitorExchangeAuthCertificate.ps1 -ConfigureScriptToRunViaScheduledTask -AutomationAccountCredential (Get-Credential) -SendEmailNotificationTo \"John.Doe@contoso.com\"\n
The following syntax runs the script in Auth Certificate export mode. In this mode, the script exports the current and (if configured) the next Auth Certificate as DER (Distinguished Encoding Rules) binary encoded PKCS #12
files, using the .pfx
file name extension.
The naming syntax for the exported .pfx file is: <CertificateThumbprint>-<Timestamp>.pfx
PS C:\\> .\\MonitorExchangeAuthCertificate.ps1 -ExportAuthCertificatesAsPfx\n
The following syntax executes the script in update-only mode. In this mode, the script only checks for a more current version of the script and downloads it if found.
PS C:\\> .\\MonitorExchangeAuthCertificate.ps1 -ScriptUpdateOnly\n
"},{"location":"Admin/MonitorExchangeAuthCertificate/#parameters","title":"Parameters","text":"Parameter Description ValidateAndRenewAuthCertificate This optional parameter enables the validation and renewal mode which will perform the required actions to replace an invalid/expired Auth Certificate or configures a new next Auth Certificate if the current Auth Certificate expires in < 60 days or the certificate configured as next Auth Certificate expires in < 120 days. IgnoreUnreachableServers This optional parameter can be used to ignore if some of the Exchange servers within the organization cannot be reached. If this parameter is used, the script only validates the servers that can be reached and will perform Auth Certificate renewal actions based on the result. Parameter can be combined with the IgnoreHybridConfig
parameter and can also be used with the ConfigureScriptToRunViaScheduledTask
parameter to configure the script to run via scheduled task. IgnoreHybridConfig This optional parameter allows you to explicitly perform Auth Certificate renewal actions (if required) even if an Exchange hybrid configuration was detected. You need to run the HCW after the renewed Auth Certificate becomes the one in use. Parameter can be combined with the IgnoreUnreachableServers
parameter and can also be used with the ConfigureScriptToRunViaScheduledTask
parameter to configure the script to run via scheduled task. PrepareADForAutomationOnly This optional parameter can be used in AD Split Permission scenarios. It allows you to create the AD account which can then be used to run the Exchange Auth Certificate Monitoring script automatically via Task Scheduler. ADAccountDomain This optional parameter allows you to specify the domain which is then used by the script to generate the AD account used for automation. Parameter can be combined with the PrepareADForAutomationOnly
parameter. ConfigureScriptToRunViaScheduledTask This optional parameter can be used to automatically prepare the requirements in AD (user account), Exchange (email enable the account, hide the account from address book, create a new role group with limited permissions) and finally it creates the scheduled task on the computer on which the script was executed (it has to be an Exchange server running the mailbox role). AutomationAccountCredential This optional parameter can be used to provide a different user under whose context the script is then executed via scheduled task. SendEmailNotificationTo This optional parameter can be used to specify recipients which will then be notified in case that an Exchange Auth Certificate renewal action was performed. The script uses the EWS API
to send out email notifications. Make sure that the user in whose context the script is running is allowed to use EWS
. TrustAllCertificates This optional parameter can be used to trust all certificates when connecting to the EWS service to send out email notifications. TestEmailNotification This optional parameter can be used to test the email notification feature of the script. Password Parameter to provide a password to the script which is required in some scenarios. ExportAuthCertificatesAsPfx This optional parameter can be used to export all on the system available Auth Certificates as password protected .pfx file. ScriptUpdateOnly This optional parameter allows you to only update the script without performing any other actions. SkipVersionCheck This optional parameter can be used to skip the Auto Update feature to download the latest version of the script."},{"location":"Admin/Remove-CertExpiryNotifications/","title":"Remove-CertExpiryNotifications","text":"Download the latest release: Remove-CertExpiryNotifications.ps1
This script deletes all AsyncOperationNotification items from the Exchange SystemMailbox that contains them. This corrects the BlockedDeserializeTypeException error described in KB5013118.
NOTE: This script only supports Exchange 2016 and Exchange 2019. It will not work on Exchange 2013.
"},{"location":"Admin/Remove-CertExpiryNotifications/#syntax","title":"Syntax","text":"Remove-CertExpiryNotifications.ps1\n [-Server <string>]\n [[-Credential] <PsCredential>]\n [-WhatIf]\n [-Confirm]\n
"},{"location":"Admin/Remove-CertExpiryNotifications/#usage","title":"Usage","text":"NOTE: If an error occurs please see Common Errors.
The user running the script must be granted full access to the arbitration mailbox prior to running the script. That can be accomplished with this command:
Get-Mailbox -Arbitration \"SystemMailbox{e0dc1c29-89c3-4034-b678-e6c29d823ed9}\" | Add-MailboxPermission -User SomeAdmin -AccessRights FullAccess\n
Next, the same user that was granted access should run the script from Exchange Management Shell. Start by running the script with -WhatIf. Optionally, the -Credential switch can be provided. Otherwise, the current user will be used.
.\\Remove-CertExpiryNotifications.ps1 -Server exch1.contoso.com -WhatIf\n
If this succeeds, it will list all the messages that would be deleted. The output should look something like this:
To remove the messages, the script can be run without -WhatIf:
.\\Remove-CertExpiryNotifications.ps1 -Server exch1.contoso.com\n
This syntax will cause it to prompt for each message:
Or, the script can be run with -Confirm:$false to skip the prompts:
.\\Remove-CertExpiryNotifications.ps1 -Server exch1.contoso.com -Confirm:$false\n
After the script has run successfully, it should report that there are no messages present in the folder:
Finally, remember to remove the permission that was granted to the user:
Get-Mailbox -Arbitration \"SystemMailbox{e0dc1c29-89c3-4034-b678-e6c29d823ed9}\" | Remove-MailboxPermission -User SomeAdmin -AccessRights FullAccess\n
"},{"location":"Admin/Remove-CertExpiryNotifications/#common-errors","title":"Common errors","text":"Invoke-RestMethod : The underlying connection was closed: An unexpected error occurred on a send.\n
\"Unexpected error occurred on a send\" usually means that the name in the certificate on the target server does not match what was specified in the -Server parameter. In other words, navigating to https://the.server.you.specified/owa
must not return a certificate error. If it does, the script will fail. The specified server must be the name in the certificate bound to IIS.
Invoke-RestMethod : The remote server returned an error: (401) Unauthorized.\n
This can occur if the user running the script does not have full access to the mailbox. Be sure the Add-MailboxPermission command was successful.
This can also occur if the server name specified is the local server, due to the loopback check. This can be resolved by passing a different name.
"},{"location":"Admin/Reset-ScanEngineVersion/","title":"Reset-ScanEngineVersion","text":"Download the latest release: Reset-ScanEngineVersion.ps1
"},{"location":"Admin/Reset-ScanEngineVersion/#syntax","title":"Syntax","text":"Reset-ScanEngineVersion.ps1\n [-Force <switch>]\n [-EngineUpdatePath <string>]\n
"},{"location":"Admin/Reset-ScanEngineVersion/#usage","title":"Usage","text":"Copy the script to an affected Exchange server and run it with no parameters. It can be run from EMS or plain PowerShell.
In scenarios where centralized distribution of scan engines is used, add the -EngineUpdatePath switch to point to the share containing the engines. For example:
.\\Reset-ScanEngineVersion.ps1 -EngineUpdatePath \\\\FileServer1\\ScanEngineUpdates\n
"},{"location":"Admin/SetUnifiedContentPath/","title":"SetUnifiedContentPath","text":"Download the latest release: SetUnifiedContentPath.ps1
Sets the CleanupFolderREsponderFolderPaths in the AntiMalware.xml file that is responsible for having Exchange automatically clean up the Unified Content that is left behind.
If this isn't properly set, you can have large amount of files left on the computer that is just using up space and can cause issues with Exchange.
The script will keep the default values of D:\\ExchangeTemp\\TransportCts\\UnifiedContent
, C:\\Windows\\Temp\\UnifiedContent
, and $ExInstall\\TransportRoles\\data\\Temp\\UnifiedContent
within the value and will include TemporaryStoragePath
from the EdgeTransport.exe.config
if different from the install path.
In order for the new settings to take effect right away, use the -RestartService
switch to have the MSExchangeHM service take in the new changes right away.
The easiest way to run the script is against all the servers and restart the service.
Get-ExchangeServer | .\\SetUnifiedContentPath.ps1 -RestartService\n
If you don't want to change anything just yet, use the -WhatIf
switch to see what servers will have something changed.
Get-ExchangeServer | .\\SetUnifiedContentPath.ps1 -WhatIf\n
Or you can just run it locally on the server
.\\SetUnifiedContentPath.ps1 -RestartService\n
NOTE: The switch -RestartService
is only going to restart the service if a change has been detected and done. Otherwise, it will not restart the service.
The Windows AntiMalware Scan Interface (AMSI) is a versatile standard that allows applications and services to integrate with any AntiMalware product present on a machine. Seeing that Exchange administrators might not be familiar with AMSI, we wanted to provide a script that would make life a bit easier to test, enable, disable, or Check your AMSI Providers.
"},{"location":"Admin/Test-AMSI/#download","title":"Download","text":"Download the latest release: Test-AMSI.ps1
"},{"location":"Admin/Test-AMSI/#parameters","title":"Parameters","text":"Parameter Description TestAMSI If you want to test to see if AMSI integration is working. You can use a server, server list or FQDN of load balanced array of Client Access servers. IgnoreSSL If you need to test and ignoring the certificate check. CheckAMSIConfig If you want to see what AMSI Providers are installed. You can combine with ServerList, AllServers or Sites. EnableAMSI If you want to enable AMSI. Without any additional parameter it will apply at Organization Level. If combine with ServerList, AllServers or Sites it will apply at server level. DisableAMSI If you want to disable AMSI. Without any additional parameter it will apply at Organization Level. If combine with ServerList, AllServers or Sites it will apply at server level. RestartIIS If you want to restart the Internet Information Services (IIS). You can combine with ServerList, AllServers or Sites. Force If you want to restart the Internet Information Services (IIS) without confirmation. ServerList If you want to apply to some specific servers. AllServers If you want to apply to all server. Sites If you want to apply to all server on a sites or list of sites."},{"location":"Admin/Test-AMSI/#common-usage","title":"Common Usage","text":"After you download the script, you will need to run it within an elevated Exchange Management Shell Session
If you want to test to see if AMSI integration is working in a LB Array, you can run: .\\Test-AMSI.ps1 mail.contoso.com
If you want to test to see if AMSI integration is working in list of servers, you can run: .\\Test-AMSI.ps1 -ServerList server1, server2
If you want to test to see if AMSI integration is working in all server, you can run: .\\Test-AMSI.ps1 -AllServers
If you want to test to see if AMSI integration is working in all server in a list of sites, you can run: .\\Test-AMSI.ps1 -AllServers -Sites Site1, Site2
If you need to test and ignoring the certificate check, you can run: .\\Test-AMSI.ps1 -IgnoreSSL
If you want to see what AMSI Providers are installed on the local machine you can run: .\\Test-AMSI.ps1 -CheckAMSIConfig
If you want to enable AMSI at organization level, you can run: .\\Test-AMSI.ps1 -EnableAMSI
If you want to enable AMSI in an Exchange Server or Server List at server level, you can run: .\\Test-AMSI.ps1 -EnableAMSI -ServerList Exch1, Exch2
If you want to enable AMSI in all Exchange Server at server level, you can run: .\\Test-AMSI.ps1 -EnableAMSI -AllServers
If you want to enable AMSI in all Exchange Server in a site or sites at server level, you can run: .\\Test-AMSI.ps1 -EnableAMSI -AllServers -Sites Site1, Site2
If you want to disable AMSI on the Exchange Server, you can run: .\\Test-AMSI.ps1 -DisableAMSI
If you want to disable AMSI in an Exchange Server or Server List at server level, you can run: .\\Test-AMSI.ps1 -DisableAMSI -ServerList Exch1, Exch2
If you want to disable AMSI in all Exchange Server at server level, you can run: .\\Test-AMSI.ps1 -DisableAMSI -AllServers
If you want to disable AMSI in all Exchange Server in a site or sites at server level, you can run: .\\Test-AMSI.ps1 -DisableAMSI -AllServers -Sites Site1, Site2
If you want to restart the Internet Information Services (IIS), you can run: .\\Test-AMSI.ps1 -RestartIIS
If you want to restart the Internet Information Services (IIS) without confirmation, you can run: .\\Test-AMSI.ps1 -RestartIIS -Force
Download the latest release: Update-Engines.ps1
"},{"location":"Admin/Test-ExchangePropertyPermissions/#syntax","title":"Syntax","text":"Test-ExchangePropertyPermissions.ps1\n [-TargetObjectDN] <string>\n [-ComputerAccountDN] <string>\n [[-DomainController] <string>]\n [-OutputDebugInfo]\n [<CommonParameters>]\n
"},{"location":"Admin/Test-ExchangePropertyPermissions/#example","title":"Example","text":".\\Test-ExchangePropertyPermissions.ps1 -TargetObjectDN \"CN=SomeRecipient,OU=Users,DC=contoso,DC=com\" -ComputerAccountDN \"CN=SomeServerName,OU=Computers,DC=contoso,DC=com\"
This example retrieves the group memberships of the SomeServerName computer account and then examines the ACL of SomeRecipient to determine if that computer account can write to all expected attributes of that recipient.
"},{"location":"Admin/Test-ExchangePropertyPermissions/#description","title":"Description","text":"Test-ExchangePropertyPermissions is designed to detect certain schema issues which can manifest as permissions problems and can be challenging to identify manually, including:
Note that the script does not perform an exhaustive check for all possible schema issues. It is only designed to identify a specific subset of issues which we have encountered. For example, using AD Schema Analyzer as described here is one such scenario:
https://learn.microsoft.com/en-us/previous-versions/technet-magazine/dd547839(v=msdn.10)
As noted in that article, this is known to corrupt the Exchange attributes. This script is able to detect that scenario, and other similar scenarios.
Further, note that such issues cannot be fixed by the script. Using AD Schema Analyzer as described results in an unsupported forest that should be torn down.
"},{"location":"Admin/Update-Engines/","title":"Update-Engines","text":"Download the latest release: Update-Engines.ps1
The UpdateEngines script can be used to download the engine packages to be used by the Forefront Protection engine on Exchange Server and Sharepoint Server products.
"},{"location":"Admin/Update-Engines/#description","title":"Description","text":"Follow the steps given below to manually update the scan engines in Exchange Server. You may need to do so if you experience issues with accessing anti-malware updates online and want to download those definitions to a central location.
The manual update involves running the Update-Engines.ps1
PowerShell script. This script can be changed according to your needs.
The update path, list of engines, and list of platforms can be passed as parameters when the script is executed.
Note:
The script will default the engine update path to https://forefrontdl.microsoft.com/server/scanengineupdate/
. If this endpoint isn't available, you can change the script to use the failover endpoint https://amupdatedl.microsoft.com/server/scanengineupdate/
. If the previous endpoints aren't available, you can use http://amupdatedl.microsoft.com/server/amupdate/
as an alternative download location. By default, all engines will be downloaded for the 64-bit (amd64) platform.
Update-Engines.ps1\n [-EngineDirPath <string>]\n [-UpdatePathUrl <string>]\n [-FailoverPathUrl <string>]\n [-EngineDownloadUrlV2 <string>]\n [-Engines <string[]>]\n [-Platforms <string[]>]\n [-ScriptUpdateOnly <switch>]\n [-SkipVersionCheck <switch>]\n
"},{"location":"Admin/Update-Engines/#steps-to-update-scan-engines","title":"Steps to update scan engines","text":"Create a local directory structure on the computer on which you want to download the scan engine updates.
a. Create a directory. For example, create a directory named ScanEngineUpdates
. This directory must be passed via -EngineDirPath
parameter to the script.
b. Set the NTFS file system and share permissions on the directory so that the target Exchange servers have access to it.
Download the latest version of the script from here
Execute the Update-Engines.ps1
PowerShell script, providing any necessary parameters.
You can now configure the servers to download updates from the directory created in step 1) by using the UNC path of a share name, such as \\\\server_name\\share_name
.
The following syntax uses the directory C:\\ScanEngineUpdates\\
as the root engine's directory to store the update pattern.
Update-Engines.ps1 -EngineDirPath C:\\ScanEngineUpdates\\\n
The following syntax uses the directory C:\\ScanEngineUpdates\\
as the root engine's directory. It also tries to download the latest updates for the Microsoft
engine using the amd64
platform from http://forefrontdl.microsoft.com/server/scanengineupdate/
.
Update-Engines.ps1 -EngineDirPath C:\\ScanEngineUpdates\\ -UpdatePathUrl http://forefrontdl.microsoft.com/server/scanengineupdate/ -Engines Microsoft -Platforms amd64\n
"},{"location":"Admin/Update-Engines/#found-a-bug-or-want-to-update-the-script","title":"Found a bug or want to update the script?","text":"Please open a new work item here or reach out to us via: ExToolsFeedback@microsoft.com
"},{"location":"Calendar/Check-SharingStatus/","title":"Check-SharingStatus","text":"Download the latest release: Check-SharingStatus.ps1
This script runs a variety of PowerShell cmdlets to validate the sharing relationship between two users.
Terminology: Owner - this is the mailbox that owns the Calendar being shared. Receiver - this is the mailbox 'viewing' the owner calendar.
First item is to determine what kind of sharing relationship the users have. Modern Sharing (New Model Sharing) - Recipient gets a replicated copy of the Owners Calendar in their MB Old Model Sharing \u2013 Recipient is granted rights but have so connect to the Owners server to get Calendar information. External Sharing \u2013 Can be New or Old Model sharing, but outside of the Exchange Online Tenant / Organization. Publishing \u2013 Owner publishes a link to their calendar, which clients can pull.
Next you need to determine if the relationship is healthy. Look at the logs and output included in the script.
Last you need to look at how it is working. Generally, you will get Calendar Logs from Owner and Receiver for a copied meeting and check replication times, etc. See CalLogSummaryScript
"},{"location":"Calendar/Get-CalendarDiagnosticObjectsSummary/","title":"Get-CalendarDiagnosticObjectsSummary","text":"Download the latest release: Get-CalendarDiagnosticObjectsSummary.ps1
This script runs the Get-CalendarDiagnosticObjects script and returns a summarized timeline of actions into clear english. To run the script, you will need a valid SMTP Address for a user and a meeting Subject or MeetingID.
The script will display summarized timeline of actions and save the logs returned into a csv file in current directory.
Syntax:
Example to return timeline for a user with MeetingID
.\\Get-CalendarDiagnosticObjectsSummary.ps1 -Identity user@contoso.com -MeetingID 040000008200E00074C5B7101A82E0080000000010E4301F9312D801000000000000000010000000996102014F1D484A8123C16DDBF8603E\n
Example to return timeline for a user with Subject
.\\Get-CalendarDiagnosticObjectsSummary.ps1 -Identity user@contoso.com -Subject Test_OneTime_Meeting_Subject\n
"},{"location":"Calendar/Get-RBASummary/","title":"Get-RBASummary","text":"Download the latest release: Get-RBASummary.ps1
This script runs the Get-CalendarProcessing cmdlet and returns the output with more details in clear English, highlighting the key settings that affect RBA and some of the common errors in configuration.
The script will also validate the mailbox is the correct type for RBA to interact with (via the Get-Mailbox cmdlet) as well as check for any Delegate rules that would interfere with RBA functionality (via the Get-InboxRules cmdlet).
Syntax:
Example to display the setting of room mailbox.
.\\Get-RBASummary.ps1 -Identity Room1@Contoso.com\n\n.\\Get-RBASummary.ps1 -Identity Room1 -Verbose\n
High-level steps for RBA processing:
When the RBA receives a Meeting Request, the first thing that it will do is to determine if the meeting is in or out of policy. How does the RBA do this? The RBA compares the Meeting properties to the Policy Configuration. If all the checks 'pass', then the meeting request is In Policy, otherwise it is Out of Policy.
Whether the meeting is in or out of policy, the RBA will look up the configuration that will tell it what to do with the meeting. By default, all out of policy meetings are rejected, and all in policy meetings are accepted, but there is a larger range of customization that you can do to get the RBA to treat this resource the way you want it to.
If the meeting is accepted, the RBA will Post Process it based on the Post Processing configuration.
"},{"location":"Databases/Analyze-SpaceDump/","title":"Analyze-SpaceDump","text":"Download the latest release: Analyze-SpaceDump.ps1
This script reports the space taken up by various tables based on a database space dump.
"},{"location":"Databases/Analyze-SpaceDump/#usage","title":"Usage","text":"The space dump must be obtained while the database is dismounted, or on a suspended copy if the issue is happening there. To obtain the space dump, use the following syntax:
eseUtil /ms /v > C:\\SpaceDump.txt
Then, feed that file to this script as follows:
.\\Analyze-SpaceDump.ps1 -File C:\\SpaceDump.txt
This script will only work with Exchange 2013 and later space dumps.
"},{"location":"Databases/Compare-MailboxStatistics/","title":"Compare-MailboxStatistics","text":"Download the latest release: Compare-MailboxStatistics.ps1
"},{"location":"Databases/Compare-MailboxStatistics/#usage","title":"Usage","text":"This script compares two sets of mailbox statistics from the same database and highlights mailbox growth that occurred between the two snapshots.
For a growing database, a typical approach would be to start by exporting the statistics for the database:
Get-MailboxStatistics -Database DB1 | Export-CliXML C:\\stats-before.xml\n
After the initial export is obtained, wait until significant growth is observed. That could mean waiting an hour, or a day, depending on the scenario. At that point, compare the stats-before.xml with the live data by using this script as follows:
.\\Compare-MailboxStatistics.ps1 -Before (Import-CliXml C:\\stats-before.xml) -After (Get-MailboxStatistics -Database DB1)\n
This makes it easy to see which mailboxes grew the most.
"},{"location":"Databases/VSSTester/","title":"VSSTester","text":"Download the latest release: VSSTester.ps1
"},{"location":"Databases/VSSTester/#usage","title":"Usage","text":""},{"location":"Databases/VSSTester/#trace-while-using-a-third-party-backup-solution","title":"Trace while using a third-party backup solution","text":".\\VSSTester -TraceOnly -DatabaseName \"Mailbox Database 1637196748\"
Enables tracing of the specified database. The user may then attempt a backup of that database and use Ctrl-C to stop data collection after the backup attempt completes.
"},{"location":"Databases/VSSTester/#trace-a-snapshot-using-the-diskshadow-tool","title":"Trace a snapshot using the DiskShadow tool","text":".\\VSSTester -DiskShadow -DatabaseName \"Mailbox Database 1637196748\" -ExposeSnapshotsOnDriveLetters M, N
Enables tracing and then uses DiskShadow to snapshot the specified database. If the database and logs are on the same drive, the snapshot is exposed as M: drive. If they are on separate drives, the snapshots are exposed as M: and N:. The user is prompted to stop data collection and should typically wait until log truncation has occurred before doing so, so that the truncation is traced.
"},{"location":"Databases/VSSTester/#trace-a-snapshot-using-the-diskshadow-tool-by-volume-instead-of-by-database","title":"Trace a snapshot using the DiskShadow tool by volume instead of by Database","text":".\\VSSTester -DiskShadow -VolumesToBackup D:\\, E:\\ -ExposeSnapshotsOnDriveLetters M, N
Enables tracing and then uses DiskShadow to snapshot the specified volumes. To see a list of available volumes, including mount points, pass an invalid volume name, such as -VolumesToBackup foo
. The error will show the available volumes. Volume names must be typed exactly as shown in that output.
.\\VSSTester -WaitForWriterFailure -DatabaseName \"Mailbox Database 1637196748\"
Enables circular tracing of the specified database, and then polls \"vssadmin list writers\" once per minute. When the writer is no longer present, indicating a failure, tracing is stopped automatically.
"},{"location":"Databases/VSSTester/#more-information","title":"More information","text":"Note that script syntax and output has changed. Syntax and screenshots in the above articles are out of date.
"},{"location":"Databases/VSSTester/#missing-microsoft-exchange-writer","title":"Missing Microsoft Exchange Writer","text":"We have seen a few cases where the Microsoft Exchange Writer will disappear after an unspecified amount of time and restarting the Microsoft Exchange Replication service. Steps on how to resolve this are linked here:
Here are the steps to verify that the local Administrators group is allowed to the COM+ Security on the computer. The script will detect if this is a possibility if we can not see the Exchange Writers and we have the registry settings set that determine this is a possibility.
Download the latest release: ExTRA.ps1
The goal of this script is to replace the ExTRA UI that was included with older versions of Exchange. The script can be run on any machine where a modern browser (Edge/Chrome/Firefox) is set as the default browser. It does not need to be run on an Exchange server. It will not work if Internet Explorer is the default browser.
"},{"location":"Diagnostics/ExTRA/#usage","title":"Usage","text":"Generally, you will want to run this script on a user workstation and use it to generate the EnabledTraces.config file. Then, that file can be copied to the Exchange server, and a logman command can be used to start and stop the ExTRA trace.
The script can be run directly on a server if desired, but remember that IE cannot be the default browser in that case.
To use, download the latest release. Then run the script with no parameters:
.\\ExTRA.ps1\n
The default browser will launch with a tag selection interface. Once the desired tags are selected, click Save and go back to the PowerShell window. You should see some output indicating that the EnabledTraces.config file was saved in the folder. That EnabledTraces.config should be placed at the root of C:\\ on the server being traced.
The output also provides example logman syntax for creating, starting, and stopping the trace.
"},{"location":"Diagnostics/ExchangeLogCollector/","title":"Exchange Log Collector","text":"Download the latest release: ExchangeLogCollector.ps1
This script is intended to collect the Exchange default logging data from the server in a consistent manner to make it easier to troubleshoot an issue when large amounts of data is needed to be collected. You can specify what logs you want to collect by the switches that are available, then the script has logic built in to determine how to collect the data.
"},{"location":"Diagnostics/ExchangeLogCollector/#how-to-run","title":"How to Run","text":"The script must be run as Administrator in PowerShell session on an Exchange Server or Tools box. Supported to run and collected logs against Exchange 2013 and greater. The intent of the script is to collect logs only that you need from X servers quickly without needing to have to manually collect it yourself and label zip them all up for you. If you don't know what logs to collect, it is recommended to use -AllPossibleLogs
.
This script no longer supports collecting logs from Exchange 2010. However, the last release of v2 should still work just fine. You can download that here.
The script is able to collect from the large set of servers while using the Invoke-Command. Prior to executing the main script, we check to make sure the server is up and that we are able to use Invoke-Command against the server. If Invoke-Command works remotely, then we will allow you to attempt to collect the data. You can still utilize the script to collect locally as it used to be able to, if the target OS doesn't allow this.
Prior to collecting the data, we check to make sure that there is at least 10GB of free space at the location of where we are trying to save the data of the target server. The script will continue to keep track of all the logs and data that is being copied over and will stop if we have less than 10GB of free space.
You are able to use a config file to load up all the parameters you wish to choose and the servers you wish to run the script against. Just create a file called ExchangeLogCollector.ps1.json
and place at the same location as the script. Then provide the switches you would like to use in the file like so:
{\n \"Servers\": [\n \"ADT-E16A\",\n \"ADT-E16B\",\n \"ADT-E16C\"\n ],\n \"FilePath\": \"C:\\\\MS_Logs\",\n \"IISLogs\": true,\n \"AppSysLogsToXml\": false,\n \"ScriptDebug\": true\n}\n
NOTE: It is import that you use \\\\
for the file path otherwise the settings will fail to load.
This cmdlet will collect all default logs of the local Exchange Server and store them in the default location of \"C:\\MS_Logs_Collection\"
.\\ExchangeLogCollector.ps1 -AllPossibleLogs\n
This cmdlet will collect all relevant data regarding database fail overs from server EXCH1 and EXCH2 and store them at Z:\\Data\\Logs. Note: at the end of the collection, the script will copy over the data to the local host execution server to make data collection even easier.
.\\ExchangeLogCollector.ps1 -DatabaseFailoverIssue -Servers EXCH1,EXCH2 -FilePath Z:\\Data\\Logs\n
This cmdlet will collect all relevant data regarding IIS Logs (within the last 3 days by default) and all RPC type logs from the servers EXCH1 and EXCH2 and store them at the default location of \"C:\\MS_Logs_Collection\"
.\\ExchangeLogCollector.ps1 -Servers EXCH1,EXCH2 -IISLogs -RPCLogs\n
This cmdlet will collect all relevant data regarding Message Tracking Logs and Protocol Logs for the past 3 hours from the servers EXCH1 and EXCH2 and store them at the default location of \"C:\\MS_Logs_Collection\"
.\\ExchangeLogCollector.ps1 -Servers EXCH1,EXCH2 -MessageTrackingLogs -ProtocolLogs -LogAge \"03:00:00\"\n
"},{"location":"Diagnostics/ExchangeLogCollector/#parameters","title":"Parameters","text":"Parameter Description FilePath The Location of where you would like the data to be copied over to. This location must be the same and accessible on all servers if you use the Servers parameter. Default value: C:\\MS_Logs_Collection Servers An array of servers that you would like to collect data from. AcceptedRemoteDomain Enable to collect Get-AcceptedDomain
and Get-RemoteDomain
. ADDriverLogs Enable to collect AD Driver Logs. Location: V15\\Logging\\ADDriver
AppSysLogs Collects the Windows Event Application, System, and MSExchange Management Logs. Default value $true
AppSysLogsToXml Collects the Windows Event Application and System and saves them out to XML. The time range only is from the time the script run and the value set on LogAge
. Default value: $true
AutoDLogs Enable to collect AutoDiscover Logs. Location: V15\\Logging\\Autodiscover
and V15\\Logging\\HttpProxy\\Autodiscover
CollectFailoverMetrics Enable to run the CollectOverMetrics.ps1
script against the DAG. Only able to be run on an Exchange tools box or an Exchange Server. DAGInformation Enable to collect the DAG Information from all different DAGs that are in the list of servers. DailyPerformanceLogs Enable to collect Daily Performance Logs. Default Location: V15\\Logging\\Diagnostics\\DailyPerformanceLogs
DefaultTransportLogging Enables the following switches and their logs to be collected. AcceptedRemoteDomain
, FrontEndConnectivityLogs
, FrontEndProtocolLogs
, HubConnectivityLogs
, MailboxConnectivityLogs
, MailboxDeliveryThrottlingLogs
, MessageTrackingLogs
, PipelineTracingLogs
, QueueInformation
, ReceiveConnectors
, SendConnectors
, TransportConfig
, TransportRoutingTableLogs
, and TransportRules
EASLogs Enable to collect Exchange Active Sync Logging. Location: V15\\Logging\\HttpProxy\\Eas
ECPLogs Enable to collect ECP Logs. Location: V15\\Logging\\ECP
and V15\\Logging\\HttpProxy\\Ecp
EWSLogs Enable to collect EWS Logs. Location: V15\\Logging\\HttpProxy\\Ews
and V15\\Logging\\Ews
ExchangeServerInformation Enable to collect Exchange Information like Get-ExchangeServer, Get-MailboxServer, etc... This is also collected when -ServerInformation
is also enabled. ExMon Enable to collect ExMon data from the server. ExPerfWiz Enable to collect ExPerfWiz data if found. FrontEndConnectivityLogs Enable to collect the connectivity logging on the FE. Location: (Get-FrontendTransportService $server).ConnectivityLogPath
FrontEndProtocolLogs Enable to collect the protocol logging on the FE. Location: (Get-FrontendTransportService $server).ReceiveProtocolLogPath
and (Get-FrontendTransportService $server).SendProtocolLogPath
GetVDirs Enable to collect the Virtual Directories of the environment. HighAvailabilityLogs Enable to collect High Availability Logs. Windows Event Logs like: Microsoft-Exchange-HighAvailability
, Microsoft-Exchange-MailboxDatabaseFailureItems
, and Microsoft-Windows-FailoverClustering
HubConnectivityLogs Enable to collect the Hub connectivity logging. Location: (Get-TransportService $server).ConnectivityLogPath
HubProtocolLogs Enable to collect the protocol logging. Location: (Get-TransportService $server).ReceiveProtocolLogPath
and (Get-TransportService $server).SendProtocolLogPath
IISLogs Enable to collect IIS Logs and HTTPErr Logs from the Exchange Server. Default Location: C:\\InetPub\\logs\\LogFiles\\W3SVC1
, C:\\InetPub\\logs\\LogFiles\\W3SVC2
, and C:\\Windows\\System32\\LogFiles\\HTTPERR
. IISlogs do not collect all logs on CollectAllLogsBasedOnLogAge:$false, just works based on log age. ImapLogs Enable to collect IMAP logging. Location: (Get-ImapSettings -Server $server).LogFileLocation
MailboxAssistantsLogs Enable to collect Mailbox Assistants logging. Location: V15\\Logging\\MailboxAssistantsLog
, V15\\Logging\\MailboxAssistantsSlaReportLog
, and V15\\Logging\\MailboxAssistantsDatabaseSlaLog
MailboxConnectivityLogs Enable to collect the connectivity logging on the mailbox server. Location: (Get-MailboxTransportService $server).ConnectivityLogPath
MailboxDeliveryThrottlingLogs Enable to collect the mailbox delivery throttling logs on the server. Location: (Get-MailboxTransportService $server).MailboxDeliveryThrottlingLogPath
MailboxProtocolLogs Enable to collect protocol logging on the mailbox server. Location: (Get-MailboxTransportService $server).ReceiveProtocolLogPath
and (Get-MailboxTransportService $server).SendProtocolLogPath
ManagedAvailabilityLogs Enable to collect the Managed Availability Logs. Location: V15\\Logging\\Monitoring
and Windows Event logs like Microsoft-Exchange-ManagedAvailability
MapiLogs Enable to collect MAPI Logs. Location: V15\\Logging\\MAPI Client Access
, V15\\Logging\\MapiHttp\\Mailbox
, and V15\\Logging\\HttpProxy\\Mapi
MessageTrackingLogs Enable to collect the Message Tracking Logs. Location: (Get-TransportService $server).MessageTrackingLogPath
MitigationService Enable to collect the Mitigation Service logs. Location: V15\\Logging\\MitigationService
OABLogs Enable to collect OAB Logs. Location: V15\\Logging\\HttpProxy\\OAB
, V15\\Logging\\OABGeneratorLog
, V15\\Logging\\OABGeneratorSimpleLog
, and V15\\Logging\\MAPI AddressBook Service
OrganizationConfig Enable to collect the Organization Configuration from the environment. OWALogs Enable to collect OWA Logs. Location: V15\\Logging\\OWA
, Logging\\HttpProxy\\OwaCalendar
, and V15\\Logging\\HttpProxy\\Owa
PipelineTracingLogs Enable to collect the Pipeline Tracing Logs. Location (Get-TransportService $server).PipelineTracingPath
, and (Get-MailboxTransportService $server).PipelineTracingPath
PopLogs Enable to collect POP logging. Location: (Get-PopSettings -Server $server).LogFileLocation
PowerShellLogs Enable to collect the PowerShell Logs. Location: V15\\Logging\\HttpProxy\\PowerShell
QueueInformation Enable to collect the historical queue information. Location: (Get-TransportService $server).QueueLogPath
ReceiveConnectors Enable to collect the Receive Connector information from the server. RPCLogs Enable to collect RPC Logs. Location: V15\\Logging\\RPC Client Access
, V15\\Logging\\HttpProxy\\RpcHttp
, and V15\\Logging\\RpcHttp
SearchLogs Enable to collect Search Logs. Location: V15\\Bin\\Search\\Ceres\\Diagnostics\\Logs
, V15\\Bin\\Search\\Ceres\\Diagnostics\\ETLTraces
, V15\\Logging\\Search
. On 2019 only we also include V15\\Logging\\BigFunnelMetricsCollectionAssistant
, V15\\Logging\\BigFunnelQueryParityAssistant
, and V15\\Logging\\BigFunnelRetryFeederTimeBasedAssistant
SendConnectors Enable to collect the send connector information from the environment. ServerInformation Enable to collect general server information. TransportAgentLogs Enable to collect the Agent Logs. Location: (Get-TransportService $server).AgentLogPath
, (Get-FrontendTransportService $server).AgentLogPath
, (Get-MailboxTransportService $server).MailboxSubmissionAgentLogPath
, and (Get-MailboxTransportService $server).MailboxDeliveryAgentLogPath
TransportConfig Enable to collect the Transport Configuration files from the Server and Get-TransportConfig
from the org. Files: EdgeTransport.exe.config
, MSExchangeFrontEndTransport.exe.config
, MSExchangeDelivery.exe.config
, and MSExchangeSubmission.exe.config
TransportRoutingTableLogs Enable to collect the Routing Table Logs. Location: (Get-TransportService $server).RoutingTableLogPath
, (Get-FrontendTransportService $server).RoutingTableLogPath
, and (Get-MailboxTransportService $server).RoutingTableLogPath
TransportRules Enable to collect Get-TransportRule
. WindowsSecurityLogs Enable to collect the Windows Security Logs. Default Location: 'C:\\Windows\\System32\\WinEvt\\Logs\\Security.evtx'
AllPossibleLogs Enables the collection of all default logging collection on the Server. CollectAllLogsBasedOnLogAge Boolean to determine if you collect all the logs based off the log's age or all the logs in that directory. Default value $true
ConnectivityLogs Enables the following switches and their logs to be collected: FrontEndConnectivityLogs
, HubConnectivityLogs
, and MailboxConnectivityLogs
DatabaseFailoverIssue Enables the following switches and their logs to be collected. DAGInformation
, DailyPerformanceLogs
, ExchangeServerInformation
, ExPerfWiz
, HighAvailabilityLogs
, ManagedAvailabilityLogs
, and ServerInformation
. DaysWorth The number of days to go back to be included int the time span for log collection. Default value: 3 HoursWorth The number of hours to go back to be included in the time span for the log collection. Default Value 0. LogStartDate Set the starting time for the log collection (DateTime). LogEndDate Set the ending time for the log collection (DateTime). DisableConfigImport Enable to not import the ExchangeLogCollector.ps1.json
file if it exists. ExMonLogmanName A list of names that we want to collect for ExMon data. The default name is ExMon_Trace
. ExPerfWizLogmanName A list of names that we want to collect performance data logs from. The default names are Exchange_PerfWiz
, ExPerfWiz
, and SimplePerf
. (For both styles of ExPerfWiz) LogAge A Time Span value to use instead of the DaysWorth and HoursWorth parameters. Default Value: 3.00:00:00 OutlookConnectivityIssues Enables the following switches and their logs to be collected: AutoDLogs
, DailyPerformanceLogs
, EWSLogs
, ExPerfWiz
, IISLogs
, MAPILogs
, RPCLogs
, and ServerInformation
PerformanceIssues Enables the following switches and their logs to be collected: DailyPerformanceLogs
, ExPerfWiz
, and ManagedAvailabilityLogs
PerformanceMailFlowIssues Enables the following switches and their logs to be collected: DailyPerformanceLogs
, ExPerfWiz
, MessageTrackingLogs
, QueueInformation
, and TransportConfig
ProtocolLogs Enables the following switches and their logs to be collected: FrontEndProtocolLogs
, HubProtocolLogs
, and MailboxProtocolLogs
ScriptDebug Enable to display all the verbose lines in the script. SkipEndCopyOver If the Servers parameter is used, by default we will attempt to collect all the data back over to the local server after all the data was collected on each server."},{"location":"Diagnostics/ManagedAvailabilityTroubleshooter/","title":"ManagedAvailabilityTroubleshooter","text":"Download the latest release: ManagedAvailabilityTroubleshooter.ps1
"},{"location":"Diagnostics/Test-ExchAVExclusions/","title":"Test-ExchAVExclusions","text":"Download the latest release: Test-ExchAVExclusions.ps1
Assists with testing Exchange Servers to determine if AV Exclusions have been properly set according to our documentation.
AV Exclusions Exchange 2016/2019
AV Exclusions Exchange 2013
"},{"location":"Diagnostics/Test-ExchAVExclusions/#usage","title":"Usage","text":"Writes an EICAR test file to all paths specified in our AV Exclusions documentation and verifies all extensions in the documentation in a temporary folder.
If the file is removed then the path is not properly excluded from AV Scanning. IF the file is not removed then it should be properly excluded.
Once the files are created it will wait 5 minutes for AV to \"see\" and remove the file.
After finishing testing directories it will test Exchange Processes. Pulls all Exchange processes and their modules. Excludes known modules and reports all Non-Default modules.
Non-Default modules should be reviewed to ensure they are expected. AV Modules loaded into Exchange Processes indicate that AV Process Exclusions are NOT properly configured.
... .\\Test-ExchAVExclusions.ps1 ...
"},{"location":"Diagnostics/Test-ExchAVExclusions/#understanding-the-output","title":"Understanding the Output","text":""},{"location":"Diagnostics/Test-ExchAVExclusions/#file-output","title":"File Output","text":"Review the BadExclusions.txt file to see any file paths were identified as being scanned by AV. Work with the AV Vendor to determine the best way to exclude these file paths according to our documentation:
AV Exclusions Exchange 2016/2019
"},{"location":"Diagnostics/Test-ExchAVExclusions/#process-output","title":"Process Output","text":"Review NonDefaultModules.txt to determine if any Non-Default modules are loaded into Exchange processes. The output should have sufficient information to identity the source of the flagged modules.
[FAIL] - PROCESS: ExchangeTransport MODULE: scanner.dll COMPANY: Contoso Security LTT.
If the Module is from an AV or Security software vendor it is a strong indication that process exclusions are not properly configured on the Exchange server. Please work with the vendor to ensure that they are properly configured according to:
AV Exclusions Exchange 2016/2019
AV Exclusions Update
"},{"location":"Diagnostics/Test-ExchAVExclusions/#parameters","title":"Parameters","text":"Parameter Description WaitingTimeForAVAnalysisInMinutes Set the waiting time for AV to analyze the EICAR files. Default is 5 minutes. Recurse Places an EICAR file in all SubFolders as well as the root. OpenLog Opens the script log file. SkipVersionCheck Skip script version verification. ScriptUpdateOnly Just update script version to latest one."},{"location":"Diagnostics/Test-ExchAVExclusions/#outputs","title":"Outputs","text":"Log file: $PSScriptRoot\\ExchAvExclusions.log
List of Folders, extensions Scanned by AV and List of Non-Default Processes: $PSScriptRoot\\BadExclusions.txt
"},{"location":"Diagnostics/FindFrontEndActivity/FindFrontEndActivity/","title":"FindFrontEndActivity","text":"Download the latest release: FindFrontEndActivity.ps1
"},{"location":"Diagnostics/FindFrontEndActivity/FindFrontEndActivity/#synopsis","title":"Synopsis","text":"Find HttpProxy protocol activity for one or more users.
"},{"location":"Diagnostics/FindFrontEndActivity/FindFrontEndActivity/#syntax","title":"Syntax","text":".\\FindFrontEndActivity.ps1 -ServerName <String[]> -SamAccountName <String[]> [-LatencyThreshold <Int32>] [-Protocol <String[]>] [-IncludeNonExecutes] [-Quiet] [-TimeSpan <TimeSpan>] [<CommonParameters>]\n\n.\\FindFrontEndActivity.ps1 -ServerName <String[]> -SamAccountName <String[]> [-LatencyThreshold <Int32>] [-Protocol <String[]>] [-IncludeNonExecutes] [-Quiet] -StartTime <DateTime> -EndTime <DateTime> [<CommonParameters>]\n
"},{"location":"Diagnostics/FindFrontEndActivity/FindFrontEndActivity/#quick-start-examples","title":"Quick Start Examples","text":"[PS] C:\\>Get-ExchangeServer | .\\FindFrontEndActivity.ps1 -SamAccountName \"john.doe\" | ft\n\nDateTime AuthenticatedUser UrlStem ServerHostName TargetServer TotalRequestTime\n-------- ----------------- ------- -------------- ------------ ----------------\n2023-02-11T15:59:35.174Z contoso\\john.doe /mapi/emsmdb/ EXCH1 exch1.contoso.local 2214\n
[PS] C:\\>Get-ExchangeServer | .\\FindFrontEndActivity.ps1 -SamAccountName \"john.doe\" -LatencyThreshold 100 | ft\n\nDateTime AuthenticatedUser UrlStem ServerHostName TargetServer TotalRequestTime\n-------- ----------------- ------- -------------- ------------ ----------------\n2023-02-11T15:59:29.898Z contoso\\john.doe /mapi/emsmdb/ EXCH1 exch1.contoso.local 505\n2023-02-11T15:59:31.560Z contoso\\john.doe /mapi/emsmdb/ EXCH1 exch1.contoso.local 403\n2023-02-11T15:59:35.174Z contoso\\john.doe /mapi/emsmdb/ EXCH1 exch1.contoso.local 2214\n2023-02-11T15:59:35.488Z contoso\\john.doe /mapi/emsmdb/ EXCH1 exch1.contoso.local 161\n2023-02-11T15:59:38.133Z contoso\\john.doe /mapi/emsmdb/ EXCH1 exch1.contoso.local 399\n
[PS] C:\\>Get-ExchangeServer | .\\FindFrontEndActivity.ps1 -SamAccountName \"john.doe\" -Protocol \"ews\", \"mapi\" | ft\n\nDateTime AuthenticatedUser UrlStem ServerHostName TargetServer TotalRequestTime\n-------- ----------------- ------- -------------- ------------ ----------------\n2023-02-11T15:10:10.643Z contoso\\john.doe /EWS/Exchange.asmx EXCH1 exch1.contoso.local 1800019\n2023-02-11T15:40:44.254Z contoso\\john.doe /EWS/Exchange.asmx EXCH1 exch1.contoso.local 1800028\n2023-02-11T15:59:35.174Z contoso\\john.doe /mapi/emsmdb/ EXCH1 exch1.contoso.local 2214\n
Note the difference between -Quiet mode and the default:
[PS] C:\\>Get-ExchangeServer | .\\FindFrontEndActivity.ps1 -SamAccountName \"john.doe\" -Quiet\nEXCH1\nEXCH3\n[PS] C:\\>\n[PS] C:\\># Notice how we returned two servers when using -Quiet.\n[PS] C:\\>\n[PS] C:\\>Get-ExchangeServer | .\\FindFrontEndActivity.ps1 -SamAccountName \"john.doe\" | ft\n\nDateTime AuthenticatedUser UrlStem ServerHostName TargetServer TotalRequestTime\n-------- ----------------- ------- -------------- ------------ ----------------\n2023-02-11T16:25:14.508Z contoso\\john.doe /mapi/emsmdb/ EXCH1 exch1.contoso.local 1182\n\n\n[PS] C:\\># But only one in the default mode. This is because the default is intended\n[PS] C:\\># to look for calls that are slow and are Execute calls. To see everything,\n[PS] C:\\># we need to remove the latency filter and include non-execute activity,\n[PS] C:\\># but this will return a lot of noise.\n[PS] C:\\>\n[PS] C:\\>Get-ExchangeServer | .\\FindFrontEndActivity.ps1 -SamAccountName \"john.doe\" -LatencyThreshold 0 -IncludeNonExecutes | ft\n\nDateTime AuthenticatedUser UrlStem ServerHostName TargetServer TotalRequestTime\n-------- ----------------- ------- -------------- ------------ ----------------\n2023-02-11T16:00:07.619Z contoso\\john.doe /mapi/emsmdb/ EXCH3 exch1.contoso.local 17\n2023-02-11T16:01:10.555Z contoso\\john.doe /mapi/nspi/ EXCH1 exch1.contoso.local 22\n2023-02-11T16:05:11.132Z contoso\\john.doe /mapi/emsmdb/ EXCH1 exch1.contoso.local 659066\n2023-02-11T16:05:12.101Z contoso\\john.doe /mapi/nspi/ EXCH1 exch1.contoso.local 21\n...\n
To see all details, use fl *
:
[PS] C:\\>Get-ExchangeServer | .\\FindFrontEndActivity.ps1 -SamAccountName \"john.doe\" | fl *\n\n\nDateTime : 2023-02-11T16:25:14.508Z\nRequestId : 0aa7958e-c59a-4f0a-903f-ebbd6ed93c9a\nMajorVersion : 15\nMinorVersion : 2\nBuildVersion : 1118\n...\n
"},{"location":"Diagnostics/FindFrontEndActivity/FindFrontEndActivity/#description","title":"Description","text":"When an Exchange client experiences issues, the HttpProxy logs are often the starting point for determining whether the issue is with the client, the network, or the server. However, since an Exchange environment may have dozens of front-end servers, it can be difficult to find the relevant logs for a given user.
This script is designed to search the logs of all Exchange servers in parallel to quickly find the HttpProxy logs related to specified users.
The default mode of the script is intended for finding slow MAPI calls from Outlook clients. The -Protocol
switch can be used to search more protocols, while specifying -LatencyThreshold
allows the admin to filter more aggressively or remove the latency filter entirely. Running in -Quiet
mode skips the filtering and just reports any servers that have the specified users in the HttpProxy logs for the specified protocols. See the parameters and examples for more information.
-ServerName <String[]>\n The name of one or more Exchange servers to search. An easy way to search all Exchange\n servers in the forest is to simply pipe Get-ExchangeServer to the script.\n\n Required? true\n Position? named\n Default value\n Accept pipeline input? true (ByValue, ByPropertyName)\n Accept wildcard characters? false\n\n-SamAccountName <String[]>\n The samAccountNames of one or more users to search for.\n\n Required? true\n Position? named\n Default value\n Accept pipeline input? false\n Accept wildcard characters? false\n\n-LatencyThreshold <Int32>\n The minimum latency (in milliseconds) to search for. This is useful for filtering out\n noise from the logs. (Default: 1000). This parameter has no effect when -Quiet is used.\n\n Required? false\n Position? named\n Default value 1000\n Accept pipeline input? false\n Accept wildcard characters? false\n\n-Protocol <String[]>\n The protocols to search. Valid values are: Autodiscover, EAS, ECP, EWS, MAPI, OWA, PowerShell,\n RpcHttp. (Default: MAPI)\n\n Required? false\n Position? named\n Default value @('MAPI')\n Accept pipeline input? false\n Accept wildcard characters? false\n\n-IncludeNonExecutes [<SwitchParameter>]\n By default, NotificationWaits from the MAPI logs are not included, because these are slow\n by design. Specify this switch to include them.\n\n Required? false\n Position? named\n Default value False\n Accept pipeline input? false\n Accept wildcard characters? false\n\n-Quiet [<SwitchParameter>]\n This switch causes the script to only report the server names rather than the full log\n entries. This may be somewhat faster. However, there is no filtering for LatencyThreshold\n and NotificationWait when this option is used.\n\n Required? false\n Position? named\n Default value False\n Accept pipeline input? false\n Accept wildcard characters? false\n\n-TimeSpan <TimeSpan>\n Specify how far back to search the logs. This is a TimeSpan value, such as \"01:00\" for the\n last hour or \"00:30\" for the last 30 minutes. (Default: 15 minutes). Use this parameter to\n search the most recent logs. Use StartTime and EndTime to search older logs.\n\n Required? false\n Position? named\n Default value (New-TimeSpan -Minutes 15)\n Accept pipeline input? false\n Accept wildcard characters? false\n\n-StartTime <DateTime>\n Logs older than this time are not searched. This is a DateTime value, such as (Get-Date).AddDays(-1)\n or \"2023-02-11 08:00\". Use this parameter to search old logs. Use -TimeSpan to search the\n most recent logs.\n\n Required? true\n Position? named\n Default value\n Accept pipeline input? false\n Accept wildcard characters? false\n\n-EndTime <DateTime>\n Logs newer than this time are not searched. This is a DateTime value, such as (Get-Date).AddDays(-1)\n or \"2023-02-11 09:00\". Use this parameter to search old logs. Use -TimeSpan to search the\n most recent logs.\n\n Required? true\n Position? named\n Default value\n Accept pipeline input? false\n Accept wildcard characters? false\n\n<CommonParameters>\n This cmdlet supports the common parameters: Verbose, Debug,\n ErrorAction, ErrorVariable, WarningAction, WarningVariable,\n OutBuffer, PipelineVariable, and OutVariable. For more information, see\n about_CommonParameters (https://go.microsoft.com/fwlink/?LinkID=113216).\n
"},{"location":"Diagnostics/FindFrontEndActivity/FindFrontEndActivity/#example-1","title":"Example 1","text":"Get-ExchangeServer | .\\FindFrontEndActivity.ps1 -SamAccountName \"user1\", \"user2\" | ft\n
Show any MAPI HttpProxy activity that took more than 1 second for user1 or user2 within the last 15 minutes on all Exchange servers in the forest."},{"location":"Diagnostics/FindFrontEndActivity/FindFrontEndActivity/#example-2","title":"Example 2","text":"Get-ExchangeServer | .\\FindFrontEndActivity.ps1 -SamAccountName \"user1\", \"user2\" -Quiet\n
Show only the server names where user1 or user2 are found in the MAPI HttpProxy logs within the last 15 minutes."},{"location":"Diagnostics/FindFrontEndActivity/FindFrontEndActivity/#example-3","title":"Example 3","text":"Get-ExchangeServer | .\\FindFrontEndActivity.ps1 -SamAccountName \"user1\", \"user2\" -Protocol \"ews\", \"mapi\" -LatencyThreshold 100 -TimeSpan \"00:30\"\n
Show any EWS or MAPI HttpProxy activity that took more than 100 milliseconds for user1 or user2 within the last 30 minutes on all Exchange servers in the forest."},{"location":"Diagnostics/HealthChecker/","title":"HealthChecker","text":"Download the latest release: HealthChecker.ps1
The Exchange Server Health Checker script helps detect common configuration issues that are known to cause performance issues and other long running issues that are caused by a simple configuration change within an Exchange Environment. It also helps collect useful information of your server to help speed up the process of common information gathering of your server.
"},{"location":"Diagnostics/HealthChecker/#requirements","title":"Requirements","text":""},{"location":"Diagnostics/HealthChecker/#supported-exchange-server-versions","title":"Supported Exchange Server Versions:","text":"The script can be used to validate the configuration of the following Exchange Server versions: - Exchange Server 2013 - Exchange Server 2016 - Exchange Server 2019
"},{"location":"Diagnostics/HealthChecker/#required-permissions","title":"Required Permissions:","text":"Please make sure that the account used is a member of the Local Administrator
group. This should be fulfilled on Exchange servers by being a member of the Organization Management
group. However, if the group membership was adjusted or in case the script is executed on a non-Exchange system like a management server, you need to add your account to the Local Administrator
group. You also need to be a member of the following groups:
DCCoreRatio
parameter)HealthChecker.ps1\n [-Server <string[]>]\n [-OutputFilePath <string>]\n [-SkipVersionCheck]\n [-SaveDebugLog]\nHealthChecker.ps1\n [-Server <string[]>]\n [-MailboxReport]\n [-OutputFilePath <string>]\n [-SkipVersionCheck]\n [-SaveDebugLog]\nHealthChecker.ps1\n [-LoadBalancingReport]\n [-ServerList <string[]>]\n [-SiteName <string>]\n [-OutputFilePath <string>]\n [-SkipVersionCheck]\n [-SaveDebugLog]\nHealthChecker.ps1\n [-BuildHtmlServersReport]\n [-XMLDirectoryPath <string>]\n [-HtmlReportFile <string>]\n [-OutputFilePath <string>]\n [-SkipVersionCheck]\n [-SaveDebugLog]\nHealthChecker.ps1\n [-AnalyzeDataOnly]\n [-XMLDirectoryPath <string>]\n [-HtmlReportFile <string>]\n [-OutputFilePath <string>]\n [-SkipVersionCheck]\n [-SaveDebugLog]\nHealthChecker.ps1\n [-DCCoreRatio]\n [-OutputFilePath <string>]\n [-SkipVersionCheck]\n [-SaveDebugLog]\nHealthChecker.ps1\n [-ScriptUpdateOnly]\n [-OutputFilePath <string>]\n [-SaveDebugLog]\nHealthChecker.ps1\n [-VulnerabilityReport]\n [-OutputFilePath <string>]\n [-SkipVersionCheck]\n [-SaveDebugLog]\n
"},{"location":"Diagnostics/HealthChecker/#how-to-run","title":"How To Run","text":"This script must be run as Administrator in Exchange Management Shell on an Exchange Server. You can provide no parameters and the script will just run against the local server and provide the detail output of the configuration of the server.
"},{"location":"Diagnostics/HealthChecker/#examples","title":"Examples:","text":"This cmdlet with run Health Checker Script by default and run against the local server.
PS C:\\> .\\HealthChecker.ps1\n
This cmdlet will run the Health Checker Script against the specified server.
PS C:\\> .\\HealthChecker.ps1 -Server EXCH1\n
This cmdlet will run the Health Checker Script against a list of servers.
PS C:\\> .\\HealthChecker.ps1 -Server EXCH1,EXCH2,EXCH3\n
This cmdlet will build the HTML report for all the XML files located in the same location as the Health Checker Script.
PS C:\\> .\\HealthChecker.ps1 -BuildHtmlServersReport\n
This cmdlet will build the HTML report for all the XML files located in the directory specified in the XMLDirectoryPath Parameter.
PS C:\\> .\\HealthChecker.ps1 -BuildHtmlServersReport -XMLDirectoryPath C:\\Location\n
This cmdlet will run the Health Checker Load Balancing Report for all the Exchange 2013+ CAS (Front End connections only) and MBX servers (BackEnd connections) in the Organization.
PS C:\\> .\\HealthChecker.ps1 -LoadBalancingReport\n
This cmdlet will run the Health Checker Load Balancing Report for these Servers EXCH1, EXCH2, and EXCH3 CAS (Front End connections) and MBX (BackEnd Connections)
PS C:\\> .\\HealthChecker.ps1 -LoadBalancingReport -ServerList EXCH1,EXCH2,EXCH3\n
This cmdlet will run the Health Checker Load Balancing Report for the Exchange 2013+ servers in the site SiteA.
PS C:\\> .\\HealthChecker.ps1 -LoadBalancingReport -SiteName SiteA\n
This cmdlet will run the Health Checker Mailbox Report against the Server EXCH1
PS C:\\> .\\HealthChecker.ps1 -MailboxReport -Server EXCH1\n
This cmdlet will run the Health Checker against all your Exchange Servers, then run the HTML report and open it.
PS C:\\> Get-ExchangeServer | ?{$_.AdminDisplayVersion -Match \"^Version 15\"} | .\\HealthChecker.ps1; .\\HealthChecker.ps1 -BuildHtmlServersReport; .\\ExchangeAllServersReport.html\n
This cmdlet will run Health Checker Vulnerability Report feature against all your Exchange Servers. Then Export out the data to a json file.
PS C:\\> .\\HealthChecker.ps1 -VulnerabilityReport\n
"},{"location":"Diagnostics/HealthChecker/#parameters","title":"Parameters","text":"Parameter Description Server The server that you would like to run the Health Checker Script against. Parameter not valid with -BuildHTMLServersReport or LoadBalancingReport. Default is the localhost. OutputFilePath The output location for the log files that the script produces. Default is the current directory. MailboxReport Produces the Mailbox Report for the server provided. LoadBalancingReport Runs the Load Balancing Report for the Script ServerList Used in combination with the LoadBalancingReport switch for letting the script to know which servers to run against. SiteName Used in combination with the LoadBalancingReport switch for letting the script to know which servers to run against in the site. XMLDirectoryPath Used in combination with BuildHtmlServersReport switch for the location of the HealthChecker XML files for servers which you want to be included in the report. Default location is the current directory. BuildHtmlServersReport Switch to enable the script to build the HTML report for all the servers XML results in the XMLDirectoryPath location. HtmlReportFile Name of the HTML output file from the BuildHtmlServersReport. Default is ExchangeAllServersReport.html DCCoreRatio Gathers the Exchange to DC/GC Core ratio and displays the results in the current site that the script is running in. AnalyzeDataOnly Switch to analyze the existing HealthChecker XML files. The results are displayed on the screen and an HTML report is generated. VulnerabilityReport Switch to collect the Vulnerability Information for all the servers in the environment and export it out to json file. SkipVersionCheck No version check is performed when this switch is used. SaveDebugLog The debug log is kept even if the script is executed successfully. ScriptUpdateOnly Switch to check for the latest version of the script and perform an auto update if a newer version was found. Can be run on any machine with internet connectivity. No elevated permissions or EMS are required."},{"location":"Diagnostics/HealthChecker/ADSiteCount/","title":"AD Site Count Check","text":"In large environments that contains a lot of sites, can cause a performance issue with Exchange. In particular Autodiscover app pool will peg the CPU at 4-hour intervals when there are many AD sites.
It is recommended to reduce the number of AD Sites within the environment to address this issue. However, there is a workaround that would prevent the issue from occurring every 4-hours and just every 24-hours.
In the %ExchangeInstallPath%\\Bin\\Microsoft.Exchange.Directory.TopologyService.exe.config
file, change the ExchangeTopologyCacheLifetime
value to be 1.00:00:00,00:20:00
instead to have the cache lifetime increase from 4-hours to 24-hours. It is not recommended to go beyond 24-hours.
Included in HTML Report?
Yes
Additional resources:
Original Issue
"},{"location":"Diagnostics/HealthChecker/AMSIIntegration/","title":"AMSI Check","text":"The Windows AntiMalware Scan Interface (AMSI) is a versatile standard that allows applications and services to integrate with any AntiMalware product present on a machine. AMSI is vendor agnostic and designed to allow for the most common malware scanning and protection techniques provided by today's products to be integrated into applications.
It only scans the HTTP protocol, and is not meant to be a replacement to existing server-level or message hygiene protections.
AMSI integration is available on the following Operating System / Exchange Server version combinations: - Windows Server 2016, or higher - Exchange Server 2016 CU21, or higher - Exchange Server 2019 CU10, or higher - AMSI is not available on Edge Transport Servers
If you use Microsoft Defender, AV engine version at or higher than 1.1.18300.4 is also required. Alternatively, a compatible AMSI capable third-party AV provider.
This check verifies if an override exists which disables the AMSI integration with Exchange Server. It does that, by running the following query:
Get-SettingOverride | Where-Object { ($_.ComponentName -eq \"Cafe\") -and ($_.SectionName -eq \"HttpRequestFiltering\") }
Included in HTML Report?
Yes
Additional resources:
Released: June 2021 Quarterly Exchange Updates
More about AMSI integration with Exchange Server
"},{"location":"Diagnostics/HealthChecker/AuthCertificateCheck/","title":"Auth Certificate Check","text":""},{"location":"Diagnostics/HealthChecker/AuthCertificateCheck/#description","title":"Description","text":"The Auth Configuration and Auth Certificate are used by Microsoft Exchange server to enable server-to-server authentication using the Open Authorization (OAuth)
protocol standard. The Auth Certificate is also used by several Exchange Server security features which makes it important to be valid and available on all servers (except Edge Transport Servers) within the organization.
An invalid Auth Certificate can lead to these and other issues:
Access to OWA or ECP isn't working
Management of your Exchange servers via Exchange Management Shell isn't working as expected
The HealthChecker script validates multiple configurations which are having a dependency to the Auth Certificate. The script will show you if the Auth Certificate which is configured, was found on the server against which the script is currently running. It will also highlight if the certificate has been expired.
HealthChecker will display the certificate, which is configured as the next Auth Certificate (if there is one) and the effective date from which it becomes available for use by the AuthAdmin servicelet (Auth Certificate rotation to ensure a smooth transition to a new one).
Note: It's required to run the Hybrid Configuration Wizard (HCW), if you are running an Exchange Server hybrid configuration and the primary Auth Certificate has been replaced by a new one.
"},{"location":"Diagnostics/HealthChecker/AuthCertificateCheck/#included-in-html-report","title":"Included in HTML Report?","text":"Yes
"},{"location":"Diagnostics/HealthChecker/AuthCertificateCheck/#additional-resources","title":"Additional resources","text":"Maintain (rotate) the Exchange Server Auth Certificate
Replace the Auth Certificate if it has already expired or isn't available
Exchange OAuth authentication couldn't find the authorization certificate with thumbprint error when running Hybrid Configuration
MonitorExchangeAuthCertificate.ps1 script
"},{"location":"Diagnostics/HealthChecker/CTSProcessorAffinityPercentageCheck/","title":"CTS Processor Affinity Percentage Check","text":"Description:
We check if the CtsProcessorAffinityPercentage
DWORD value under HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\ExchangeServer\\V15\\Search\\SystemParameters
exists and is set to any other value than 0
. This setting can be used to limit CPU utilization of a process.
This can cause an impact to the server's search performance. This should never be used as a long term solution!
Included in HTML Report?
Yes
"},{"location":"Diagnostics/HealthChecker/CertificateCheck/","title":"Certificate Check","text":"This check retrieves all certificates from the Exchange server by using the Get-ExchangeCertificate
cmdlet. We display the following information:
We also perform the following checks:
Certificate lifetime check:
Weak key size check:
Weak hash algorithm check:
Valid Auth certificate check:
Included in HTML Report?
Yes
"},{"location":"Diagnostics/HealthChecker/CloudConnectorCheck/","title":"Cloud Connector Check","text":"This check performs testings against the Exchange Send- and Receive Connectors which are enabled for cloud usage if a hybrid configuration was detected. We run Get-HybridConfiguration
to validate if hybrid has been configured for the environment.
A proper configured Send- and Receive Connector is important - especially in hybrid scenarios. A misconfigured connector can lead to multiple issues including broken tenant attribution and email classification (internal / anonymous) which can then lead to false-positive/false-negative.
We to make sure that the mail flow between Exchange on-premises and Exchange Online works as expected
If a Send Connector has the following setting set, it means that the connector is eligible for cloud mail usage:
If a Receive Connector has the following setting set, it means that the connector is eligible for cloud mail usage:
We only perform testings for the Receive Connectors if:
We run the following checks:
Connector enabled check:
Send Connector configured to relay emails via M365 check:
TlsAuthLevel
is set to CertificateValidation
RequireTLS
is set to true
TlsDomain
is set (only performed if TlsAuthLevel
is set to DomainValidation
)TlsCertificateName configuration check:
Get-HybridConfiguration
<I>X.500Issuer<S>X.500Subject
Included in HTML Report?
Yes
Additional resources:
Certificate requirements for hybrid deployments
Demystifying and troubleshooting hybrid mail flow: when is a message internal?
Set up your email server to relay mail to the internet via Microsoft 365 or Office 365
"},{"location":"Diagnostics/HealthChecker/CredentialGuardCheck/","title":"Credential Guard Check","text":"Description:
In this check we validate, weather Credential Guard
was activated or not. Credential Guard
is not supported on an Exchange Server. This can cause a performance hit on the server.
Included in HTML Report?
Yes
Additional resources:
Manage Windows Defender Credential Guard
"},{"location":"Diagnostics/HealthChecker/DownloadDomainCheck/","title":"Download Domain Check","text":"Description:
In this check we validate if the Download Domain
feature was configured or not. This feature was introduced to address CVE-2021-1730
.
If the feature is enabled, we validate if the URL configured to download attachments, is not set to the same as the internal or external Outlook Web App (OWA) url.
CVE-2021-1730
will not be addressed if the url configured to be used by the Download Domain
feature points to the same url(s) which is/are used by OWA.
The Download Domain
feature is available on Microsoft Exchange Server 2016 and Microsoft Exchange Server 2019.
More details and configuration instructions can be found in the Microsoft Learn article, that is linked in the additional resource section.
Included in HTML Report?
Yes
Additional resources:
Configure Download Domains in Exchange Server
"},{"location":"Diagnostics/HealthChecker/EEMSCheck/","title":"Exchange Emergency Mitigation Service Check","text":"Description:
The Exchange Emergency Mitigation Server
also known as EEMS
or EM
was introduced with the Exchange Server 2019 Cumulative Update 11
and Exchange Server 2016 Cumulative Update 22
.
The Exchange Emergency Mitigation service helps to keep your Exchange Servers secure by applying mitigations to address any potential threats against your servers. It uses the cloud-based Office Config Service (OCS)
to check for and download available mitigations and to send diagnostic data to Microsoft.
The EM service runs as a Windows service on an Exchange Mailbox server. The EM service will be installed automatically on servers with the Mailbox role. The EM service will not be installed on Edge Transport servers.
The use of the EM service is optional. If you do not want Microsoft to automatically apply mitigations to your Exchange servers, you can disable the feature.
This check performs the following testings to highlight the configuration state of the EEMS:
Configuration Check
Windows Service Check
MSExchangeMitigation
Windows service startup type should be: Automatic
MSExchangeMitigation
Windows service status should be: Running
Pattern Service Check
https://officeclient.microsoft.com/GetExchangeMitigations
Mitigations Check
Diagnostic Data Check
Included in HTML Report?
Yes
Additional resources:
New security feature in September 2021 Cumulative Update for Exchange Server
Released: September 2021 Quarterly Exchange Updates
Addressing Your Feedback on the Exchange Emergency Mitigation Service
Exchange Emergency Mitigation (EM) service
Mitigations Cloud endpoint is not reachable
"},{"location":"Diagnostics/HealthChecker/ExchangeServerMaintenanceCheck/","title":"Exchange Server Maintenance Check","text":"Description:
We validate the Maintenance State for the Exchange server. We run the following checks:
Get-ServerComponentState
Get-ClusterNode
Component.State
is not Active
Component.LocalStates
and Component.RemoteStates
LocalStates
& RemoteStates
are the sameLocalStates
& RemoteStates
are differentWe show a green information Server is not in Maintenance Mode
if the server is not in maintenance mode.
We display a yellow warning Exchange Server Maintenance
if components in maintenance state are detected. We also show additional information about the Database Copy Maintenance
and Cluster Node
state.
Included in HTML Report?
Yes
Additional resources:
Determine the requestor that changed Server component state
"},{"location":"Diagnostics/HealthChecker/FIPFSCheck/","title":"FIP-FS Check","text":"Description:
We have addressed the issue causing messages to be stuck in transport queues of on-premises Exchange Server 2016
and Exchange Server 2019
. The problem relates to a date check failure with the change of the new year and it not a failure of the AV engine itself. This is not an issue with malware scanning or the malware engine, and it is not a security-related issue.
The version checking performed against the signature file is causing the malware engine to crash, resulting in messages being stuck in transport queues.
This check validates if the problematic signature file has already downloaded and processed. It shows a red warning indicating that the FIP-FS scan engine should be reset to avoid running into the transport or pattern update issue.
2112330001
) will be applied.2201010000
or greater exists under ExchangeInstallPath\\FIP-FS\\Data\\Engines\\amd64\\Microsoft\\Bin
.We also check if the server runs a fixed Exchange build (March 2022 Security Update or higher) that does not crash when the problematic version is used.
If we detect the problematic version folder and the server doesn't run a fixed build, we recommend to reset the scan engine version (see Email Stuck in Exchange On-premises Transport Queues
in the \"Additional resources\" section).
If we detect the problematic version folder but the server runs a fixed build, it should be safe to delete the folder without performing a scan engine reset. If the directory cannot be deleted, it means that the problematic version is in use. This is a problem because in this case, no new scan engine version will be applied. In this case, a reset of the scan engine must be performed.
Please follow the instructions in the references below to reset the scan engine.
Included in HTML Report?
Yes
Additional resources:
Email Stuck in Exchange On-premises Transport Queues
"},{"location":"Diagnostics/HealthChecker/GeneralHardwareInformation/","title":"General Hardware Information","text":"Description:
We show some general information about the Processor/Hardware of the Exchange server against which the script was executed.
Hardware Type:
We additionally show the following information, if HardwareType
is Physical
or AmazonEC2
: - Manufacturer - Model - Processor
Number of Processors:
ServerType
is VMWare
[1]2 Processors
installedNumber of Physical/Logical Cores:
24 Physical Cores
and running Exchange 2013/2016
[2]48 Physical Cores
and running Exchange 2019
[2]Hyper-Threading:
We show if Hyper-Threading is enabled or not.
NUMA BIOS Check:
We check to see if we can properly see all cores on the server. [3], [4]
Max Processor Speed:
We return the MaxMegacyclesPerCore
. This is the max speed that we can get out of the cores. We also check if the processor is throttled which may be a result of a misconfigured Power Plan.
Physical Memory:
We validate if the amount of installed memory meets our specifications. [5]
Included in HTML Report?
Yes
Additional resources:
1 - Does CoresPerSocket Affect Performance?
2 - Commodity servers
3 - CUSTOMER ADVISORY c04650594
4 - Exchange performance:HP NUMA BIOS settings
5 - Exchange 2013 Sizing
5 - Hardware requirements for Exchange 2016
5 - Hardware requirements for Exchange 2019
"},{"location":"Diagnostics/HealthChecker/HyperThreadingCheck/","title":"Hyper-Threading Check","text":"Description:
We validate if Hyper-Threading is enabled or not. We do this by checking if LogicalCores
is greater than PhysicalCores
which means that Hyper-Threading is enabled. We show a red error and recommend turning off Hyper-Threading.
Included in HTML Report?
Yes
Additional resources:
Exchange 2013 Sizing and Configuration Recommendations - Processing
"},{"location":"Diagnostics/HealthChecker/IISInformation/","title":"Exchange IIS Information","text":""},{"location":"Diagnostics/HealthChecker/IISInformation/#description","title":"Description","text":"We show some general information about your Exchange Server from the IIS perspective. This goes into detail to make sure that Sites and App Pools are started, which might not be easy to spot at a quick look a the server. It will also call out some common misconfiguration issues, that will cause problems with client connectivity.
"},{"location":"Diagnostics/HealthChecker/IISInformation/#sites","title":"Sites","text":"This provides the sites that we found and the following information:
Default Web Site
)NOTE: HSTS if enabled on the Back End will call out an issue.
"},{"location":"Diagnostics/HealthChecker/IISInformation/#app-pools","title":"App Pools","text":"This provides the application pools on the server with the following information:
This provides the different locations that you use for different connection endpoints with the following information:
default setting
will be provided if that is enabled Out of the Box on the server )NOTE: For each of the URL Rewrite rules, we will display additional information about the rule to let you know what it is doing. It is also recommended to remove any mitigation rules that you might have applied if you have the security fix installed on the server.
"},{"location":"Diagnostics/HealthChecker/IISInformation/#included-in-html-report","title":"Included in HTML Report?","text":"Yes
"},{"location":"Diagnostics/HealthChecker/IISWebConfigCheck/","title":"IIS Web Configuration Check","text":"Description:
After a CU or an SU install, sometimes there can be issues with the web.config or the SharedWebConfig.config file that causes issues with the virtual directories from working properly. Most of these issues are from SU installs where they are installed from double clicking on the msi file. This prevents the process from starting as administrator and can cause multiple issues.
This check detects to make sure all the default web.config and SharedWebConfig.config files exist and if they have any default variable values still set within it - %ExchangeInstallDir%
.
If Default Variable Detected
file is found, open up that file and replace the %ExchangeInstallDir%
with the Exchange Install path from (Get-ItemProperty HKLM:\\SOFTWARE\\Microsoft\\ExchangeServer\\v15\\Setup).MsiInstallPath
Included in HTML Report?
Yes, if issue detected
"},{"location":"Diagnostics/HealthChecker/IPv6EnabledCheck/","title":"IPv6 Enabled Check","text":"Description:
We check if IPv6 is enabled or not. If we determine that IPv6 has been disabled, we check to see if it's fully disabled as recommended. We determine if the IPv6 is fully disabled by checking to see if we have an IPv6 Address available on the NIC and that it matches what is found in the registry at SYSTEM\\CurrentControlSet\\Services\\TcpIp6\\Parameters\\DisabledComponents
.
If both places don't have IPv6 enabled/disabled properly a warning is thrown. This can cause communication issues if not properly disabled.
Included in HTML Report?
Yes
Additional resources:
Disabling IPv6 And Exchange \u2013 Going All The Way
Guidance for configuring IPv6 in Windows for advanced users
"},{"location":"Diagnostics/HealthChecker/InternalTransportCertificateCheck/","title":"Internal Transport Certificate","text":""},{"location":"Diagnostics/HealthChecker/InternalTransportCertificateCheck/#description","title":"Description","text":"The Internal Transport Certificate in Exchange Server is used in Exchange Server Front-End to Back-End MailFlow scenarios as well as in scenarios in which the Exchange Servers communicate with each other, using the SMTP (Simple Mail Transfer Protocol)
protocol. It is generated on a per-server base during the Exchange Server setup process and contains the computers NetBIOS (Network Basic Input/Output System)
name as well as the FQDN (Fully Qualified Domain Name)
.
A missing Internal Transport Certificate can lead to a broken MailFlow on or with the affected machine. It's therefore essential to have a valid certificate for this purpose on the machine. We recommend to not replace the self-signed certificate which was created by Exchange itself.
"},{"location":"Diagnostics/HealthChecker/InternalTransportCertificateCheck/#what-does-the-check-do","title":"What does the check do?","text":"The check queries the certificate which is marked as Internal Transport Certificate on the server against which the script is currently running. The script will throw a warning if the certificate cannot be found on the machine. It must then be recreated by the Exchange Server administrator and set as new Internal Transport Certificate.
"},{"location":"Diagnostics/HealthChecker/InternalTransportCertificateCheck/#how-to-create-a-new-internal-transport-certificate","title":"How to create a new Internal Transport Certificate?","text":"You can run the following PowerShell code from an elevated Exchange Management Shell (EMS). It will generate a new Internal Transport Certificate which replaces the existing one on the machine where the command was executed.
$newInternalTransportCertificateParams = @{\n Server = $env:COMPUTERNAME\n KeySize = 2048\n PrivateKeyExportable = $true\n FriendlyName = $env:COMPUTERNAME\n DomainName = $env:COMPUTERNAME\n IncludeServerFQDN = $true\n Services = \"SMTP\"\n Force = $true\n ErrorAction = \"Stop\"\n}\n\nNew-ExchangeCertificate @newInternalTransportCertificateParams\n
"},{"location":"Diagnostics/HealthChecker/InternalTransportCertificateCheck/#included-in-html-report","title":"Included in HTML Report?","text":"Yes
"},{"location":"Diagnostics/HealthChecker/InternalTransportCertificateCheck/#additional-resources","title":"Additional resources","text":"N/A
"},{"location":"Diagnostics/HealthChecker/LMCompatibilityLevelInformationCheck/","title":"LM Compatibility Level Information Check","text":"LAN Manager authentication level setting determines which challenge/response authentication protocol is used for network logons. This choice affects the authentication protocol level that clients use, the session security level that the computers negotiate, and the authentication level that servers accept.
Included in HTML Report?
Yes
Additional resources:
Network security: LAN Manager authentication level
"},{"location":"Diagnostics/HealthChecker/MAPIFrontEndAppPoolGCModeCheck/","title":"MAPI Front End App Pool GC Mode Check","text":"Description:
We validate the Garbage Collection (GC) configuration for MSExchangeMapiFrontEndAppPool
App Pool if the check is executed against an Exchange 2013 server that is not running the EdgeTransport role.
We check if:
The server has a total memory of 21474836480 MB
and gcServer.Enabled
set to false
\\ In this case we recommend to enable Server GC
.
gcServer.Enabled
is neither true
nor false
\\ This case should be investigated.
gcServer.Enabled
is false
In this case we're running Workstation GC.\\ You could be seeing some GC issues within the MSExchangeMapiFrontEndAppPool
App Pool. However, you don't have enough memory installed on the system to recommend switching the GC mode by default without consulting a support professional.
How to fix this:
MSExchangeMapiFrontEndAppPool_CLRConfig.config
\\ You can find the file by running %winDir%\\system32\\inetSrv\\AppCmd.exe list AppPool \"MSExchangeMapiFrontEndAppPool\" /text:\"CLRConfigFile\"
via cmd.exe
\\ It should be located here: %ExchangeInstallPath%\\bin\\MSExchangeMapiFrontEndAppPool_CLRConfig.config
notepad.exe
and change the gcServer Enabled
value from false
to true
MAPI Front End App Pool
by running: Restart-WebAppPool MSExchangeMapiFrontEndAppPool
via PowerShell
or by running:\\ %winDir%\\system32\\inetSrv\\AppCmd.exe RECYCLE AppPool \"MSExchangeMapiFrontEndAppPool\"
via cmd.exe
Included in HTML Report?
Yes
Additional resources:
Fundamentals of garbage collection
Workstation and server garbage collection
"},{"location":"Diagnostics/HealthChecker/May22SU/","title":"May 2022 Security Update","text":"In order to protect against CVE-2022-21978 within your environment /PrepareDomain
must be run against each domain that contains the MESO container within it.
Health Checker will query all the domains in the environment to see if it has a MESO container. If it does, it checks for a particular ACE or version number of the MESO container to see if we are secure. If we don't pass this check, it will provide what domains you need to run /PrepareDomain
against.
In order to protect your environment from CVE-2022-21978, you must install the May 2022 SU or a newer SU/CU that contains this security fix. All SUs and CUs after May 2022 contain this fix. After you have installed this security fix, you must run /PrepareDomain
or /PrepareAllDomains
from the Exchange bin directory.
Included in HTML Report?
Yes
Additional resources:
Exchange Team Blog - May SU 2022
"},{"location":"Diagnostics/HealthChecker/NETFrameworkSupportabilityCheck/","title":".NET Framework Supportability Check","text":"Description:
We check if the Exchange server is running a supported .NET Framework version. We do this based on the information provided by PG on Microsoft Docs (.NET Supportability Matrix).
Included in HTML Report?
Yes
Additional resources:
Microsoft .NET Framework Supportability Matrix
"},{"location":"Diagnostics/HealthChecker/NumaBiosCheck/","title":"NUMA BIOS / All Processor Cores Visible Check","text":"Description:
Check to see if the OS is able to see all the processor cores on the server. What normally happens is the OS is able to see 1 processor socket presented (aka half the number of cores)
This can become a major problem on a server if you do not see all the processor cores for a few reasons.
Logic is built into the Exchange Code to handle user workload management is based of the how much CPU the user is using or the process itself. When we aren't able to see all the cores on the system, the process can consume a higher amount than what logic dictates. We base this logic off of the number of cores presented to the OS by [System.Environment]::ProcessorCount
. Because the underlying hardware has full access to all the processor cores, the process can go above what Exchange calculated out to set the threshold to be at and then throttling can occur.
Sometimes the underlying setting isn't able to keep up and doesn't distribute the load between both the processor sockets, thus causing an issue because the application just lost half of its resources. You can see this occur when you look at the performance counter \"\\Processor Information(0,_Total)\\% Processor Time\" and \"\\Processor Information(1,_Total)\\% Processor Time\" as each one sees their own socket. One will go up while the other goes down. This might only happen for a few seconds, but there are health checks on the server that can be triggered to cause additional issues that will spiral the server.
Included in HTML Report?
Yes
Additional resources:
CUSTOMER ADVISORY c04650594
Exchange performance:HP NUMA BIOS settings
Exchange 2016 users unable to edit Distribution Group membership using Outlook
"},{"location":"Diagnostics/HealthChecker/OpenRelayDomain/","title":"Open Relay Domain","text":"Description:
We show a warning if we weren't able to run Get-AcceptedDomain
and provide an unknown
status. If we determine that an Open Relay Domain is set on the environment, we will throw an error in the results and provide which accepted domain ID is set with this. It is recommended to have an anonymous relay and scope down the receive connector for who can use it. Otherwise, you are allowing anybody to use your environment to send mail anywhere.
NOTE: After installing the September 2021 CUs for Exchange 2016/2019, you can see crashes occur on your system for the transport services that look like this:
Log Name: Application\nSource: MSExchange Common\nDate: 12/3/2021 12:40:35 PM\nEvent ID: 4999\nTask Category: General\nLevel: Error\nKeywords: Classic\nUser: N/A\nComputer: Contoso-E19A.Contoso.com\nDescription:\nWatson report about to be sent for process id: 10072, with parameters: E12IIS, c-RTL-AMD64, 15.02.0986.005, MSExchangeDelivery, M.Exchange.Transport, M.E.T.AcceptedDomainTable..ctor, System.FormatException, 28d7-DumpTidSet, 15.02.0986.005.\nErrorReportingEnabled: False\n
This is caused by having an Internal Relay with an Accepted Domain of *. This is not a recommended configuration.
Included in HTML Report?
Yes
Additional resources:
Allow anonymous relay on Exchange servers
"},{"location":"Diagnostics/HealthChecker/PacketsLossCheck/","title":"Packets Loss Check","text":"Description:
We check if there are any PacketsReceivedDiscarded
logged for the NIC. Large package loss can cause a performance impact on a system and should be investigated and fixed.
PacketsReceivedDiscarded
is 0
PacketsReceivedDiscarded
lower than 1000
PacketsReceivedDiscarded
greater than 1000
NOTE: This counter is accumulation from reboot, or if the NIC setting was changed, so the counter can be stale for some time. However, even though you might not be actively dropping packets, the counter should be at 0 in a healthy environment.
Included in HTML Report?
Yes
Additional Information
Large packet loss in the guest OS using VMXNET3 in ESXi (2039495)
Disable \"adaptive rx ring sizing\" to avoid random interface reset (78343)
"},{"location":"Diagnostics/HealthChecker/PagefileSizeCheck/","title":"Pagefile Size Check","text":"Description:
We check if the Pagefile is configured as recommended and that there is only 1 PageFile configured (multiple PageFiles can cause performance issues on Exchange server).
"},{"location":"Diagnostics/HealthChecker/PagefileSizeCheck/#exchange-2019","title":"Exchange 2019","text":"Set the paging file minimum and maximum value to the same size:
Less than 32 GB of RAM installed: Physical RAM plus 10MB, up to a maximum value of 32GB (32,778MB)
32 GB of RAM or more installed: 32GB
You can set the pagefile to a static size via wmic
whereas InitialSize
and MaximumSize
is the size in megabytes calculated based on the Exchange Server version and memory installed in the server:
wmic ComputerSystem set AutomaticManagedPagefile=False\nwmic PageFileSet set InitialSize=1024,MaximumSize=1024\n
Included in HTML Report?
Yes
Additional resources:
PageFile requirements for Exchange 2019
PageFile requirements for Exchange 2016
PageFile requirements for Exchange 2013
"},{"location":"Diagnostics/HealthChecker/ProcessorCheck/","title":"Number Of Processors","text":"Description:
Number of Processors is the number of processor sockets detected on the server. It is only recommended to have up to 2 processors on the server. [3]
An additional note is displayed if Type
is set to VMware
and greater than 2 processors. [1]
([array](Get-WmiObject -Class Win32_Processor)).count\n
"},{"location":"Diagnostics/HealthChecker/ProcessorCheck/#number-of-logical-and-physical-cores","title":"Number Of Logical and Physical Cores","text":"Show the number of Physical and Logical cores presented to the OS. This is provided by the WmiObject class Win32_Processor
.
24 Logical Cores
and running Exchange 2013/2016
[2]48 Logical Cores
and running Exchange 2019
[2]$processor = Get-WmiObject -Class Win32_Processor\n$processor |ForEach-Object {$logical += $_.NumberOfLogicalProcessors; $physical += $_.NumberOfCores}\nPS C:\\> $logical\n24\nPS C:\\> $physical\n12\n
"},{"location":"Diagnostics/HealthChecker/ProcessorCheck/#max-processor-speed","title":"Max Processor Speed","text":"Check to see what the Max Processor Speed is set to for the processor. If the processor is throttled which may be a result of a misconfigured Power Plan.
NOTE: If Power Plan isn't set to High Performance and the processor is being throttled, this will be flagged that Power Plan is the cause and to fix it ASAP.
"},{"location":"Diagnostics/HealthChecker/ProcessorCheck/#how-this-is-checked_2","title":"How This Is Checked","text":"$processor = Get-WmiObject -Class Win32_Processor\n$throttled = $processor | Where-Object {$_.CurrentClockSpeed -lt $_.MaxClockSpeed}\n\nif ($throttled) {\n Write-Host (\"Throttling your CPU\")\n}\n
Included in HTML Report?
Yes
Additional resources:
1 - Does CoresPerSocket Affect Performance?
2 - Commodity servers
3 - Hardware requirements for Exchange 2019
Exchange 2013 Sizing
Hardware requirements for Exchange 2016
"},{"location":"Diagnostics/HealthChecker/RPCMinConnectionTimeoutCheck/","title":"RPC Minimum Connection Timeout Check","text":"Description:
By default, Outlook Anywhere opens two default connections to the Exchange CAS called RPC_InData
and RPC_OutData
. The Outlook Anywhere client to server used a default timeout of 12 minutes (720 seconds)
of inactivity and the server to the client timeout is 15 minutes (900 seconds)
.
These default Keep-Alive intervals are not aggressive enough for some of today's home networking devices and/or aggressive network devices on the Internet. Some of those devices are dropping TCP connections after as little as 5 minutes (300 seconds)
of inactivity. When one or both of the two default connections are dropped, the connection to the Exchange server is essentially broken and not useable.
Included in HTML Report?
Yes
Additional resources:
Outlook Anywhere Network Timeout Issue
"},{"location":"Diagnostics/HealthChecker/RSSEnabledCheck/","title":"RSS Enabled Check","text":"Description:
We check on Windows 2012 R2
or newer whether RSS (if it's supported from the NIC) is enabled or not. This is collected by the Get-NetAdapterRss
cmdlet. We show a warning if it's supported on NIC-side but disabled.
The Get-NetAdapterRss cmdlet gets receive side scaling (RSS) properties of the network adapters that support RSS. RSS is a scalability technology that distributes the receive network traffic among multiple processors by hashing the header of the incoming packet and using an indirection table. Without RSS in Windows Server\u00ae 2012 and later, network traffic is received on the first processor which can quickly reach full utilization limiting receive network throughput. Various properties can be configured to optimize the performance of RSS.
Included in HTML Report?
Yes
Additional resources:
Introduction to Receive Side Scaling
"},{"location":"Diagnostics/HealthChecker/RebootPending/","title":"Reboot Pending","text":"Description:
We show a warning if we detect an outstanding pending reboot. We also display the type of pending reboot. We differentiate between:
It is best to reboot the server to address these issues. It may take some time after a reboot to have the keys automatically removed. However, if they don't remove automatically, follow these steps to address the issue for the keys that were provided to be a problem.
NOTE: With Component Based Servicing\\RebootPending
you need to do the same for Component Based Servicing\\PackagesPending
prior to RebootPending
NOTE: Follow the steps in this section carefully. Serious problems might occur if you modify the registry incorrectly. Before you modify it, back up the registry for restoration in case problems occur.
Included in HTML Report?
Yes
Additional resources:
Determine Pending Reboot Status\u2014PowerShell Style! Part 1
Determine Pending Reboot Status\u2014PowerShell Style! Part 2
"},{"location":"Diagnostics/HealthChecker/RunHCViaSchedTask/","title":"How to run the Exchange Health Checker via Scheduled Task","text":"Description:
You can run the Exchange Health Checker script by the help of a Scheduled Task on a daily, weekly or monthly base.
This article describes some of the ways how to run the script as task and how to create those tasks.
Note: We assume that the script is stored under C:\\Scripts\\HealthChecker
. Please make sure to adjust the path if you use a different one in your environment.
View-Only Organization Management
instead of Organization Management
. This should be sufficient for the script to run.Note: Using View-Only Organization Management
instead of Organization Management
requires you to add the account to the local Administrators
group on each server. This can be achieved by creating a dedicated Security Group
which is then added to the Administrators
group on each Exchange server (manually or via Group Policy
).
We need to create multiple objects and finally combining them to the Scheduled Task. We need a trigger
, settings
, action
and task
object.
Create a trigger that defines when the script should be executed:
$hcTrigger = New-ScheduledTaskTrigger -Daily -At 3am
$hcTrigger = New-ScheduledTaskTrigger -Weekly -WeeksInterval 4 -DaysOfWeek Monday -At 3am
Create a Scheduled Task setting object:
$hcSettings = New-ScheduledTaskSettingsSet
RestartCount
and RestartInterval
:$hcSettings = New-ScheduledTaskSettingsSet -RestartCount 3 -RestartInterval (New-TimeSpan -Minutes 60)
Define the actions to be executed via Scheduled Task:
$hcAction = New-ScheduledTaskAction -Execute 'powershell.exe' -WorkingDirectory \"C:\\Scripts\\HealthChecker\\\" -Argument '-NonInteractive -NoLogo -NoProfile -Command \".\\HealthChecker.ps1 -ScriptUpdateOnly; .\\HealthChecker.ps1; .\\HealthChecker.ps1 -BuildHtmlServersReport\"'
ExchSrv01
in this example):$hcAction = New-ScheduledTaskAction -Execute 'powershell.exe' -WorkingDirectory \"C:\\Scripts\\HealthChecker\\\" -Argument '-NonInteractive -NoLogo -NoProfile -Command \".\\HealthChecker.ps1 -ScriptUpdateOnly; .\\HealthChecker.ps1 -Server ExchSrv01; .\\HealthChecker.ps1 -BuildHtmlServersReport\"'
Create the Scheduled Task object using the pre-defined action, trigger and settings objects:
$hcTask = New-ScheduledTask -Action $hcAction -Trigger $hcTrigger -Settings $hcSettings
Create the Scheduled Task:
Register-ScheduledTask -TaskName 'HealthChecker Daily Run' -InputObject $hcTask -User (Read-Host \"Please enter username in format (Domain\\Username)\") -Password (Read-Host \"Please enter password\")
Additional resources:
New-ScheduledTaskTrigger
New-ScheduledTaskSettingsSet
New-ScheduledTaskAction
New-ScheduledTask
Register-ScheduledTask
"},{"location":"Diagnostics/HealthChecker/SMBv1Check/","title":"SMBv1 Check","text":"To make sure that your Exchange organization is better protected against the latest threats (for example Emotet, TrickBot or WannaCry to name a few) we recommend disabling SMBv1 if it's enabled on your Exchange (2013/2016/2019) server.
There is no need to run the nearly 30-year-old SMBv1 protocol when Exchange 2013/2016/2019 is installed on your system. SMBv1 isn't safe and you lose key protections offered by later SMB protocol versions.
This check verifies that SMBv1 is not installed (if OS allows) and that its activation is blocked.
Included in HTML Report?
Yes
Additional resources:
Exchange Server and SMBv1
"},{"location":"Diagnostics/HealthChecker/SerializedDataSigningCheck/","title":"PowerShell Serialization Payload Signing","text":""},{"location":"Diagnostics/HealthChecker/SerializedDataSigningCheck/#description","title":"Description","text":"Certificate-based signing of PowerShell Serialization Payload is a defense-in-depth security feature to prevent malicious manipulation of serialized data exchanged in Exchange Management Shell (EMS) sessions.
The Serialized Data Signing feature was introduced with the January 2023 Exchange Server Security Update (SU). It's available on Exchange Server 2013, Exchange Server 2016 and Exchange Server 2019 and enabled by default with the November 2023 Security Update.
The HealthChecker check validates that the feature is enabled on supported Exchange builds.
Documentation Moved
This documentation has been moved to Microsoft Learn. Please read Configure certificate signing of PowerShell serialization payloads in Exchange Server for more information.
"},{"location":"Diagnostics/HealthChecker/SerializedDataSigningCheck/#included-in-html-report","title":"Included in HTML Report?","text":"Yes
"},{"location":"Diagnostics/HealthChecker/SerializedDataSigningCheck/#additional-resources","title":"Additional resources","text":"Released: January 2023 Exchange Server Security Updates
Released: November 2023 Exchange Server Security Updates
MonitorExchangeAuthCertificate.ps1 script
"},{"location":"Diagnostics/HealthChecker/SettingOverridesCheck/","title":"Setting Overrides","text":""},{"location":"Diagnostics/HealthChecker/SettingOverridesCheck/#description","title":"Description","text":"Setting Overrides can be configured via New-SettingOverride
cmdlet and in certain cases with the help of registry values. They can be created to change default values for common Exchange services and features (e.g., the default run cycle of the Managed Folder Assistant).
Sometimes they are used to enable new features like the recently introduced Serialized Data Signing for PowerShell payload.
In very rare cases, Microsoft recommends to disable a feature or component by the help of an override (e.g., EWS web application pool stops after the February 2023 Security Update is installed) to work around known issues.
HealthChecker checks for known overrides which should be removed as a solution for to a particular problem is available.
Important
Incorrect usage of the setting override cmdlets can cause serious damage to your Exchange organization. This damage could require you to reinstall Exchange. Only use these cmdlets as instructed by product documentation or under the direction of Microsoft Customer Service and Support.
"},{"location":"Diagnostics/HealthChecker/SettingOverridesCheck/#setting-overrides_1","title":"Setting Overrides","text":"Feature Exchange Version(s) Controlled via Recommended setting BaseTypeCheckForDeserialization 2013, 2016, 2019 Registry Value DisabledEnable:
New-ItemProperty -Path HKLM:\\SOFTWARE\\Microsoft\\ExchangeServer\\v15\\Diagnostics -Name \"DisableBaseTypeCheckForDeserialization\" -Value 1 -Type String\n
Disable:
Remove-ItemProperty -Path HKLM:\\SOFTWARE\\Microsoft\\ExchangeServer\\v15\\Diagnostics -Name \"DisableBaseTypeCheckForDeserialization\"\n
Feature Exchange Version(s) Controlled via Recommended setting Strict Mode for ClientExtensionCollectionFormatter 2016, 2019 New-SettingOverride Enabled Enable:
Get-SettingOverride | Where-Object {$_.ComponentName -eq \"Data\" -and $_.SectionName -eq \"DeserializationBinderSettings\" -and $_.Parameters -eq \"LearningLocations=ClientExtensionCollectionFormatter\"} | Remove-SettingOverride\n
Disable:
New-SettingOverride -Name \"Adding learning location ClientExtensionCollectionFormatter\" -Component Data -Section DeserializationBinderSettings -Parameters @(\"LearningLocations=ClientExtensionCollectionFormatter\") -Reason \"Deserialization failed\"\n
"},{"location":"Diagnostics/HealthChecker/SettingOverridesCheck/#included-in-html-report","title":"Included in HTML Report?","text":"Yes
"},{"location":"Diagnostics/HealthChecker/SettingOverridesCheck/#additional-resources","title":"Additional resources","text":"New-SettingOverride
Remove-SettingOverride
"},{"location":"Diagnostics/HealthChecker/SleepyNICCheck/","title":"Sleepy NIC Check","text":"Description:
We validate the NIC power saving options. It's recommended to disable NIC power saving options as this may cause packet loss.
To detect the NIC power saving options, we're probing the sub keys under: HKLM\\SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002bE10318}
We then check if the PnPCapabilities
REG_DWORD exists and if it does, we're validating its value. If it's 24
or 280
, NIC power saving is disabled as we recommend it.
We skip this check for Multiplexor NIC adapters
and in case that the host system is Hyper-V
(because we're assuming that we don't support NIC power saving options on this platform).
NOTE: If the REG_DWORD doesn't exists, we're assuming that NIC power saving is not disabled or configured and show a warning.
Included in HTML Report?
Yes
Additional resources:
Information about power management setting on a network adapter
"},{"location":"Diagnostics/HealthChecker/TCPIPSettingsCheck/","title":"TCP/IP Settings Check","text":"Description:
We validate if a KeepAliveTime
DWORD value exists under HKEY_LOCAL_MACHINE\\System\\CurrentControlSet\\Services\\TcpIp\\Parameters
and verify that it is set to a recommended value.
Exchange TCP KeepAliveTime
registry entry should be set to a decimal value between 900000 and 1800000 (15 to 30 minutes in milliseconds). If there's no entry in the registry for KeepAliveTime
then the default value is 2 hours.
This value, if not set correctly, can affect both connectivity and performance. You must make sure that the load balancer and any other devices in the path from client to Exchange are configured correctly.
The goal is to set Exchange with the lowest value so that client sessions, when ended, are ended by Exchange and not by the device.
Example:
Client -> Firewall (1 hour) -> NLB (40 minutes) -> Exchange Servers (20 Minutes)
Included in HTML Report?
Yes
Additional resources:
Checklist for Troubleshooting Performance Related issues in Exchange 2013, 2016 and 2019 (on-prem)
"},{"location":"Diagnostics/HealthChecker/TLSConfigurationCheck/","title":"TLS Configuration Check","text":"We check and validate Exchange servers TLS 1.0 - 1.3 configuration. We can detect mismatches in TLS versions for client and server. This is important because Exchange can be both a client and a server.
We will also show a yellow warning, if TLS 1.0 and/or TLS 1.1 is enabled. Microsoft's TLS 1.0 implementation is free of known security vulnerabilities. Due to the potential for future protocol downgrade attacks and other TLS 1.0 vulnerabilities not specific to Microsoft's implementation, it is recommended that dependencies on all security protocols older than TLS 1.2 be removed where possible (TLS 1.1/1.0/ SSLv3/SSLv2).
At this time TLS 1.3 is not supported by Exchange and has been known to cause issues if enabled. If detected to be anything but disabled on Exchange, it will be thrown as an error and needs to be addressed right away.
We also check for the SystemDefaultTlsVersions registry value which controls if .NET Framework will inherit its defaults from the Windows Schannel DisabledByDefault registry values or not.
An invalid TLS configuration can cause issues within Exchange for communication.
Only the values 0 or 1 are accepted and determined to be properly configured. The reason being is this is how our documentation provides to configure the value only and it then depends on how the code reads the value from the registry interpret the value.
By not having the registry value defined, different versions of .NET Frameworks for what the code is compiled for will treat TLS options differently. Therefore, we throw an error if the key isn't defined and action should be taken to correct this as soon as possible. To correct this, you create the missing DWORD
registry key with the value you wish to have.
The Configuration
result can provide a value of Enabled
, Disabled
, Half Disabled
, or Misconfigured
. They are defined by the following conditions:
The location where we are checking for the TLS values are here:
SYSTEM\\CurrentControlSet\\Control\\SecurityProviders\\SCHANNEL\\Protocols\\TLS 1.0\\Client
SYSTEM\\CurrentControlSet\\Control\\SecurityProviders\\SCHANNEL\\Protocols\\TLS 1.0\\Server
SYSTEM\\CurrentControlSet\\Control\\SecurityProviders\\SCHANNEL\\Protocols\\TLS 1.1\\Client
SYSTEM\\CurrentControlSet\\Control\\SecurityProviders\\SCHANNEL\\Protocols\\TLS 1.1\\Server
SYSTEM\\CurrentControlSet\\Control\\SecurityProviders\\SCHANNEL\\Protocols\\TLS 1.2\\Client
SYSTEM\\CurrentControlSet\\Control\\SecurityProviders\\SCHANNEL\\Protocols\\TLS 1.2\\Server
SYSTEM\\CurrentControlSet\\Control\\SecurityProviders\\SCHANNEL\\Protocols\\TLS 1.3\\Client
SYSTEM\\CurrentControlSet\\Control\\SecurityProviders\\SCHANNEL\\Protocols\\TLS 1.3\\Server
At each location, we are looking at the value of Enabled
and DisabledByDefault
. If the key isn't present, Enabled
is set to true
and DisabledByDefault
is set to false
. With the exception of TLS 1.3, if that isn't present it is disabled by default.
The location for the .NET Framework TLS related settings are located here:
SOFTWARE\\Wow6432Node\\Microsoft\\.NETFramework\\v4.0.30319
SOFTWARE\\Microsoft\\.NETFramework\\v4.0.30319
SOFTWARE\\Wow6432Node\\Microsoft\\.NETFramework\\v2.0.50727
SOFTWARE\\Microsoft\\.NETFramework\\v2.0.50727
At each location, we are looking at the value of SystemDefaultTlsVersions
and SchUseStrongCrypto
. If the key isn't present, both are set to false
.
Included in HTML Report?
Yes
Additional resources:
Exchange Server TLS configuration best practices
Solving the TLS 1.0 Problem, 2nd Edition
TLS 1.2 support at Microsoft
Exchange Server TLS guidance, part 1: Getting Ready for TLS 1.2
Exchange Server TLS guidance Part 2: Enabling TLS 1.2 and Identifying Clients Not Using It
Exchange Server TLS guidance Part 3: Turning Off TLS 1.0/1.1
"},{"location":"Diagnostics/HealthChecker/VisualCRedistributableVersionCheck/","title":"Visual C++ Redistributable Version Check","text":"Description:
We check if the the latest Visual C++ Redistributable version, required for the installed Exchange server role, is installed or not.
Included in HTML Report?
Yes
Additional resources:
Microsoft Visual C++ Redistributable Latest Supported Downloads
Exchange Server 2019 prerequisites
Exchange Server 2016 prerequisites
"},{"location":"Diagnostics/HealthChecker/VulnerabilityCheck/","title":"Vulnerability Check","text":"The script performs different checks to detect vulnerabilities which may lead into a security issue for the Exchange server.
Vulnerability checks performed:
CVE-2020-0796
SMBv3 vulnerabilityCVE-2020-1147
.NET Core & .NET Framework vulnerabilityCVE-2021-1730
Download Domains stateIncluded in HTML Report?
Yes
"},{"location":"Hybrid/Test-HMAEAS/","title":"Validating Hybrid Modern Authentication setup for Outlook for iOS and Android","text":"Download the latest release: Test-HMAEAS.ps1
This script allows you to check and see if your on-premises Exchange environment is configured correctly to use Hybrid Modern Authentication (HMA) with Outlook for iOS and Android. For this to work correctly, you will need to enable HMA and follow HMA Outlook for iOS and Android guidance to configure this feature properly.
To run the script, at minimum you will need a valid SMTP Address for a user that is located on-premises.
To test basic AutoDiscover and a Empty Bearer Authorization check you can run:
.\\Test-HMAEAS.ps1 user@contoso.com\n
To test basic AutoDiscover with a custom AutoDiscover Name and also do Empty Bearer Authorization check you can run:
.\\Test-HMAEAS.ps1 user@contoso.com -CustomAutoD autodiscover.contoso.com\n
To test basic EAS Connectivity you can run (you will need to use the users credentials for this test):
.\\Test-HMAEAS.ps1 user@contoso.com -TestEAS\n
"},{"location":"M365/DLT365Groupsupgrade/","title":"DLT365GroupsUpgrade","text":"Download the latest release: DLT365GroupsUpgrade.ps1
"},{"location":"M365/DLT365Groupsupgrade/#validating-distribution-group-eligibility-for-upgrade-to-o365-group","title":"Validating Distribution group eligibility for upgrade to O365 Group","text":"This script allows you to check Distribution to O365 Group migration eligibility for a specific distribution group SMTP, for more information over the Distribution to O365 Group migration blockers please check: https://docs.microsoft.com/en-us/microsoft-365/admin/manage/upgrade-distribution-lists?view=o365-worldwide
The script will prompt for global administrator username & password to connect to EXO Then the script will ask for required group smtp Then start to check and provide feedback in case group migration blockers found as illustrated below:
"},{"location":"NewUserGuide/","title":"New User Guide","text":""},{"location":"NewUserGuide/#introduction","title":"Introduction","text":"If you are new to Git and GitHub, and you want to contribute to CSS-Exchange, you've come to the right place.
There are many, many resources on how to use Git and GitHub. We recommend starting with Pro Git. Reading chapters 1 to 3 provides a great foundation for understanding and using Git.
This page will serve as a quick start that leads you through submitting a Pull Request to CSS-Exchange step by step.
This page will not cover the use of any GUI that attempts to insulate the user from the Git command line. In this author's opinion, the only way to really learn Git is to use the command line, so that's all we'll cover here.
"},{"location":"NewUserGuide/#before-you-start","title":"Before You Start","text":"If you are considering a large change to a script or a brand new script, it's often a good idea to open an Issue first to discuss the change. This will allow the repository owners to provide feedback on whether they would accept this type of change. By getting feedback before you spend days on a complex change, you can ensure that you're not wasting your time.
"},{"location":"NewUserGuide/#installation","title":"Installation","text":"The first step is to fork the repository on GitHub. Unless you have Write access to CSS-Exchange, you can't push directly to our repo. Creating a fork creates your own copy of the repo on GitHub, so you have somewhere to push your changes.
To fork the repository, use the Fork icon at the top right of the repository page.
You'll be prompted for a name and description. The defaults are fine. When the fork is complete, you'll be taken to the new repository page. At the top left, you should see that you are now on your own fork.
"},{"location":"NewUserGuide/#cloning-the-repository","title":"Cloning the repository","text":"Now you're ready to start using the git command line. To clone the repository, drop down the Code button and copy the URL:
Then use that URL to clone the repository using the command line:
git clone <url>\n
This creates a folder called CSS-Exchange
in your current directory.
Change into the folder that was just created. Your shell should now look something like this.
Because we have PoshGit loaded, it's showing our current branch name in the prompt - main. Let's create a new branch for our work. It's nice to use a descriptive name. For example, if we're updating this guide, we might call name it like so:
"},{"location":"NewUserGuide/#making-changes","title":"Making changes","text":"Now that you're on your own branch, you're ready to make your changes. You can technically use any tool you like - notepad, vim, whatever. But, if you open the repo root folder in Visual Studio Code, many of the repository formatting settings will be applied automatically. You can also shift-alt-F to reformat a file according to the settings. This may save you some time later.
For this example, I created a new script called New-Script.ps1.
After making our changes, it's a good idea to verify that git sees everything we changed, and that we haven't changed any files we didn't intend to. Because we have PoshGit, just hitting Enter to get a new prompt shows us some information about how many files have changed. We can also run git status
to see some details.
This looks good. My intent was to add one script file, and that's the only change shown here.
"},{"location":"NewUserGuide/#formatting-changes","title":"Formatting changes","text":"CSS-Exchange has some formatting requirements to ensure consistency, and these checks are integrated into our build process. Before committing changes, let's run .build\\CodeFormatter.ps1
to see if our new script meets the requirements.
CodeFormatter highlighted a few problems here:
CodeFormatter will fix some problems automatically if the -Save switch is included. Let's run it again with -Save.
Here we see CodeFormatter automatically fixed all of these issues when run with the -Save switch. Running a second time, we can confirm everything was fixed, as it generates no output at all.
"},{"location":"NewUserGuide/#staging-changes","title":"Staging changes","text":"We're almost ready to commit our changes, but first we should stage them. Staging gives us a chance to sanity-check what we're about to commit before we actually commit. It's especially useful when we have modified several files for testing, but we only intend to commit some of them.
If we run git status
again, we should once again see that only one file is modified for our simple test case. Then we can stage our file with git add
, and check the result again with git status
.
When we have many files to commit, we can use git add .
to stage all files in the current folder and SubFolders, or git add :/
to stage all files everywhere. When using those options, it's especially important to check git status
to make sure we haven't staged something we didn't intend to.
If git status
shows that the correct files are staged, we can commit them with git commit
. This will open the default editor, which will be Visual Studio Code if you chose it when installing Git as described earlier.
The top line should be the title of the commit. Then skip a line and add further details as necessary. Close the tab, choose Save when prompted, and we see the following output.
Now our changes are committed to our local copy of our branch, but we need to push those to GitHub.
"},{"location":"NewUserGuide/#pushing-the-changes","title":"Pushing the changes","text":"Because this is the first time we're pushing changes for our new branch, we have to provide a few details. On our first push of our new branch, the syntax will be git push -u origin <branch name>
.
Origin means we're pushing to the location we cloned from - this is the name of the remote repo by default. The -u
parameter tells it to set this as our upstream for this branch. We only have to do this the first time. If we make additional changes on this branch and commit them, we can now push them to the server with a simple git push
, since we have now told it that origin will be our upstream going forward.
Now we're ready to request that our changes be pulled into the official repo.
"},{"location":"NewUserGuide/#creating-a-pull-request","title":"Creating a Pull Request","text":"There are a few ways to create a Pull Request. We can see in the previous screenshot that GitHub helpfully shows us a URL we can visit to start a Pull Request. You can also manually navigate to the Pull Request tab of the official repo, and create a new Pull Request there. You might even see a prompt to create a PR for the branch you just pushed. Either of these methods will work.
At this point we're presented with a form to provide some details about the PR. Be sure that at the top of the PR form, we see the official repo and the main
branch on the left, followed by your fork and the branch you created on the right.
Fill in the details and hit Create Pull Request.
"},{"location":"NewUserGuide/#responding-to-feedback","title":"Responding to feedback","text":"The repository owners will often request some changes to our code by commenting on the Pull Request. To update the code in the Pull Request, simply make the additional changes in your local files, stage them, and commit them just as before. Then, git push
. Remember, we don't need any other parameters on the push this time. After pushing new changes, we should see the PR update almost instantly.
Once the owners are satisfied with the changes, they will approve and merge the PR. And we're done!
"},{"location":"NewUserGuide/#cleaning-up","title":"Cleaning up","text":"Once the PR is merged, we can delete our fork and delete the folder containing our local clone. We can keep the fork around if we intend to contribute further, but the main
branch of the fork will not automatically pull in the latest changes from the official repo. It will get further and further out of date, which may cause problems with future pull requests. To avoid this, we'll need to pull in the changes from the main
branch of the official repo into our fork. This is out of scope for this guide, so we'll leave this an exercise for the reader.
Download the latest release: ExPerfAnalyzer.ps1
"},{"location":"Performance/ExPerfAnalyzer/#running-the-script","title":"Running the script","text":".\\ExPerfAnalyzer.ps1 .\\EXSERVER01_FULL_000001.BLG\n
"},{"location":"Performance/ExPerfAnalyzer/#registering-script-as-a-default-handler","title":"Registering script as a default handler","text":".\\ExPerfAnalyzer.ps1 -RegisterHandler\n
PowerShell must be running as an administrator for this command to work. The script will register itself as a shell handler for perfmon .blg files. You can then right-click any .blg file and select ExPerfAnalyzer to quickly parse the file.
"},{"location":"Performance/ExPerfAnalyzer/#inspiration","title":"Inspiration","text":"This script was inspired by Performance Analysis of Logs (PAL) and PMA.VBS (an internal tool used by Windows support).
"},{"location":"Performance/ExPerfAnalyzer/#faq","title":"FAQ","text":"This takes forever to run.
It's faster than PAL.
Why don't I just use PAL?
You could, but PAL takes even longer to run and throws a lot of false positives.
What's the expected running time?
v0.2.2 and an Intel Core i7-4810MQ @ 2.8Ghz processed a 1GB perfmon sitting on an SSD in 11 seconds.
Can I edit this script however I'd like?
Yes, that's the magic of open source software!
Do you accept pull requests? Can I contribute to the script?
Of course!
Download the latest release: ExPerfWiz.ps1
ExPerfWiz is a PowerShell based script to help automate the collection of performance data on Exchange 2013, 2016 and 2019 servers.\u00a0 Supported operating systems are Windows 2012, 2012 R2, 2016 and 2019 Core and Standard.
"},{"location":"Performance/ExPerfWiz/#initial-run","title":"Initial Run","text":"Run .\\ExPerfWiz.ps1 from an elevated shell.
Once a prompt is returned all of the ExPerfWiz functions will now be available to run.
"},{"location":"Performance/ExPerfWiz/#common-usage","title":"Common Usage","text":"New-ExPerfWiz -FolderPath C:\\PerfWiz -StartOnCreate
The following functions are provided by ExPerfWiz to manage data collection.
"},{"location":"Performance/ExPerfWiz/#get-experfwiz","title":"Get-ExPerfWiz
","text":"Gets ExPerfWiz data collector sets
Switch Description Default Name Name of the Data Collector set Exchange_PerfWiz Server Name of the Server Local Machine ShowLog Displays the ExPerfWiz Log file NA"},{"location":"Performance/ExPerfWiz/#new-experfwiz","title":"New-ExPerfWiz
","text":"Creates an ExPerfWiz data collector set Will overwrite any existing sets with the same name
Switch Description Default Circular Enabled or Disable circular logging Disabled Duration How long should the performance data be collected 08:00:00 FolderPath Output Path for performance logs NA Interval How often the performance data should be collected. 5s MaxSize Maximum size of the perfmon log in MegaBytes (256-4096) 1024Mb Name The name of the data collector set Exchange_PerfWiz Server Name of the server where the perfmon collector should be created Local Machine StartOnCreate Starts the counter set as soon as it is created False StartTime Daily time to start perfmon counter NA Template XML perfmon template file that should be loaded to create the data collector set. Exch_13_16_19_Full.xml Threads Includes threads in the counter set. False"},{"location":"Performance/ExPerfWiz/#set-experfwiz","title":"Set-ExPerfWiz
","text":"Modifies the configuration of an existing data collector set.
Switch Description Default Duration How long should the performance data be collected 08:00:00 Interval How often the performance data should be collected. 5s MaxSize Maximum size of the perfmon log in MegaBytes (256-4096) 1024Mb Name The name of the data collector set Exchange_PerfWiz Server Name of the server where the perfmon collector should be created Local Machine StartTime Daily time to start perfmon counter NA Quiet Suppress output False"},{"location":"Performance/ExPerfWiz/#remove-experfwiz","title":"Remove-ExPerfWiz
","text":"Removes an ExPerfWiz data collector set
Switch Description Default Name Name of the Perfmon Collector set Exchange_PerfWiz Server Name of the server to remove the collector set from Local Machine"},{"location":"Performance/ExPerfWiz/#start-experfwiz","title":"Start-ExPerfWiz
","text":"Starts an ExPerfWiz data collector set
Switch Description Default Name The Name of the Data Collector set to start Exchange_PerfWiz Server Name of the remote server to start the data collector set on. Local Machine"},{"location":"Performance/ExPerfWiz/#stop-experfwiz","title":"Stop-ExPerfWiz
","text":"Stops an ExPerfWiz data collector set
Switch Description Default Name Name of the data collector set to stop. Exchange_PerfWiz Server Name of the server to stop the collector set on. Local Machine"},{"location":"Performance/ExPerfWiz/#example-usage","title":"Example Usage","text":""},{"location":"Performance/ExPerfWiz/#default-usage-for-data-gathering","title":"Default usage for data gathering","text":"New-ExPerfWiz -FolderPath C:\\ExPerfWiz -StartOnCreate
Stop-ExPerfWiz
New-ExPerfWiz -FolderPath C:\\ExPerfWiz -server RemoteExchServer
Get-ExchangeServer | Foreach {New-ExPerfWiz -FolderPath C:\\ExPerfWiz -StartOnCreate -Server $_.name}
Download the latest release: SimplePerf.ps1
This script is a stripped-down and streamlined performance log collector for Exchange Server.
"},{"location":"Performance/SimplePerf/#common-examples","title":"Common Examples","text":".\\SimplePerf.ps1 -Start\n
Starts a collector using Exchange counter defaults. The collector is non-circular, will run for 8 hours, has a 5-second interval, has a max file size of 1 GB, and saves the logs to C:\\SimplePerf. .\\SimplePerf.ps1 -Start -IncludeCounters \"\\Thread\"\n
Starts a collector using Exchange counter defaults plus all \\Thread counters. The collector is non-circular, will run for 8 hours, has a 5-second interval, has a max file size of 1 GB, and saves the logs to C:\\SimplePerf. .\\SimplePerf.ps1 -Start -Duration 02:00:00 -Interval 30 -MaximumSizeInMB 512 -OutputFolder C:\\PerfLogs\n
Starts a collector using Exchange counter defaults. The collector is non-circular, will run for 2 hours, has a 30-second interval, has a max file size of 512 MB, and saves the logs to C:\\PerfLogs. .\\SimplePerf.ps1 -Start -Duration 02:00:00 -Interval 30 -MaximumSizeInMB 1024 -Circular -OutputFolder C:\\PerfLogs\n
Starts a collector using Exchange counter defaults. The collector is circular, will run for 2 hours, has a 30-second interval, has a max file size of 1024 MB, and saves the logs to C:\\PerfLogs. .\\SimplePerf.ps1 -Stop\n
Stops a running SimplePerf. Get-ExchangeServer | .\\SimplePerf.ps1 -Start\n
Starts a SimplePerf with the default options on all Exchange servers. \"SRV1\", \"SRV2\", \"SRV3\" | .\\SimplePerf.ps1 -Start\n
Starts a SimplePerf with the default options on the three named servers. \"SRV1\", \"SRV2\", \"SRV3\" | .\\SimplePerf.ps1 -Stop\n
Stops a running SimplePerf on the three named servers."},{"location":"Performance/SimplePerf/#using-named-collectors","title":"Using Named Collectors","text":"It is possible to run several SimplePerf collectors on the same computer at the same time by providing the -CollectorName parameter. For example:
.\\SimplePerf -Start -Interval 60 -CollectorName \"Minute\"\n.\\SimplePerf -Start -Interval 5 -CollectorName \"FiveSeconds\"\n
When using collector names, the same name must be provided to the -Stop command:
.\\SimplePerf -Stop -CollectorName \"Minute\"\n.\\SimplePerf -Stop -CollectorName \"FiveSeconds\"\n
"},{"location":"Performance/SimplePerf/#counter-name-filters","title":"Counter Name Filters","text":"The counters collected by SimplePerf can be controlled with a combination of three parameters: -Scenario, -IncludeCounters, and -ExcludeCounters.
Currently, there are only two scenarios: Exchange and None. The Exchange scenario is a common set of counters for Exchange Server, similar to what ExPerfWiz would collect. None is a completely empty counter set.
-IncludeCounters and -ExcludeCounters perform a StartsWith match against the counter name. This makes it possible to collect a large number of counters with minimal syntax. For example:
.\\SimplePerf.ps1 -Start -IncludeCounters \"\\MSExchange\", \"\\Microsoft Exchange\"\n
This example starts a SimplePerf using the Exchange scenario, but then it includes every counter starting with either MSExchange or Microsoft Exchange. .\\SimplePerf.ps1 -Start -IncludeCounters \"\\MSExchange\", \"\\Microsoft Exchange\" -Scenario \"None\"\n
This example starts a SimplePerf collecting all the matching Exchange counters without including any default counters at all, because the None scenario was specified. .\\SimplePerf.ps1 -Start -ExcludeCounters \"\\MSExchange Transport\"\n
In this example, we use the Exchange scenario as a starting point, but then we remove all counters starting with MSExchange Transport. Note that individual counters can be excluded even if the counter set has been included. To illustrate:
In this screenshot we see all the counters that exist for the Thread set.
If we tell SimplePerf to include \"\\Thread\", then it simply collects the whole object.
However, if we tell it to Include \"\\Thread\" but exclude \"\\Thread(*)\\Priority\", we see that it has correctly expanded the Thread object and is collecting all counters except \"Priority Current\" and \"Priority Base\".
This filtering mechanism makes it easy to customize the counter set with minimal text. To check the result of your counter filters, add the -Verbose switch, or check the counters txt file in $env:TEMP.
Note that the resulting set can only show counters that exist on the local machine. For instance, you won't see any Exchange counters in the Verbose output if the script is not running on an Exchange Server.
"},{"location":"Performance/SimplePerf/#language-support","title":"Language Support","text":"SimplePerf works regardless of the current language. It does this by translating the provided counter filters to whatever the current server language happens to be. This means that counter names must always be provided in English, even when the current language is not English.
For example, here is the same command from the earlier example running on a server where Spanish is the current language:
"},{"location":"PublicFolders/SourceSideValidations/","title":"SourceSideValidations","text":"Download the latest release: SourceSideValidations.ps1
This script performs pre-migration public folder checks for Exchange 2013, 2016, and 2019. For Exchange 2010, please use previous script found here.
"},{"location":"PublicFolders/SourceSideValidations/#syntax","title":"Syntax","text":"SourceSideValidations.ps1\n [-StartFresh <bool>]\n [-SlowTraversal]\n [-ResultsFile <string>]\n [-SkipVersionCheck]\n [-Tests <string[]>]\n [<CommonParameters>]\nSourceSideValidations.ps1 -RemoveInvalidPermissions\n [-ResultsFile <string>]\n [-SkipVersionCheck]\n [<CommonParameters>]\nSourceSideValidations.ps1 -SummarizePreviousResults\n [-ResultsFile <string>]\n [-SkipVersionCheck]\n [<CommonParameters>]\n
"},{"location":"PublicFolders/SourceSideValidations/#output","title":"Output","text":"The script will generate the following files. Usually the only one we care about is ValidationResults.csv. The others are purely for saving time on subsequent runs.
File Name Content Use IpmSubtree.csv A subset of properties of all Public Folders Running with -StartFresh $false loads this file instead of retrieving fresh data Statistics.csv EntryID, item count, and size of every folder Running with -StartFresh $false loads this file instead of retrieving fresh data NonIpmSubtree.csv A subset of properties of all System Folders Running with -StartFresh $false loads this file instead of retrieving fresh data ValidationResults.csv Information about any issues found. This is file we want to examine to understand any issues found. The script will display a summary of what it found, and in many cases it will provide an example command that uses input from this file to fix the problem."},{"location":"PublicFolders/SourceSideValidations/#tests","title":"Tests","text":"The script performs the following tests. The ValidationResults.csv can be filtered by ResultType to identify the respective folders.
Test Category ResultType Criteria DumpsterMapping BadDumpsterMapping DumpsterEntryId is null, or the dumpster is not in \\NON_IPM_SUBTREE\\DUMPSTER_ROOT, or the DumpsterEntryId of the dumpster does not point back to the folder. Limit ChildCount The folder has more than 10,000 direct child folders. Limit EmptyFolder The folder and all its child folders (recursive) have no items. Limit FolderPathDepth The folder path is greater than 299 folders deep. Limit HierarchyCount There are more than 250,000 total folders in the hierarchy. Limit HierarchyAndDumpsterCount There are more than 250,000 total folders if you count both the folders and their dumpsters. Limit ItemCount The folder has more than 1,000,000 items. Limit NoStatistics Get-PublicFolderStatistics did not return any statistics for these folders. ItemCount, TotalItemSize, and EmptyFolder tests were skipped. Limit TotalItemSize The items directly in this folder (not child folders) add up to more than 25 GB. MailEnabledFolder MailDisabledWithProxyGuid The folder is not mail-enabled, but it has the GUID of an Active Directory object in its MailRecipientGuid property. MailEnabledFolder MailEnabledSystemFolder The folder is a system folder, which should not be mail-enabled. MailEnabledFolder MailEnabledWithNoADObject The folder is mail-enabled, but it has no Active Directory object. MailEnabledFolder OrphanedMPF An Active Directory object exists, but it is not linked to any folder. MailEnabledFolder OrphanedMPFDuplicate An Active Directory object exists, but it points to a public folder which points to a different object. MailEnabledFolder OrphanedMPFDisconnected An Active Directory object exists, but it points to a public folder that is mail-disabled. FolderName SpecialCharacters Folder name contains @, /, or \\. Permission BadPermission The permission does not refer to a valid entity."},{"location":"PublicFolders/SourceSideValidations/#usage","title":"Usage","text":"Typically, the script should be run with no parameters:
.\\SourceSideValidations.ps1\n
Progress indicators are displayed as it collects data and validates the results.
The final test, which checks permissions, will usually take much longer than the other tests.
When all the tests are done, the script provides a summary of what it found, along with example commands that fix some issues.
In this example output, the script calls out four issues.
First, it points out that we have 111,124 folders that are completely empty (this is a lab). Note the ResultType of EmptyFolder. If we want to see the list of empty folders, we can open up ValidationResults.csv in Excel, filter for a ResultType of EmptyFolder, and then we see all those results:
For these folders, no action is required. The script is just giving us information.
The next thing it calls out is that 4 folders have problematic characters in the name. The output tells us these have a ResultType of SpecialCharacters. Filtering for that in the CSV, we see the folders.
Fortunately, the script gives us a command we can run to fix all the names. We can copy and paste the command it gave us, let it run, and then spot check the result.
Now that the names are fixed, we move on to the next item.
The script tells us we have a mail public folder object for a public folder that is mail-disabled. For this type of problem, we need to examine the folder and figure out what we want to do. The CSV file gives us the DN of the mail object and the entry ID of the folder, which we can use to examine the two objects.
The folder says MailEnabled is False, yet we have a MailPublicFolder which points to it. We need to decide whether we want the folder to receive email or not. For this lab, I decide I do want the folder to be mail-enabled, so I remove the orphaned MailPublicFolder and then mail-enable the folder.
I also confirm the new object has the same email address as the old one. This might need to be adjusted manually in some cases, but here I didn't have to.
Finally, the script says we have 9,850 invalid permissions. Fortunately, this is another one that is easy to fix, as the script provides a command.
This one is going to take a while. Once completed, we can rerun SourceSideValidations to make sure all the issues are resolved.
If you close the shell and you need to see the summary results again, use the -SummarizePreviousResults switch.
.\\SourceSideValidations -SummarizePreviousResults\n
The script reads the output file and repeats the instructions on what to do. You can also summarize the results from previous runs, or point to files in other locations, by providing the -ResultsFile parameter.
"},{"location":"PublicFolders/ValidateEXOPFDumpster/","title":"ValidateExoPfDumpster","text":"Download the latest release: ValidateExoPfDumpster.ps1
This script investigates public folders/items deletion operations failures & propose FIXes for mitigation. The script is working to validate the below conditions over the affected public folder
"},{"location":"PublicFolders/ValidateEXOPFDumpster/#checks-run","title":"Checks run:","text":"ValidateExoPfDumpster.ps1\n [-PFolder <string[]>]\n [-AffectedUser <string[]>]\n [-ExportPath <string[]>]\n
"},{"location":"PublicFolders/ValidateEXOPFDumpster/#output","title":"Output","text":"The script will generate the public folder validation checks failures & proposed Fixes results on screen and will generate same results on ValidatePFDumpsterREPORT.txt file as well. There are other files generated for either script logging purposes or sometimes for logs to be shared with Microsoft personnel in case issues encountered requires microsoft support team intervention.
File Name Content Use ValidatePFDumpsterREPORT.txt Information about any blockers found The script will display what it found, and in many cases it will provide a mitigation to fix the problem ValidatePFDumpsterChecksLogging.csv Information about the reason of script failure to run The file will display errors encountered on running the script and at which stage PublicFolderInfo.xml All required information about the affected public folder This log file to be shared with Microsoft personnel"},{"location":"PublicFolders/ValidateEXOPFDumpster/#usage","title":"Usage","text":"Typically, the script should run with PFolder identity parameter as illustrated below:
.\\ValidateExoPfDumpster.ps1 -PFolder \\pf1\n
The script will prompt for affected public folder identity/EntryID if it wasn't provided using PFolder parameter then it will prompt for global administrator username & password to connect to EXO by default it validates if the issue is specific to the Public folder \"e.g. all users are affected\"
If the issue happens only with a specific user on that case an affected user smtp address is required to be provided
In this example output, the script calls out two blockers.
It points out the below blockers: - Neither user nor Default user have sufficient permissions to delete items inside the public folder - Public folder size has exceeded Individual Public Folder ProhibitPostQuota value
In this example output, the script calls out four blockers.
It points out the below issues: - Public folder & its dumpster doesn't have the same content public folder mailbox - Public folder EntryId & DumpsterEntryID values are not mapped properly - Public folder size has exceeded Organization DefaultPublicFolderProhibitPostQuota value - Public folder dumpster has 1 subfolder
The script created a log file containing all the required information \"PublicFolderInfo.xml\" to be shared with Microsoft personnel for the first two blockers & provided mitigation for the last two blockers and you can see same results under ValidatePFDumpsterREPORT.txt file.
"},{"location":"PublicFolders/ValidateMailEnabledPublicFolders/","title":"ValidateMailEnabledPublicFolders","text":"
Download the latest release: ValidateMailEnabledPublicFolders.ps1
This script performs pre-migration checks on mail-enabled folders on Exchange 2010 and up. Note that these checks are also included in the new SourceSideValidations.ps1 for 2013 and up.
"},{"location":"Retention/Get-MRMDetails/","title":"Get-MRMDetails","text":"Download the latest release: Get-MRMDetails.ps1
This script will gather the MRM configuration for a given user. It will collect the current MRM Policy and Tags for the Exchange Organization, the current MRM Policy and Tags applied to the user, the current Exchange Diagnostics Logs for the user, and Exchange Audit logs for the mailbox selected. The resulting data will allow you to see what tags are applied to the user and when the Managed Folder Assistant has run against the user. It also will grab the Admin Audit log so that we can tell if the Tags or Polices have been modified and who modified them.
To run the script, at minimum you will need a valid SMTP Address for a user. Then you can review the associated logs that are generated from the script.
Syntax:
.\\Get-MRMDetails.ps1 -Mailbox <user>\n
Example to collect the MRM Details from rob@contoso.com:
.\\Get-MRMDetails.ps1 -Mailbox rob@contoso.com\n
"},{"location":"Search/Troubleshoot-ModernSearch/","title":"Troubleshoot-ModernSearch","text":"Download the latest release: Troubleshoot-ModernSearch.ps1
This script is still in development. However, this should be able to quickly determine if an item is indexed or not and why it isn't indexed. Just provide the full message subject and the mailbox identity and it will dump out the information needed to determine if the message is indexed or not.
"},{"location":"Search/Troubleshoot-ModernSearch/#parameters","title":"Parameters","text":"Parameter Description MailboxIdentity Provide the identity of the mailbox that you wish to be looking at. If you are able to find it viaGet-Mailbox
it is able to be used here. ItemSubject Provide the message's subject name. Must be exact if -MatchSubjectSubstring
isn't used. This includes if there is a trailing space at the end of the message subject. MatchSubjectSubstring Enable to perform a like
search in the mailbox with the value that is passed with -ItemSubject
. FolderName If you want to scope the search to a folder for better and faster results, include the name of the folder that the message is in. DocumentId If you already know the document ID number for the mailbox, provide this. This can not be use with -ItemSubject
parameter. Category Provides a breakdown of the messages in the mailbox for that index category state. Possible options are: All
, Indexed
, PartiallyIndexed
, NotIndexed
, Corrupted
, Stale
, and ShouldNotBeIndexed
. NOTE: Depending the item count, this can take a long while to complete. GroupMessages To group the messages by Indexing Error Message and Permanent failure state or not. By Disabling this, you get more properties displayed of the message as well. Server Provide a list of possible servers that you wish to get mailbox statistics for all the active databases on that server. SortByProperty Provide the property that you wish to have the information sorted by in the output to screen. Default is to sort by FullyIndexPercentage
ExcludeFullyIndexedMailboxes When look at the multiple mailbox statistics, we don't want to view the mailboxes that are fully indexed without any indexing problems. QueryString Include a string that you are using to try to find this item, we will run an instant query against it to see if we can find it. IsArchive Enable if you want to look at the archive mailbox. IsPublicFolder Enable if you want to look at a public folder mailbox."},{"location":"Search/Troubleshoot-ModernSearch/#examples","title":"Examples","text":"This is an example of how to run a basic query again a single item.
.\\Troubleshoot-ModernSearch.ps1 -MailboxIdentity han@solo.com -ItemSubject \"Test Message\"\n
This is an example of how to run the script when you want to query multiple items with a similar subject name.
.\\Troubleshoot-ModernSearch.ps1 -MailboxIdentity \"Zelda01\" -ItemSubject \"Initial Indexing\" -MatchSubjectSubstring\n
This is an example of how to run the script against an Archive Mailbox.
.\\Troubleshoot-ModernSearch.ps1 -MailboxIdentity han@solo.com -ItemSubject \"Test Message\" -IsArchive\n
This is an example of how to run the script against a Public Folder Mailbox
.\\Troubleshoot-ModernSearch.ps1 -MailboxIdentity PFMailbox2 -ItemSubject \"My Item Test\" -IsPublicFolder\n
This is an example of how to run the script to get all the index state categories
.\\Troubleshoot-ModernSearch.ps1 -MailboxIdentity \"Zelda02\" -Category \"All\"\n
This is an example of how to run the script to get all the non indexed items
.\\Troubleshoot-ModernSearch.ps1 -MailboxIdentity \"Zelda02\" -Category \"NotIndexed\"\n
This is an example of how to run the script to get all the active mailboxes on a server
.\\Troubleshoot-ModernSearch.ps1 -Server \"Solo-E19A\"\n
"},{"location":"Security/CVE-2023-21709/","title":"CVE-2023-21709","text":"Download the latest release: CVE-2023-21709.ps1
Note
Microsoft has released the Windows Server October 2023 security update to address the TokenCacheModule vulnerability. While the script can still be used to mitigate the vulnerability, the recommended solution is to install the Windows Server October 2023 (or later) security update instead. The update and more information can be found here: CVE-2023-36434
The CVE-2023-21709.ps1
script can be used to mitigate the CVE-2023-21709
and CVE-2023-36434
vulnerability by removing the TokenCacheModule
from IIS. It can also be used to restore a previously removed TokenCacheModule
.
Note
The script doesn't perform any check if the Windows Server October 2023 (or later) security update has been installed before restoring the TokenCacheModule. Make sure to install the update before restoring the module.
The script allows you to explicitly specify a subset of Exchange servers on which the TokenCacheModule
should be removed or restored. It's also possible to exclude a subset of Exchange servers from the operation performed by the script.
This script must be run as Administrator in Exchange Management Shell (EMS)
. The user must be a member of the Organization Management
role group.
This syntax removes the TokenCacheModule
from all Exchange servers within the organization.
.\\CVE-2023-21709.ps1\n
This syntax removes the TokenCacheModule
from ExchangeSrv01
and ExchangeSrv02
.
.\\CVE-2023-21709.ps1 -ExchangeServerNames ExchangeSrv01, ExchangeSrv02\n
This syntax removes the TokenCacheModule
from all Exchange servers within the organization except ExchangeSrv02
.
.\\CVE-2023-21709.ps1 -SkipExchangeServerNames ExchangeSrv02\n
This syntax restores the TokenCacheModule
on all Exchange servers within the organization.
.\\CVE-2023-21709.ps1 -Rollback\n
"},{"location":"Security/CVE-2023-21709/#parameters","title":"Parameters","text":"Parameter Description ExchangeServerNames A list of Exchange servers that you want to run the script against. This can be used for applying or rollback the CVE-2023-21709
configuration change. SkipExchangeServerNames A list of Exchange servers that you don't want to execute the TokenCacheModule
configuration action. Rollback Switch parameter to rollback the CVE-2023-21709
configuration change and add the TokenCacheModule
back to IIS. ScriptUpdateOnly Switch parameter to only update the script without performing any other actions. SkipVersionCheck Switch parameter to skip the automatic version check and script update."},{"location":"Security/EOMT/","title":"Exchange On-premises Mitigation Tool (EOMT)","text":"Download the latest release: EOMT.ps1
This script contains mitigations to help address the following vulnerabilities.
This is the most effective way to help quickly protect and mitigate your Exchange Servers prior to patching. We recommend this script over the previous ExchangeMitigations.ps1 script. The Exchange On-premises Mitigation Tool automatically downloads any dependencies and runs the Microsoft Safety Scanner. This a better approach for Exchange deployments with Internet access and for those who want an attempt at automated remediation. We have not observed any impact to Exchange Server functionality via these mitigation methods. EOMT.ps1 is completely automated and uses familiar mitigation methods previously documented. This script has four operations it performs:
This a better approach for Exchange deployments with Internet access and for those who want an attempt at automated remediation. We have not observed any impact to Exchange Server functionality via these mitigation methods nor do these mitigation methods make any direct changes that disable features of Exchange.
Use of the Exchange On-premises Mitigation Tool and the Microsoft Safety Scanner are subject to the terms of the Microsoft Privacy Statement: https://aka.ms/privacy
"},{"location":"Security/EOMT/#requirements-to-run-the-exchange-on-premises-mitigation-tool","title":"Requirements to run the Exchange On-premises Mitigation Tool","text":"The Exchange On-premises Mitigation Tool runs the Microsoft Safety Scanner in a quick scan mode. If you suspect any compromise, we highly recommend you run it in the FULL SCAN mode. FULL SCAN mode can take a long time but if you are not running Microsoft Defender AV as your default AV, FULL SCAN will be required to remediate threats.
"},{"location":"Security/EOMT/#exchange-on-premises-mitigation-tool-examples","title":"Exchange On-premises Mitigation Tool Examples","text":"The default recommended way of using EOMT.ps1. This will determine if your server is vulnerable, mitigate if vulnerable, and run MSERT in quick scan mode. If the server is not vulnerable only MSERT quick scan will run.
.\\EOMT.ps1
To run a Full MSERT Scan - We only recommend this option only if the initial quick scan discovered threats. The full scan may take hours or days to complete.
.\\EOMT.ps1 -RunFullScan -DoNotRunMitigation
To run the Exchange On-premises Mitigation Tool with MSERT in detect only mode - MSERT will not remediate detected threats.
.\\EOMT.ps1 -DoNotRemediate
To roll back the Exchange On-premises Mitigation Tool mitigations
.\\EOMT.ps1 -RollbackMitigation
Note: If ExchangeMitigations.ps1 was used previously to apply mitigations, Use ExchangeMitigations.ps1 for rollback.
+NEW EOMT will now AutoUpdate by downloading the latest version from GitHub. To prevent EOMT from fetching updates to EOMT.ps1 from the internet.
.\\EOMT.ps1 -DoNotAutoUpdateEOMT
Question: What mode should I run EOMT.ps1 in by default?
Answer: By default, EOMT.ps1 should be run without any parameters:
This will run the default mode which does the following: 1. Checks if your server is vulnerable based on the presence of the SU patch or Exchange version. 2. Downloads and installs the IIS URL rewrite tool (only if vulnerable). 3. Applies the URL rewrite mitigation (only if vulnerable). 4. Runs the Microsoft Safety Scanner in \"Quick Scan\" mode (vulnerable or not).
Question: What if I run a full scan and it's affecting the resources of my servers?
Answer: You can terminate the process of the scan by running the following command in an Administrative PowerShell session.
Stop-Process -Name msert
Question: What is the real difference between this script (EOMT.PS1) and the previous script Microsoft released (ExchangeMitigations.Ps1).
Answer: The Exchange On-premises Mitigation Tool was released to help pull together multiple mitigation and response steps, whereas the previous script simply enabled mitigations. Some details on what each do:
"},{"location":"Security/EOMT/#eomtps1","title":"EOMT.PS1","text":"Question: What if I do not have an external internet connection from my Exchange server?
Answer: If you do not have an external internet connection, you can still use the legacy script (ExchangeMitigations.ps1) and other steps from the mitigation blog post: Microsoft Exchange Server Vulnerabilities Mitigations \u2013 March 2021
Question: If I have already ran the mitigations previously, will the Exchange On-premises Mitigation Tool roll back any of the mitigations?
Answer: No, please use the legacy script (ExchangeMitigations.ps1) to do rollback. The legacy script supports rollback for the mitigations the Exchange On-premises Mitigation Tool applied.
"},{"location":"Security/EOMTv2/","title":"Exchange On-premises Mitigation Tool v2 (EOMTv2)","text":"Please read carefully
The vulnerability addressed by this mitigation script has been addressed in latest Exchange Server Security Updates (starting with November 2022 SU). Mitigations can become insufficient to protect against all variations of an attack. Thus, installation of an applicable SU is the only way to protect your servers. Once you install the updates, you can rollback the mitigation as described in the Exchange On-premises Mitigation Tool v2 Examples section.
Download the latest release: EOMTv2.ps1
The Exchange On-premises Mitigation Tool v2 script (EOMTv2.ps1) can be used to mitigate CVE-2022-41040. This script does the following:
Use of the Exchange On-premises Mitigation Tool v2 is subject to the terms of the Microsoft Privacy Statement: https://aka.ms/privacy
"},{"location":"Security/EOMTv2/#requirements-to-run-the-exchange-on-premises-mitigation-tool-v2","title":"Requirements to run the Exchange On-premises Mitigation Tool v2","text":"NOTE: The script has to be executed individually for each server.
"},{"location":"Security/EOMTv2/#exchange-on-premises-mitigation-tool-v2-examples","title":"Exchange On-premises Mitigation Tool v2 Examples","text":"The default recommended way of using EOMTv2.ps1. This will apply the URL rewrite mitigation. If IIS URL rewrite module is not installed, this will also download and install the module.
.\\EOMTv2.ps1\n
To roll back EOMTv2 mitigations run
.\\EOMTv2.ps1 -RollbackMitigation\n
"},{"location":"Security/ExchangeExtendedProtectionManagement/","title":"ExchangeExtendedProtectionManagement","text":"Download the latest release: ExchangeExtendedProtectionManagement.ps1
The Exchange Extended Protection Management is a script to help automate the Extended Protection feature on the Windows Authentication Module on Exchange Servers. Prior to configuration, it validates that all servers that we are trying to enable Extended Protection on and the servers that already have Extended Protection enabled have the same TLS settings and other prerequisites that are required for Extended Protection to be enabled successfully.
"},{"location":"Security/ExchangeExtendedProtectionManagement/#requirements","title":"Requirements","text":"The user must be in Organization Management
and must run this script from an elevated Exchange Management Shell (EMS) command prompt.
This syntax enables Extended Protection on all Exchange Servers that are online that we can reach.
PS C:\\> .\\ExchangeExtendedProtectionManagement.ps1\n
This syntax enables Extended Protection on only the Exchange Servers specified in the -ExchangeServerNames parameter. However, TLS checks will still occur against all servers, and the script will confirm that the TLS settings are correct on all servers with Extended Protection enabled and all servers specified in the -ExchangeServerNames parameter.
PS C:\\> .\\ExchangeExtendedProtectionManagement.ps1 -ExchangeServerNames <Array_of_Server_Names>\n
This syntax enables Extended Protection on all Exchange Servers that are online that we can reach, excluding any servers specified in the -SkipExchangeServerNames parameter. As above, TLS checks will still occur against all servers, and the script will confirm that the TLS settings are correct on all servers with Extended Protection enabled and all servers being enabled.
PS C:\\> .\\ExchangeExtendedProtectionManagement.ps1 -SkipExchangeServerNames <Array_of_Server_Names>\n
This syntax collects the possible IP addresses to be used for the IP restriction for a virtual directory. Plus the location to store the file.
NOTE: This is only to assist you with the IP collections. You must verify the list to make sure it is accurate and contains all the required IP addresses.
PS C:\\> .\\ExchangeExtendedProtectionManagement.ps1 -FindExchangeServerIPAddresses -OutputFilePath \"C:\\temp\\ExchangeIPs.txt\"\n
This syntax will enable Extended Protection for all virtual directories and set EWS Backend virtual directory to None and then proceed to set IP restriction for the EWS Backend virtual directory for all servers online, while providing the IP address list.
PS C:\\> .\\ExchangeExtendedProtectionManagement.ps1 -RestrictType \"EWSBackend\" -IPRangeFilePath \"C:\\temp\\ExchangeIPs.txt\"\n
This syntax will verify the IP restrictions for the EWS Backend virtual directory.
PS C:\\> .\\ExchangeExtendedProtectionManagement.ps1 -ValidateType \"RestrictTypeEWSBackend\" -IPRangeFilePath \"C:\\temp\\ExchangeIPs.txt\"\n
This syntax rolls back the Extended Protection configuration for all the Exchange Servers that are online where Extended Protection was previously configured.
NOTE: This is done by restoring the applicationHost.config file back to the previous state before Extended Protection was configured. If other changes occurred after this configuration, those changes will be lost.
PS C:\\> .\\ExchangeExtendedProtectionManagement.ps1 -RollbackType \"RestoreIISAppConfig\"\n
This syntax rolls back the Extended Protection mitigation of IP restriction for the EWS Backend virtual directory of all the Exchange Server that are online where Extended Protection was previously configured.
PS C:\\> .\\ExchangeExtendedProtectionManagement.ps1 -RollbackType \"RestrictTypeEWSBackend\"\n
This syntax displays the current Extended Protection configuration for all the Exchange Servers that are online.
PS C:\\> .\\ExchangeExtendedProtectionManagement.ps1 -ShowExtendedProtection\n
"},{"location":"Security/ExchangeExtendedProtectionManagement/#parameters","title":"Parameters","text":"Parameter Description ExchangeServerNames A list of servers to pass that you want to run the script against. This can be used for configuration or rollback. SkipExchangeServerNames A list of server to pass that you don't want to execute the script for configuration or rollback. ShowExtendedProtection Show the current configuration of Extended Protection for the passed server list. FindExchangeServerIPAddresses Use this to collect a list of the Exchange Server IPs that should be used for IP Restriction. OutputFilePath Is a custom file path to be used to export the list of Exchange Server IPs collected from FindExchangeServerIPAddresses
. Default value is the local location IPList.txt
. IPRangeFilePath Is the path to the file that contains all the IP Addresses or subnets that are needed to be in the IP Allow list for Mitigation. RestrictType To enable a IP Restriction on a virtual directory. Must be used with IPRangeFilePath
. The following values are allowed: EWSBackend
ValidateType To verify if the IP Restrictions have been applied correctly. Must be used with IPRangeFilePath
. The following values are allowed: RestrictTypeEWSBackend
RollbackType Using this parameter will allow you to rollback using the type you specified. The following values are allowed: RestoreIISAppConfig
, RestrictTypeEWSBackend
SkipAutoUpdate Skips over the Auto Update feature to download the latest version of the script."},{"location":"Security/ExchangeMitigations/","title":"ExchangeMitigations","text":"Download the latest release: ExchangeMitigations.ps1
This script contains 4 mitigations to help address the following vulnerabilities:
For more information on each mitigation please visit https://aka.ms/exchangevulns
This should only be used as a temporary mitigation until your Exchange Servers can be fully patched, recommended guidance is to apply all of the mitigations at once.
For this script to work you must have the IIS URL Rewrite Module installed which can be done via this script using the -FullPathToMSI parameter.
For IIS 10 and higher URL Rewrite Module 2.1 must be installed, you can download version 2.1 here:
For IIS 8.5 and lower Rewrite Module 2.0 must be installed, you can download version 2.0 here:
x86 - https://www.microsoft.com/en-us/download/details.aspx?id=5747
x64 - https://www.microsoft.com/en-us/download/details.aspx?id=7435
Installing URL Rewrite version 2.1 on IIS versions 8.5 and lower may cause IIS and Exchange to become unstable. If there is a mismatch between the URL Rewrite module and IIS version, ExchangeMitigations.ps1 will not apply the mitigation for CVE-2021-26855. You must uninstall the URL Rewrite module and reinstall the correct version.
Script requires PowerShell 3.0 and later and must be executed from an elevated PowerShell Session.
Download the latest release here:
Download ExchangeMitigations.ps1
To apply all mitigations with MSI install
.\\ExchangeMitigations.ps1 -FullPathToMSI \"FullPathToMSI\" -WebSiteNames \"Default Web Site\" -ApplyAllMitigations
To apply all mitigations without MSI install
.\\ExchangeMitigations.ps1 -WebSiteNames \"Default Web Site\" -ApplyAllMitigations -Verbose
To rollback all mitigations
.\\ExchangeMitigations.ps1 -WebSiteNames \"Default Web Site\" -RollbackAllMitigation
To apply multiple or specific mitigations (out of the 4)
.\\ExchangeMitigations.ps1 -WebSiteNames \"Default Web Site\" -ApplyECPAppPoolMitigation -ApplyOABAppPoolMitigation
To rollback multiple or specific mitigations
.\\ExchangeMitigations.ps1 -WebSiteNames \"Default Web Site\" -RollbackECPAppPoolMitigation -RollbackOABAppPoolMitigation
Documentation Moved
This documentation has been moved to Microsoft Learn. Please read Configure Windows Extended Protection in Exchange Server for more information.
"},{"location":"Security/Test-CVE-2021-34470/","title":"Test-CVE-2021-34470","text":"Download the latest release: Test-CVE-2021-34470.ps1
Environments running supported versions of Exchange Server should address CVE-2021-34470 by applying the CU and/or SU for the respective versions of Exchange, as described in Released: July 2021 Exchange Server Security Updates.
Environments where the latest version of Exchange Server is any version before Exchange 2013, or environments where all Exchange servers have been removed, can use this script to address the vulnerability.
"},{"location":"Security/Test-CVE-2021-34470/#examples","title":"Examples","text":"Check for the vulnerability:
.\\Test-CVE-2021-34470.ps1
Fix the vulnerability if found:
.\\Test-CVE-2021-34470.ps1 -ApplyFix
Note that the user must be a Schema Admin to use the -ApplyFix switch.
"},{"location":"Security/Test-ProxyLogon/","title":"Test-ProxyLogon.ps1","text":"Download the latest release: Test-ProxyLogon.ps1
Formerly known as Test-Hafnium, this script automates all four of the commands found in the Hafnium blog post. It also has a progress bar and some performance tweaks to make the CVE-2021-26855 test run much faster.
"},{"location":"Security/Test-ProxyLogon/#usage","title":"Usage","text":"The most typical usage of this script is to check all Exchange servers and save the reports, by using the following syntax from Exchange Management Shell:
Get-ExchangeServer | .\\Test-ProxyLogon.ps1 -OutPath $home\\desktop\\logs
To check the local server only, just run the script:
.\\Test-ProxyLogon.ps1 -OutPath $home\\desktop\\logs
To check the local server and copy the identified logs and files to the OutPath:
.\\Test-ProxyLogon.ps1 -OutPath $home\\desktop\\logs -CollectFiles
To display the results without saving them, pass -DisplayOnly:
.\\Test-ProxyLogon.ps1 -DisplayOnly
The script says it found suspicious files, and it lists a bunch of zip files. What does this mean?
The script will flag any zip/7x/rar files that it finds in ProgramData. As noted in this blog post, web shells have been observed using such files for exfiltration. An administrator should review the files to determine if they are valid. Determining if a zip file is a valid part of an installed product is outside the scope of this script, and whitelisting files by name would only encourage the use of those specific names by attackers.
I'm having trouble running the script on Exchange 2010.
If PowerShell 3 is present, the script can be run on Exchange 2010. It will not run-on PowerShell 2. One can also enable PS Remoting and run the script remotely against Exchange 2010. However, the script has minimal functionality in these scenarios, as Exchange 2010 is only affected by one of the four announced exploits - CVE-2021-26857. Further, this exploit is only available if the Unified Messaging role is present. As a result, it is often easier to simply run the Get-EventLog command from the blog post, rather than using Test-ProxyLogon.
"},{"location":"Security/CVE-2023-23397/","title":"CVE-2023-23397 script","text":"Download the latest release: CVE-2023-23397.ps1
CVE-2023-23397.ps1 is a script that checks Exchange messaging items (mail, calendar and tasks) to see whether a property is populated with a non empty string value. It is up to the admin to determine if the value is malicious or not. If required, admins can use this script to clean up the property for items that are malicious or even delete the items permanently. Please see CVE-2023-23397 for more information.
There are two modes for the script: Audit and Cleanup.
Audit Mode: Script provides a CSV file with details of items that have the property populated.
Cleanup Mode: Script performs cleanup on detected items by either clearing the property or deleting the item.
"},{"location":"Security/CVE-2023-23397/#steps-to-run-the-script","title":"Steps to run the script:","text":"Run the script in audit mode.
For organizations with large number of mailboxes: It is recommended to break up the mailbox list into multiple files, so the script can be run against mailboxes in batches. Here is an example of how to break up the mailboxes into batches of 1000:
$batchSize = 1000; $batchNumber = 1; $count = 0; Get-Mailbox -ResultSize Unlimited | Select PrimarySmtpAddress | % {\n if ($count++ -ge $batchSize) { $batchNumber++; $count = 0; }\n Export-Csv -InputObject $_ -Path \"Batch$batchNumber.csv\" -Append\n}\n\n# Then run against the batches similar to this:\nImport-Csv .\\BatchFileName.csv | .\\CVE-2023-23397.ps1 -Environment Online\n
If the script execution finishes with \"No vulnerable item found\", no further action is required.
To run this script in an on-premises Exchange Server environment, you need to use an account with the ApplicationImpersonation
management role. You can create a new role group with the required permissions by running the following PowerShell command in an elevated Exchange Management Shell (EMS):
New-RoleGroup -Name \"CVE-2023-23397-Script\" -Roles \"ApplicationImpersonation\" -Description \"Permission to run the CVE-2023-23397 script\"\nAdd-RoleGroupMember -Identity \"CVE-2023-23397-Script\" -Member \"<UserWhoRunsTheScript>\"\n
The script uses Exchange Web Services (EWS) to fetch items from user mailboxes. So, the machine on which the script is run should be able to make EWS calls to your Exchange server. You can also create a new Throttling Policy to prevent the user who runs the script from being throttled. Make sure to revert the throttling policy after you're done running the script.
Please note that this is for Exchange on-premises environments only.
New-ThrottlingPolicy \"CVE-2023-23397-Script\"\nSet-ThrottlingPolicy \"CVE-2023-23397-Script\" -EWSMaxConcurrency Unlimited -EWSMaxSubscriptions Unlimited -CPAMaxConcurrency Unlimited -EwsCutoffBalance Unlimited -EwsMaxBurst Unlimited -EwsRechargeRate Unlimited\nSet-Mailbox -Identity \"<UserWhoRunsTheScript>\" -ThrottlingPolicy \"CVE-2023-23397-Script\"\n
"},{"location":"Security/CVE-2023-23397/#prerequisites-to-run-the-script-for-exchange-online","title":"Prerequisites to run the script for Exchange Online","text":"To run this script in an Exchange Online environment, you need to be a Global Administrator
or an Application Administrator
. The script will create an application with full access permission on all the mailboxes.
Furthermore it is possible to use a certificate to run the script in Audit
and Cleanup
mode. This is called Certificate Based Authentication (CBA)
. The steps are outlined in the FAQ section.
NOTE: The script uses Microsoft.Exchange.WebServices.dll to make EWS calls. The script will try to download the DLL and use it. However, if it is unable to, you will need to download the DLL and specify the path.
"},{"location":"Security/CVE-2023-23397/#steps-to-download-microsoftexchangewebservicesdll","title":"Steps to Download Microsoft.Exchange.WebServices.dll:","text":"-DLLPath
parameter when running the script.The script accepts the following parameters:
Parameter Description Environment Specify the environment where you are running the script. This parameter is required. CreateAzureApplication Use this parameter to create an Azure AD application that can be used for running the script in Exchange Online. DeleteAzureApplication Use this parameter to delete the Azure AD application. UserMailboxes Use this parameter to provide a list of user primary SMTP addresses. You can pipe the addresses while running. This parameter is required in Audit mode. StartTimeFilter Use this parameter to provide start time filter. (Format: \"mm/dd/yyyy hh:mm:ss\") EndTimeFilter Use this parameter to provide end time filter. (Format: \"mm/dd/yyyy hh:mm:ss\") CleanupAction Use this parameter to provide type of cleanup action you want to perform (ClearProperty/ClearItem). CleanupInfoFilePath Use this parameter to provide path to the CSV file containing the details of messages to be cleaned up. EWSExchange2013 Use this switch if you are running on Exchange Server 2013 mailboxes. DLLPath Provide the path to Microsoft.Exchange.WebServices.dll. This is an optional parameter. AzureApplicationName Provide the name of the application which the script should create. This is an optional parameter. The default name is CVE-2023-23397Application. CertificateThumbprint Provide the thumbprint of the certificate which was uploaded to the Azure application. The certificate must exist under the 'Cert:\\CurrentUser\\My' path on the machine. It can only be used if the private key exists and is accessible. AppId Provide the ID of the application which was created in Azure and which is required to run the script in audit or cleanup mode. The ID can be found within the Azure application under 'Overview' and is labeled as: 'Application (client) ID'. If you don't specify this parameter but specify theCertificateThumbprint
parameter, the script will ask you to logon to query the required information. Organization Provide the ID of your organization. It can be provided in GUID format or by using your onmicrosoft.com domain. If you don't specify this parameter but specify the CertificateThumbprint
parameter, the script will ask you to logon to query the required information. AzureEnvironment Provide the Azure Environment name. This is an optional parameter. The default value is Global
. MaxCSVLength Provide the maximum number of rows the script should create in the CSV while running in Audit mode. This is an optional parameter. The default is 200,000. EWSServerURL Provide the EWS endpoint. If not provided, the script will make an Autodiscover call to get it. This parameter works only with Exchange Server. ScriptUpdateOnly This optional parameter allows you to only update the script without performing any other actions. SkipVersionCheck This optional parameter allows you to skip the automatic version check and script update. IgnoreCertificateMismatch This optional parameter lets you ignore TLS certificate mismatch errors. Credential This optional parameter lets you pass admin credentials when running on Exchange Server. UseSearchFolders This parameter causes the script to use deep-traversal search folders, significantly improving performance. SearchFolderCleanup This parameter cleans up any search folders left behind by the asynchronous search feature. It must be used together with the UseSearchFolders
parameter. SkipSearchFolderCreation This parameter skips the creation of search folders. It must be used together with the UseSearchFolders
parameter. TimeoutSeconds This optional parameter specifies the timeout on the EWS ExchangeService object. The default is 300 seconds (5 minutes)."},{"location":"Security/CVE-2023-23397/#set-exchange-online-cloud-specific-values","title":"Set Exchange Online Cloud Specific values:","text":"You can use the AzureEnvironment
parameter to specify the cloud against which the script runs. By default, the script will run against the Global (worldwide) service. Supported values are:
Execute the script in audit mode as an admin with the ApplicationImpersonation management role. For scanning on-premises mailboxes, the Environment value should be \"Onprem\" and you should provide the EWS URL of your Exchange server in EWSServerURL property. The script will ask for a login prompt, and the username must be provided.
Note
The username which is passed to the script, must be specified in the UPN format where the domain-part is a domain accepted by the Exchange Server.
Optionally, you can use the Credential flag to provide admin credentials in PSCredential format. Set the EWSServerURL parameter to specify the EWS URL if the Autodiscover call fails.
"},{"location":"Security/CVE-2023-23397/#examples","title":"Examples:","text":"This syntax runs the script to audit all the mailboxes.
PS C:\\> Get-Mailbox -ResultSize Unlimited | .\\CVE-2023-23397.ps1 -Environment Onprem\n
Note: If there are Exchange 2013 servers in the environment with Exchange 2016 or 2019, the script may not be able to open mailboxes on Exchange 2013 and may give the following error:
If the above error appears, run the script with an additional parameter EWSExchange2013, as shown below.
PS C:\\> Get-Mailbox -ResultSize Unlimited | .\\CVE-2023-23397.ps1 -Environment Onprem -EWSExchange2013\n
This syntax runs the script to audit all mailboxes for items that were created during a specific period.
PS C:\\> Get-Mailbox -ResultSize Unlimited | .\\CVE-2023-23397.ps1 -Environment Onprem -StartTimeFilter \"01/01/2023 00:00:00\" -EndTimeFilter \"01/01/2024 00:00:00\"\n
"},{"location":"Security/CVE-2023-23397/#cleanup-mode","title":"Cleanup Mode:","text":"The script provides a list of all the messages containing the problematic property in the mailboxes of users specified in an AuditResult_timestamp.CSV file. Admins should analyze this file and mark (with a \"Y\") messages for which either the property is to be cleaned or the message must be removed.
Step 1 Mark the messages for cleanup by entering \"Y\" instead of \"N\" in the cleanup column of CSV file.
Step 2 Choose either to remove the message or only the problematic property in the next step by specifying CleanupAction as \"ClearItem\" or \"ClearProperty.\" Execute the script as follows to remove the message or property marked with Y in the CSV file.
"},{"location":"Security/CVE-2023-23397/#examples_1","title":"Examples:","text":"This syntax runs the script to clear the problematic property from messages:
PS C:\\> .\\CVE-2023-23397.ps1 -Environment Onprem -CleanupAction ClearProperty -CleanupInfoFilePath <Path to modified CSV>\n
This syntax runs the script to delete messages containing the malicious property
PS C:\\> .\\CVE-2023-23397.ps1 -Environment Onprem -CleanupAction ClearItem -CleanupInfoFilePath <Path to modified CSV>\n
"},{"location":"Security/CVE-2023-23397/#running-against-exchange-online-mailboxes","title":"Running Against Exchange Online Mailboxes","text":"First, execute the script in Audit mode as an admin with Global Administrator
or Application Administrator
role. For scanning online mailboxes, the Environment parameter should be \"Online.\"
While scanning Exchange Online mailboxes, the script needs an Azure AD app that has delegate permissions for all Exchange Online mailboxes. You can create the application using the script. And once the application is no longer required, you can delete the application using the script as well.
"},{"location":"Security/CVE-2023-23397/#managing-azureadapplication","title":"Managing AzureADApplication:","text":""},{"location":"Security/CVE-2023-23397/#examples_2","title":"Examples:","text":"This syntax runs the script to create an Azure application
PS C:\\> .\\CVE-2023-23397.ps1 -CreateAzureApplication\n
This syntax runs the script to delete the Azure application created by the script
PS C:\\> .\\CVE-2023-23397.ps1 -DeleteAzureApplication\n
"},{"location":"Security/CVE-2023-23397/#audit-mode_1","title":"Audit Mode:","text":""},{"location":"Security/CVE-2023-23397/#examples_3","title":"Examples:","text":"This syntax runs the script to Audit all mailboxes in Exchange Online.
NOTE: Connect to EXO with Exchange Online PowerShell session
PS C:\\> Get-EXOMailbox -ResultSize Unlimited | .\\CVE-2023-23397.ps1 -Environment \"Online\"\n
This syntax runs the script to Audit all mailboxes for items that were during a specific period.
PS C:\\> Get-EXOMailbox -ResultSize Unlimited | .\\CVE-2023-23397.ps1 -Environment \"Online\" -StartTimeFilter \"01/01/2023 00:00:00\" -EndTimeFilter \"01/01/2024 00:00:00\"\n
This syntax runs the script to Audit all mailboxes by using a certificate to authenticate and using the improved SearchFolder functionality.
PS C:\\> Get-EXOMailbox -ResultSize Unlimited | .\\CVE-2023-23397.ps1 -Environment Online -CertificateThumbprint <Thumbprint of the certificate> -AppId <Application Id of the 'CVE-2023-23397Application' app> -Organization contoso.onmicrosoft.com -UseSearchFolders\n
"},{"location":"Security/CVE-2023-23397/#cleanup-mode_1","title":"Cleanup Mode:","text":""},{"location":"Security/CVE-2023-23397/#examples_4","title":"Examples:","text":"This syntax runs the script to clear the problematic property from messages.
PS C:\\> .\\CVE-2023-23397.ps1 -Environment \"Online\" -CleanupAction ClearProperty -CleanupInfoFilePath <Path to modified CSV>\n
This syntax runs the script to delete messages containing the problematic property.
PS C:\\> .\\CVE-2023-23397.ps1 -Environment \"Online\" -CleanupAction ClearItem -CleanupInfoFilePath <Path to modified CSV>\n
This syntax runs the script to delete messages containing the problematic property. It uses a certificate to acquire the required tokens.
PS C:\\> .\\CVE-2023-23397.ps1 -Environment \"Online\" -CleanupAction ClearItem -CleanupInfoFilePath <Path to modified CSV> -CertificateThumbprint <Thumbprint of the certificate> -AppId <Application Id of the 'CVE-2023-23397Application' app> -Organization contoso.onmicrosoft.com\n
"},{"location":"Security/CVE-2023-23397/#script-execution-errors-and-troubleshooting","title":"Script execution errors and troubleshooting","text":""},{"location":"Security/CVE-2023-23397/#exchange-server-doesnt-support-the-requested-version","title":"Exchange Server doesn't support the requested version","text":"If there are Exchange 2013 servers in an environment with Exchange 2016 or Exchange 2019, the script may not be able to open mailboxes on Exchange 2013 and may give the following error:
If the above error appears, run the script with the EWSExchange2013 parameter:
PS C:\\> Get-Mailbox -ResultSize Unlimited | .\\CVE-2023-23397.ps1 -Environment Onprem -EWSExchange2013\n
"},{"location":"Security/CVE-2023-23397/#blocked-autodiscover-redirection","title":"Blocked Autodiscover redirection","text":"If Autodiscover fails due to a redirection error and the above error appears, provide the EWS URL using the EWSServerURL parameter.
"},{"location":"Security/CVE-2023-23397/#invalid-client-secret-provided","title":"Invalid client secret provided","text":"While running the script in Exchange Online, you might see the above error intermittently. Re-running the script should resolve the issue. If it occurs frequently, then remove the Azure application you have created using -DeleteAzureApplication parameter and then recreate it using -CreateAzureApplication parameter.
"},{"location":"Security/CVE-2023-23397/#cannot-convert-the-microsoftexchangewebservicesdatawebcredentials","title":"\"Cannot convert the \"Microsoft.Exchange.WebServices.Data.WebCredentials\"","text":"Incorrect link was provided to download Microsoft.Exchange.WebServices.dll originally that is causing this issue. Follow these steps to correct this problem.
lib\\40\\Microsoft.Exchange.WebServices.dll
)You are getting a 401 unauthorized when trying to provide the -EWSServerURL
parameter to the script. The possible causes can be due to bad credentials provided or the URL endpoint is not working correctly. Try to provide the credentials again to start off with. If that doesn't work, does the URL work when using a browser? You should get a result like this:
If you don't get a response looking like this after you are prompted for a username and password, then this could be the problem. Try to see if either the FQDN, https://localhost/ews/exchange.asmx
, or https://127.0.0.1/ews/exchange.asmx
works instead. If one of those do, use that instead for the -EWSServerURL
parameter.
NOTE: Make sure to include -IgnoreCertificateMismatch
if using localhost or 127.0.0.1
This feature changes the way Audit mode works to be dramatically faster in most environments. The original approach searches folders synchronously one by one. When using the new switch, we perform two passes. In the first pass, we create a search folder that searches the whole mailbox. In the second pass, we collect the results. This often reduces the time to run the Audit mode by 80% or more.
To use the new feature, use the same syntax as before, but add -UseSearchFolders. For example:
NOTE: Connect to EXO with Exchange Online PowerShell session
Get-EXOMailbox -ResultSize Unlimited | .\\CVE-2023-23397.ps1 -Environment Online -UseSearchFolders\n
This switch only applies to Audit mode. Cleanup mode has no syntax changes. To take maximum advantage of the search folders, it's best to leave them in place until cleanup is done, so you can repeatedly and quickly search for any new items. After cleanup is completed, the search folders can be removed with:
Get-EXOMailbox -ResultSize Unlimited | .\\CVE-2023-23397.ps1 -Environment Online -UseSearchFolders -SearchFolderCleanup\n
"},{"location":"Security/CVE-2023-23397/FAQ/#what-is-the-relationship-of-exchange-server-march-2023-su-and-outlook-fix-for-cve-2023-23397","title":"What is the relationship of Exchange Server March 2023 SU and Outlook fix for CVE-2023-23397?","text":"Those two updates are completely independent from each other. Exchange SUs address Exchange vulnerabilities and security improvements. We mentioned the Outlook\u00a0CVE-2023-23397 update in the Exchange March SU release to raise the awareness to our customers, as we know most use Outlook for Windows. Exchange March SU does not address CVE-2023-23397, you need to install Outlook update to address this vulnerability in Outlook.
"},{"location":"Security/CVE-2023-23397/FAQ/#does-the-account-running-the-script-need-to-be-part-of-organization-management","title":"Does the account running the script need to be part of Organization Management?","text":"In OnPrem environments, the account running the script only needs the EWS Impersonation role, which is provided by adding that user to the group as described in the docs.
In Online environments, the account running the script in -CreateAzureApplication mode needs Global Admin role in order to create the Azure application used for impersonation.
"},{"location":"Security/CVE-2023-23397/FAQ/#in-onprem-does-the-script-need-to-be-executed-on-the-exchange-server","title":"In OnPrem, does the script need to be executed on the Exchange Server?","text":"No, the script can be executed from a workstation. There are essentially two parts to running the script. First, we have to get a list of mailboxes. Second, we have to run the script against them. These steps do not necessarily need to be performed by the same user or on the same machine.
If we just want to run the script against a few users, the email addresses can be specified manually:
.\\CVE-2023-23397.ps1 -Environment OnPrem -UserMailboxes \"user1@contoso.com\", \"user2@contoso.com\"\n
For a large number of mailboxes, an Exchange Organization Administrator could create a CSV of mailboxes to process using a command like this:
Get-Mailbox -ResultSize Unlimited | Export-Csv .\\Mailboxes.csv\n
Then, the script could be run against the CSV file on a different machine by a different user using a command like this:
Import-Csv .\\Mailboxes.csv | .\\CVE-2023-23397.ps1 -Environment OnPrem\n
The default script execution appears to be limited to processing 1000 mailboxes, how to execute the script for more than 1000 mailboxes? You can use following steps to break up the mailboxes into multiple files, so the script can be run against mailboxes in batches. Here is an example of how to break up the mailboxes into batches of 1000: $batchSize = 1000; $batchNumber = 1; $count = 0; Get-Mailbox -ResultSize Unlimited | Select PrimarySmtpAddress | % {\n if ($count++ -ge $batchSize) { $batchNumber++; $count = 0; }\n Export-Csv -InputObject $_ -Path \"Batch$batchNumber.csv\" -Append\n}\n
"},{"location":"Security/CVE-2023-23397/FAQ/#in-onprem-does-the-credential-parameter-need-to-be-upn-or-domainuser","title":"In OnPrem, does the -Credential parameter need to be UPN or domain\\user?","text":"Either format can be used. However, by default, the script will attempt to use the username to perform Autodiscover. If Autodiscover does not work for your UPN, or if domain\\user is being specified, then Autodiscover can be skipped by providing the -EWSServerUrl parameter.
.\\CVE-2023-23397.ps1 -Environment OnPrem -EWSServerUrl \"https://exch1.contoso.com/EWS/Exchange.asmx\"\n
"},{"location":"Security/CVE-2023-23397/FAQ/#in-onprem-does-the-impersonation-account-need-to-have-a-mailbox","title":"In OnPrem, does the impersonation account need to have a mailbox?","text":"The latest version of the script no longer requires the impersonation account to have a mailbox if running on Exchange 2016 or later. Exchange 2013 still requires that the impersonation user have a mailbox on prem.
"},{"location":"Security/CVE-2023-23397/FAQ/#why-does-my-output-file-contain-entries-with-empty-pidlidreminderfileparameter-column-or-reminderwav-is-this-an-issue","title":"Why does my output file contain entries with empty PidLidReminderFileParameter column or 'reminder.wav'. Is this an issue?","text":"The search query is only determining if the property PidLidReminderFileParameter is set, including empty values is a set property. It is up to the admin to determine if they to take actions against this particular item.
NOTE: Script version 23.03.22.1926 and after only provide results for non-empty string values. So the columns should no longer be empty when running the audit mode.
"},{"location":"Security/CVE-2023-23397/FAQ/#why-does-my-output-file-only-contain-some-of-my-mailboxes-that-we-searched-against","title":"Why does my output file only contain some of my mailboxes that we searched against?","text":"It will only export individual items that contain the PidLidReminderFileParameter properties set. If the mailbox doesn't have any items that contains this property, it will not be exported out.
"},{"location":"Security/CVE-2023-23397/FAQ/#why-does-my-output-file-contain-multiple-entries-for-the-same-mailbox","title":"Why does my output file contain multiple entries for the same mailbox?","text":"For each individual item that does contain the PidLidReminderFileParameter property, it will be exported out with a item ID that is needed to possibly take action against.
"},{"location":"Security/CVE-2023-23397/FAQ/#what-are-the-required-steps-to-prepare-the-cve-2023-23397application-application-to-support-certificate-based-authentication-cba","title":"What are the required steps to prepare the 'CVE-2023-23397Application' application to support Certificate Based Authentication (CBA)","text":"Step 1: Create the Azure application by running the script with the CreateAzureApplication
. This step must be performed by someone who is Global Administrator
or an Application Administrator
.
Step 2: Generate a new self-signed certificate and export the public part:
$cert = New-SelfSignedCertificate -Subject $env:COMPUTERNAME -CertStoreLocation \"Cert:\\CurrentUser\\My\"\n$cert | Export-Certificate -FilePath MySelfSignedCertificate.cer\n$cert.Thumbprint\n
Important
The certificate must be kept confidential as it allows the owner to access the Azure application without further authentication.
Step 3: Upload the certificate to the CVE-2023-23397Application
Azure application
Go to the Azure Active Directory and search for App registrations
. Select the CVE-2023-23397Application
application and go to Certificates & secrets
. From here, select Certificates
and click on Upload certificate
. Select the MySelfSignedCertificate.cer
file which was created in Step 2, add a descriptive description. Complete the process by clicking on Add
.
The application is now ready for CBA.
"},{"location":"Setup/CopyMissingDlls/","title":"CopyMissingDlls","text":"Download the latest release: CopyMissingDlls.ps1
This script is used to copy over missing dlls that might have occurred during a CU install. This script has a mapping of the location of where the .dll should be on the server and where it should be on the ISO and will attempt to copy it over if the file is detected to be missing on the install location.
Parameter Type Description IsoRoot string The Root location of the ISO. Example:D:
"},{"location":"Setup/FixInstallerCache/","title":"FixInstallerCache","text":"Download the latest release: FixInstallerCache.ps1
This script is used to copy over the missing MSI files from the installer cache.
Parameter Type Description CurrentCuRootDirectory string The root location of the current CU that you are on. MachineName string array One or more machine names from which to copy the required MSI files."},{"location":"Setup/Set-ExchAVExclusions/","title":"Set-ExchAVExclusions","text":"Download the latest release: Set-ExchAVExclusions.ps1
The Script will assist in setting the Antivirus Exclusions according to our documentation for Microsoft Exchange Server.
AV Exclusions Exchange 2016/2019
AV Exclusions Exchange 2013
If you use Windows Defender you can Set the exclusions executing the script without parameters but if you have any other Antivirus solution you can get the full list of Expected Exclusions.
"},{"location":"Setup/Set-ExchAVExclusions/#requirements","title":"Requirements","text":""},{"location":"Setup/Set-ExchAVExclusions/#supported-exchange-server-versions","title":"Supported Exchange Server Versions:","text":"The script can be used to validate the configuration of the following Microsoft Exchange Server versions: - Microsoft Exchange Server 2013 - Microsoft Exchange Server 2016 - Microsoft Exchange Server 2019
The server must have Microsoft Defender to set it and enable it to be effective.
"},{"location":"Setup/Set-ExchAVExclusions/#required-permissions","title":"Required Permissions:","text":"Please make sure that the account used is a member of the Local Administrator
group. This should be fulfilled on Exchange servers by being a member of the Organization Management
group.
This script must be run as Administrator in Exchange Management Shell on an Exchange Server. You do not need to provide any parameters and the script will set the Windows Defender exclusions for the local Exchange server.
If you want to get the full list of expected exclusions you should use the parameter ListRecommendedExclusions
You can export the Exclusion List with the parameter FileName
This will run Set-ExchAVExclusions Script against the local server.
.\\Set-ExchAVExclusions.ps1\n
This will run Set-ExchAVExclusions Script against the local server and show in screen the expected exclusions on screen without setting them.
.\\Set-ExchAVExclusions.ps1 -ListRecommendedExclusions\n
This will run Set-ExchAVExclusions Script against the local server and show in screen the expected exclusions on screen without setting them and write them in the defined FileName
.
.\\Set-ExchAVExclusions.ps1 -ListRecommendedExclusions -FileName .\\Exclusions.txt\n
This will run Set-ExchAVExclusions Script against the local server and write them in the defined FileName
.
.\\Set-ExchAVExclusions.ps1 -FileName .\\Exclusions.txt\n
"},{"location":"Setup/Set-ExchAVExclusions/#outputs","title":"Outputs","text":"Exclusions List File: FileName
Log file: $PSScriptRoot\\SetExchAvExclusions.log
"},{"location":"Setup/SetupLogReviewer/","title":"SetupLogReviewer","text":"Download the latest release: SetupLogReviewer.ps1
This script is meant to be run against the Exchange Setup Logs located at C:\\ExchangeSetupLogs\\ExchangeSetup.log
. You can run this on the server, or on a personal computer.
It currently checks for common prerequisite issues, clearly calling out if you need up run /PrepareAD in your environment and calls out where it needs to be run. It also checks for some other common issue that we have seen in support that we call out and display the actions to the screen.
Parameter Description [string]SetupLog The location of the Exchange Setup Log that needs to be reviewed [switch]DelegatedSetup Use this switch if you are troubleshooting Prerequisites of a Delegated Setup issue"},{"location":"Setup/SetupAssist/","title":"SetupAssist","text":"Download the latest release: SetupAssist.ps1
This script is meant to be run on the system where you are running setup from. It currently checks and displays the following when just running it:
Domain Admins
Schema Admins
Enterprise Admins
Organization Management
Additional Parameters are used for when they are called out from the SetupLogReviewer.ps1
When the CN=Computers container has been renamed or removed from the root of an Active Directory domain, /PrepareAD will fail for certain Cumulative Updates. Please see https://support.microsoft.com/help/5005319 for details.
"},{"location":"Setup/SetupAssist/InstallWatermark/","title":"Install Watermark","text":"After a failed install attempt of Exchange, we can leave behind a watermark that then prevents you from trying to run setup again when trying use unattended mode. To get around this issue, run Setup.exe from the GUI and not the command line. From the GUI, it is able to detect that we had a watermark and tries to pick up where we left off. However, unattended mode fails in the prerequisites check section prior to running and the GUI skips over this section.
Warning
Do NOT remove the watermark from the registry as you will run into more setup issues trying to run steps the server already completed. Run setup from the GUI to allow setup to pick up where the watermark is set at.
"},{"location":"Setup/SetupAssist/ReadOnlyDomainControllerContainer/","title":"Read Only Domain Controller - Domain Controllers OU","text":"A Read Only Domain Controller appears to be in the container other than CN=Domain Controllers. This will cause setup to fail if we attempt to domain prep that domain. The path to the RODC must be CN=DCName,CN=Domain Controllers....
"},{"location":"Setup/SetupAssist/RebootPending/","title":"Reboot Pending","text":"It is best to reboot the server to address these issues. It may take some time after a reboot to have the keys automatically removed. However, if they don't remove automatically, follow these steps to address the issue for the keys that were provided to be a problem.
NOTE: With Component Based Servicing\\RebootPending
you need to do the same for Component Based Servicing\\PackagesPending
prior to RebootPending
NOTE: Follow the steps in this section carefully. Serious problems might occur if you modify the registry incorrectly. Before you modify it, back up the registry for restoration in case problems occur.
"},{"location":"Transport/Compute-TopExoRecipientsFromMessageTrace/","title":"Compute-TopExoRecipientsFromMessageTrace","text":"Download the latest release: Compute-TopExoRecipientsFromMessageTrace.ps1
This script aggregates message trace events hourly and generates a report with the top o365 recipients
"},{"location":"Transport/Compute-TopExoRecipientsFromMessageTrace/#parameters","title":"Parameters","text":"-StartDate
The StartDate parameter specifies the end date of the date range
-EndDate
The EndDate parameter specifies the end date of the date range. It is recommended to limit the start-end date range to a range of hours. i.e. an ~ 5 to 7 hours.
-TimeoutAfter
The TimeoutAfter parameter specifies the number of minutes before the script stop working. This is to make sure that the script does not run for infinity. The default value is 30 minutes.
-Threshold
The Threshold parameter specifies the min threshold for the received limit. It is used to filter the hourly aggregation. The default value is 3600 messages.
"},{"location":"Transport/Compute-TopExoRecipientsFromMessageTrace/#examples","title":"Examples","text":"$results = Compute-TopExoRecipientsFromMessageTrace -StartDate (Get-Date).AddHours(-7) -EndDate (Get-Date)\n
"},{"location":"Transport/Compute-TopExoRecipientsFromMessageTrace/#output","title":"Output","text":"$results.TopRecipients : hourly report for top recipients over the threshold $results.HourlyReport : hourly aggregated message events without applying the threshold $results.MessageTraceEvents: all downloaded message trace events without aggregations
"},{"location":"Transport/ReplayQueueDatabases/","title":"ReplayQueueDatabases","text":"Download the latest release: ReplayQueueDatabases.ps1
When Transport crashes, in some scenarios it will move the current queue database to Messaging.old- and create a new empty database. The old database is usually not needed, unless shadow redundancy was failing. In that case, it can be useful to drain the old queue file to recover those messages.
This script automates the process of replaying many old queue files created by a series of crashes.
"},{"location":"Transport/ReplayQueueDatabases/#syntax","title":"Syntax","text":"ReplayQueueDatabases.ps1\n [-MaxAgeInDays <int>]\n [-RemoveDeliveryDelayedMessages]\n
"},{"location":"Transport/ReplayQueueDatabases/#parameters","title":"Parameters","text":"-MaxAgeInDays <Int32>\n Only replay queue databases newer than this date\n\n Required? false\n Position? 1\n Default value 7\n\n-RemoveDeliveryDelayedMessages [<SwitchParameter>]\n Attempt to remove delivery delay notifications so user mailboxes do not fill up with these while we replay old messages\n\n Required? false\n Position? named\n Default value False\n
"},{"location":"Transport/ReplayQueueDatabases/#usage","title":"Usage","text":"The script must be run from Exchange Management Shell locally on the server where queue databases are being replayed. Preliminary steps before running this script:
Set-MailboxServer $env:ComputerName -DatabaseCopyAutoActivationPolicy Blocked
When the script is run, it takes the following actions.
The EdgeTransport.exe.config is copied to EdgeTransport.exe.config.before-replay.
Begin looping over the folders that were under MaxAgeInDays, starting with the most deeply nested folder.
Continue to the next folder.
When finished with all the folders, stop the Transport services.
Note that when the script is run without -Confirm:$false, it will prompt for nearly every step of this process. This is probably the best approach for most scenarios, so that each step of the script is visible and understood by the user. \"Yes to All\" can be used to remove most of the prompting within the script. However, even with \"Yes to All\", prompts to start and stop services between replays of each database will occur.
If there are many databases to replay, -Confirm:$false can be used to remove all prompting.
"},{"location":"Transport/ReplayQueueDatabases/#cleanup","title":"Cleanup","text":"If the script fails out or is terminated in the middle, the following steps may be needed in order to run the script again and/or return the environment to a normal state.
This project contains scripts for supporting and troubleshooting Microsoft Exchange Server.
"},{"location":"#popular-scripts","title":"Popular Scripts","text":"Script Docs Download HealthChecker.ps1 Docs Download ExchangeExtendedProtectionManagement.ps1 Docs Download SetupAssist.ps1 Docs Download SourceSideValidations.ps1 Docs Download Test-AMSI.ps1 Docs Download"},{"location":"Emerging-Issues/","title":"Emerging Issues for Exchange On-Premises","text":"This page lists emerging issues for Exchange On-Premises deployments, possible root cause and solution/workaround to fix the issues. The page will be consistently updated with new issues found and reflect current status of the issues mentioned.
Updated on Update causing the issue Issue Workaround/Solution 11/23/2023 November 2023 Security Update for Exchange 2016, Exchange 2019 Some customers may find queue viewer crashing with error \"Failed to enable constraints. One or more rows contain values violating non-null, unique, or foreign-key constraints\" The error can occur if the Exchange server auth certificate has expired. Solution is to renew the Exchange server auth certificate manually or by using this script 10/12/2023 All versions of August 2023 Security Update for Exchange 2016, Exchange 2019 Users in account forest can't change expired password in OWA in multi-forest Exchange deployments after installing any version of August 2023 Security Update for Exchange servers Note The account forest user will be able to change the password after they sign in to Outlook on the web if their password is not yet expired. The issue affects only account forest users who have passwords that are already expired. This change does not affect users in organizations that don't use multiple forests. ** Update on 10/12/2023 ** Follow steps on this article 8/15/2023 Non-English August 2023 Security Update for Exchange 2016, Exchange 2019 When you install the Microsoft Exchange Server 2019 or 2016 August 2023 Security Update (SU) on a Windows Server-based device that is running a non-English operating system (OS) version, Setup suddenly stops and rolls back the changes. However, the Exchange Server services remain in a disabled state. The latest SUs have been released that do not require a workaround to install. If you used a workaround to install KB5029388, it is highly recommend to uninstall the KB5029388 to avoid issues down the line. For more information please check out this KB. 6/15/2023 January 2023 Security Update for Exchange 2016, Exchange 2019 When you try to uninstall Microsoft Exchange Server 2019 or 2016 on servers, that had January 2023 Security Update for Exchange Server installed at any point, the Setup fails with following error message: [ERROR] The operation couldn't be performed because object '' couldn't be found on ''. Install Exchange Security Update June 2023 or higher to resolve the issue. Check this KB for more details 6/15/2023 Extended protection enabled on Exchange server Changing the permissions for Public Folders by using an Outlook client will fail with the following error, if Extended Protection is enabled:The modified Permissions cannot be changed.
Install Exchange Security Update June 2023 or higher Security Update and create the setting override mentioned in this KB 3/16/2023 Outlook client update for CVE-2023-23397 released These vulnerabilities affect Exchange Server. Exchange Online customers are already protected from the vulnerabilities addressed in these SUs and do not need to take any action other than updating Exchange servers in their environment, and if applicable, installing the security update for Outlook on Windows described on the link on the right.More details about specific CVEs can be found in the Security Update Guide (filter on Exchange Server under Product Family).Awareness: Outlook client update for CVE-2023-23397 releasedThere is a critical security update for Microsoft Outlook for Windows that is required to address CVE-2023-23397. To address this CVE, you must install the Outlook security update, regardless of where your mail is hosted (e.g., Exchange Online, Exchange Server, some other platform). Please check this page for FAQs about the Outlook CVE-2023-23397 3/14/2023 February 2023 Security Update for Exchange 2016, Exchange 2019, Exchange 2013 After installing February 2023 security update, customers are seeing EWS application pool crash with Event ID 4999 with following error E12IIS, c-RTL-AMD64, 15.01.2507.021, w3wp#MSExchangeServicesAppPool, M.Exchange.Diagnostics, M.E.D.ChainedSerializationBinder.EnforceBlockReason, M.E.Diagnostics.BlockedDeserializeTypeException, 437c-dumptidset, 15.01.2507.021. The issue is causing connectivity issues to EWS based clients (Outlook for Mac) Update on 3/14/2023 The issue is fixed in March 2023 security update for Exchange servers Please follow the steps in this KB 3/14/2023 February 2023 Security Update for Exchange 2016, Exchange 2019, Exchange 2013 Some customers are reporting issues with Outlook/OWA add-ins, like add-in not listing in EAC or with the Get-App command. Additionally, they may notice EWS application pool crash with Event ID 4999 in the application log of the Exchange server. Update on 3/14/2023 The issue is fixed in March 2023 security update for Exchange servers 3/14/2023 January 2023 Security Update for Exchange 2016, Exchange 2019 The Exchange toolbox may start crashing on launch after certificate Serialization for PowerShell is enabled. The error noticed is \"Deserialization fails: System.Reflection.TargetInvocationException\". The issue happens only on Exchange 2016 and Exchange 2019 Update on 3/14/2023 The issue is fixed in March 2023 security update for Exchange servers - - - - 1/24/2023 January 2023 Security Update for Exchange 2016, Exchange 2019 After installing January 2023 security update and enabling certificate signing for serialization of PowerShell, you may find various Exchange commands and scripts (example: RedistributeActiveDatabases.ps1) that use deserialization failing with the error similar to : Error: \"Cannot convert the value of type.....to type\" Use this script to update the auth certificate 1/24/2023 January 2023 Security Update for Exchange 2016, Exchange 2019 RecoverServer will fail at pre-requisites check with following error: \"Exchange Server version Version 15.1 (Build 2507.17) or later must be used to perform a recovery of this server.\" Update on 02/23/2023 The issue has been fixed in February 2023 Security Update for Exchange servers, however, the following workaround still needs to be used for servers that are on January 2023 Security Update Workaround Use the steps in this article 1/24/2023 January 2023 Security Update for Exchange 2016 installed on Windows 2012 R2, other versions are not affected The Exchange services in Automatic start-up mode will not start after reboot of the server. The services start successfully if started manually Update on 02/23/2023The issue has been fixed in February 2023 Security Update for Exchange servers 1/24/2023 January 2023 Security Update for Exchange 2016, Exchange 2019 Transport header shows the older version of server once January 2023 SU is installed (the build shown seems to be the build of the last CU) The issue will be addressed in upcoming security update Updated on 11/8/2022
Issue Possible reason Workaround/Solution Zero-day vulnerabilities reported in Microsoft Exchange Server, CVE-2022-41040 and CVE-2022-41082 N/A Install November 2022 Exchange Server Security Updates to address the vulnerabilityUpdated on 5/11/2022
Issue Possible reason Workaround/Solution After installing March 2022 Security Update For Exchange Server 2013, 2016, 2019, the Microsoft Exchange Service Host service may crash repeatedly with Event ID 7031 in system log and Event ID 4999 in application log. Event ID 4999 Watson report about to be sent for process id: 4564, with parameters: E12IIS, c-RTL-AMD64, 15.01.2375.024, M.Exchange.ServiceHost, M.Exchange.Diagnostics, M.E.D.ChainedSerializationBinder.LoadType, M.E.Diagnostics.BlockedDeserializeTypeException, c0e9-DumpTidSet, 15.01.2375.024. The issue can occur if there are any expired certificates present on or any certificates nearing expiry on the server Install May 2022 Exchange Server Security Updates to resolve the issueUpdated on 3/16/2022
Issue Possible reason Workaround/Solution After installing March 2022 Security Update For Exchange Server 2013, 2016, 2019, the Microsoft Exchange Service Host service may crash repeatedly with Event ID 7031 in system log and Event ID 4999 in application log. Event ID 4999 Watson report about to be sent for process id: 4564, with parameters: E12IIS, c-RTL-AMD64, 15.01.2375.024, M.Exchange.ServiceHost, M.Exchange.Diagnostics, M.E.D.ChainedSerializationBinder.LoadType, M.E.Diagnostics.BlockedDeserializeTypeException, c0e9-DumpTidSet, 15.01.2375.024. The issue can occur if there are any expired certificates present on or any certificates nearing expiry on the server Update 3/16/2022 Follow the steps from KB 5013118 to resolve the issue"},{"location":"Emerging-Issues/#old-issues","title":"Old Issues","text":""},{"location":"Emerging-Issues/#email-stuck-in-transport-queues","title":"Email Stuck in Transport Queues","text":"Issue Possible reason Workaround/Solution You may observe emails building up in the transport queues of Exchange Server 2016 and Exchange Server 2019. The issue does not impact Exchange 2013 servers.Following events may be noticed in the application log: Log Name: ApplicationSource: FIPFSLogged: 1/1/2022 1:03:42 AM Event ID: 5300 Level: Error Computer: server1.contoso.comDescription: The FIP-FS \"Microsoft\" Scan Engine failed to load. PID: 23092, Error Code: 0x80004005.Error Description: Can't convert \"2201010001\" to long. Log Name: Application Source: FIPFS Logged: 1/1/2022 11:47:16 AM Event ID: 1106 Level: Error Computer: server1.contoso.com Description: The FIP-FS Scan Process failed initialization. Error: 0x80004005. Error Details: Unspecified error. The problem relates to a date check failure with the change of the new year and it not a failure of the AV engine itself. This is not an issue with malware scanning or the malware engine, and it is not a security-related issue. The version checking performed against the signature file is causing the malware engine to crash, resulting in messages being stuck in transport queues. Run this script on each Exchange server in your organization. You can run this script on multiple servers in parallel. Check this article for detailed steps."},{"location":"Emerging-Issues/#november-2021-security-update","title":"November 2021 Security Update","text":"Following are the known issues after installing November 2021 Security Updates for Exchange On-Premises servers
Issue Possible reason Workaround/Solution Hybrid OWA Redirect is broken after application of November SU for Exchange 2013/2016 and 2019. Users using Exchange 2016 and 2019 server will see error \":-( Something went wrong. We can't get that information right now. Please try again later. Exchange 2013 users will see error \"External component has thrown an exception.\" Some On-Premises environments, that are not using FBA, may also see cross-site OWA redirection fail with similar errors. After installing November SU, the OWA redirection URL for hybrid users is providing an encoded URL for &., causing the redirect to fail Update 1/12/2022 The OWA redirection issue is fixed in January 2022 security updates. Please install the relevant update to fix the issue. Alternatively, you can also use the workarounds provided in KB article 5008997"},{"location":"Emerging-Issues/#september-cumulative-updates","title":"September Cumulative Updates","text":"Following are the known issues after installing September 2021 Cumulative Updates for Exchange On-Premises servers
Issue Possible reason Workaround/Solution After installing the September 2021 CU, the Microsoft Exchange Transport Services will continue to crash. You can see the following message for the 4999 crash eventWatson report about to be sent for process id: 10072, with parameters: E12IIS, c-RTL-AMD64, 15.02.0986.005, MSExchangeDelivery, M.Exchange.Transport, M.E.T.AcceptedDomainTable..ctor, System.FormatException, 28d7-DumpTidSet, 15.02.0986.005.
Having a Wild Card Only (*) Accepted Domain Set on an Internal Relay. This is an open relay and is very bad to have set. Remove the Accepted Domain that is set to *
and properly configure an anonymous relay on a receive connector or change to an External Relay. More Information: Allow anonymous relay on Exchange servers"},{"location":"Emerging-Issues/#july-2021-security-updatecumulative-updates","title":"July 2021 Security Update/Cumulative Updates","text":"Following are the known issues after installing July 2021 Security Updates/Cumulative Updates for Exchange On-Premises servers
Issue Possible reason Workaround/Solution OWA/ECP stops working after installing July Security Update with following error: ASSERT: HMACProvider.GetCertificates:protectionCertificates.Length<1 The issue occurs if OAuth certificate is missing or expired Follow steps on this article to re-publish the Oauth certificate. Do note it takes up to an hour for certificate to change place OWA/ECP stops working when accessed from load balanced URL, but works if directly accessed from the server URL The root cause for the issue is under investigation Follow steps in this article to fix the issue PrepareAD with Exchange 2016 CU21/Exchange 2019 CU10 error: Used domain controller dc1.contoso.com to read object CN=AdminSDHolder,CN=System,DC=Contoso,DC=COM. [ERROR] Object reference not set to an instance of an object. The issue is under investigation Follow steps in this article to fix the issue PrepareSchema in environments that have empty root AD domain July Security Update for Exchange 2013 have shipped schema changes and needs Exchange role installed for PrepareSchema, this makes it difficult for environments that have Exchange 2013 as the highest installed Exchange server and do not have an Exchange server installed in the same AD site as that of root AD domain. Option 1 Introduce a new server that meets system requirements for Exchange 2013 Management tools, in the root AD domain. Install just the Exchange 2013 Management Tools role on this server. Install the July security fix, perform Schema update. Option 2 PrepareSchema using Exchange 2016 21/Exchange 2019 CU10 media, as the CU's have the changes. However, once Exchange 2016/2019 media is used to perform schema update, you will need to continue using Exchange 2016/2019 media in the future as well. The Schema Version number for Exchange 2013 environment remains on 15312, even after installing SU and performing PrepareSchema This is expected behavior. The schema version is going to remain 15312 after installing Security Update and performing PrepareSchema After installing Exchange 2016 CU21/Exchange 2019 CU10, the values added to custom attributes using EAC are not retained. The scenario works fine in Exchange 2016 CU20/Exchange 2019 CU9 The issue is under investigation Workaround 1: Use EAC from Internet Explorer Workaround 2: Add the values using Exchange Management Shell"},{"location":"Admin/Clear-MailboxPermission/","title":"Clear-MailboxPermission","text":"Download the latest release: Clear-MailboxPermission.ps1
Attempting to Add-MailboxPermission or Remove-MailboxPermission sometimes fails with the following message:
The ACL for object is not in canonical order (Deny/Allow/Inherited) and will be ignored.
This indicates that the ACEs that make up the ACL do not follow canonical ordering, which generally means denies before allows, and explicit before inherited. When the mailbox security descriptor is in this state, the cmdlets can no longer modify it.
This script can be used to return it to a working state. The script does this by clearing all permissions and resetting it to the default permissions that a brand new mailbox would have.
"},{"location":"Admin/Clear-MailboxPermission/#common-usage","title":"Common Usage","text":"The easiest way to use the script is to pipe the affected mailboxes to it:
Get-Mailbox joe@contoso.com | .\\Clear-MailboxPermission.ps1
Note the script also supports -WhatIf and -Confirm. It will prompt for confirmation by default.
"},{"location":"Admin/CrossTenantMailboxMigrationValidation/","title":"CrossTenantMailboxMigrationValidation","text":"Download the latest release: CrossTenantMailboxMigrationValidation.ps1
"},{"location":"Admin/CrossTenantMailboxMigrationValidation/#description","title":"DESCRIPTION","text":"This script offers the ability to validate users and org settings related to the Cross-tenant mailbox migration before creating a migration batch and have a better experience.
It will help you on:
The script will prompt you to connect to your source and target tenants for EXO and AAD as needed You can decide to run the checks for the source mailbox and target MailUser (individually or by providing a CSV file), for the organization settings described above, collect the source information and compress it to a zip file that can be used by the target tenant admins, or use the collected zip file as a source to validate the target objects and configurations against it.
Additionally, the script provides a version check feature that will check if there's a newer version available on CSS-Exchange repository and will download it if so. If for some reason the version cannot be checked, the build check will be skipped and the existing file will be used.
"},{"location":"Admin/CrossTenantMailboxMigrationValidation/#pre-requisites","title":"PRE-REQUISITES:","text":"This will allow you to skip the version check and run the existing local version of the script. This parameter is optional.
"},{"location":"Admin/CrossTenantMailboxMigrationValidation/#scriptupdateonly","title":"ScriptUpdateOnly","text":"This will allow you to check if there's a newer version available on CSS-Exchange repository without performing any additional checks, and will download it if so. This parameter is optional.
"},{"location":"Admin/CrossTenantMailboxMigrationValidation/#checkobjects","title":"CheckObjects","text":"This will allow you to perform the checks for the Source Mailbox and Target MailUser objects you provide. If used without the \"-CSV\" parameter, you will be prompted to type the identities.. If used with the '-SourceIsOffline' you also need to specify the '-PathForCollectedData' parameter
"},{"location":"Admin/CrossTenantMailboxMigrationValidation/#csv","title":"CSV","text":"This will allow you to specify a path for a CSV file you have with a list of users that contain the \"SourceUser, TargetUser\" columns. An example of the CSV file content would be:
SourceUser, TargetUser\nJdoe@contoso.com, Jdoe@fabrikam.com\nBSmith@contoso.com, BSmith@fabrikam.com\n
If Used along with the 'CollectSourceOnly' parameter, you only need the 'SourceUser' column.
"},{"location":"Admin/CrossTenantMailboxMigrationValidation/#checkorgs","title":"CheckOrgs","text":"This will allow you to perform the checks for the source and target organizations. More specifically the organization relationship on both tenants, the migration endpoint on target tenant and the existence of the AAD application needed.
"},{"location":"Admin/CrossTenantMailboxMigrationValidation/#sdp","title":"SDP","text":"This will collect all the relevant information for troubleshooting from both tenants and be able to send it to Microsoft Support in case of needed.
"},{"location":"Admin/CrossTenantMailboxMigrationValidation/#logpath","title":"LogPath","text":"This will allow you to specify a log path to transcript all the script execution and it's results. This parameter is mandatory.
"},{"location":"Admin/CrossTenantMailboxMigrationValidation/#collectsourceonly","title":"CollectSourceOnly","text":"This will allow you to specify a CSV file so we can export all necessary data of the source tenant and mailboxes to migrate, compress the files as a zip file to be used by the target tenant admin as a source for validation against the target. This parameter is mandatory and also requires the '-CSV' parameter to be specified containing the SourceUser column.
"},{"location":"Admin/CrossTenantMailboxMigrationValidation/#pathforcollecteddata","title":"PathForCollectedData","text":"This will allow you to specify a path to store the exported data from the source tenant when used along with the 'CollectSourceOnly' and 'SDP' parameters transcript all the script execution and it's results. This parameter is mandatory.
"},{"location":"Admin/CrossTenantMailboxMigrationValidation/#sourceisoffline","title":"SourceIsOffline","text":"With this parameter, the script will only connect to target tenant and not source, instead it will rely on the zip file gathered when running this script along with the 'CollectSourceOnly' parameter. When used, you also need to specify the 'PathForCollectedData' parameter pointing to the collected zip file.
"},{"location":"Admin/CrossTenantMailboxMigrationValidation/#examples","title":"EXAMPLES","text":""},{"location":"Admin/CrossTenantMailboxMigrationValidation/#example-1","title":"EXAMPLE 1","text":".\\CrossTenantMailboxMigrationValidation.ps1 -CheckObjects -LogPath C:\\Temp\\LogFile.txt\n
This will prompt you to type the source mailbox identity and the target identity, will establish 2 EXO remote powershell sessions (one to the source tenant and another one to the target tenant), and will check the objects.
"},{"location":"Admin/CrossTenantMailboxMigrationValidation/#example-2","title":"EXAMPLE 2","text":".\\CrossTenantMailboxMigrationValidation.ps1 -CheckObjects -CSV C:\\Temp\\UsersToMigrateValidationList.CSV -LogPath C:\\Temp\\LogFile.txt\n
This will establish 2 EXO remote powershell sessions (one to the source tenant and another one to the target tenant), will import the CSV file contents and will check the objects one by one.
"},{"location":"Admin/CrossTenantMailboxMigrationValidation/#example-3","title":"EXAMPLE 3","text":".\\CrossTenantMailboxMigrationValidation.ps1 -CheckOrgs -LogPath C:\\Temp\\LogFile.txt\n
This will establish 4 remote powershell sessions (source and target EXO tenants, and source and target AAD tenants), and will validate the migration endpoint on the target tenant, AAD applicationId on target tenant and the Organization relationship on both tenants.
"},{"location":"Admin/CrossTenantMailboxMigrationValidation/#example-4","title":"EXAMPLE 4","text":".\\CrossTenantMailboxMigrationValidation.ps1 -SDP -LogPath C:\\Temp\\LogFile.txt -PathForCollectedData C:\\temp\n
This will establish 4 remote powershell sessions (source and target EXO tenants, and source and target AAD tenants), and will collect all the relevant information (config-wise) so it can be used for troubleshooting and send it to Microsoft Support if needed.
"},{"location":"Admin/CrossTenantMailboxMigrationValidation/#example-5","title":"EXAMPLE 5","text":".\\CrossTenantMailboxMigrationValidation.ps1 -SourceIsOffline -PathForCollectedData C:\\temp\\CTMMCollectedSourceData.zip -CheckObjects -LogPath C:\\temp\\CTMMTarget.log\n
This will expand the CTMMCollectedSourceData.zip file contents into a folder with the same name within the zip location, will establish the EXO remote powershell session and also with AAD against the Target tenant and will check the objects contained on the UsersToProcess.CSV file.
"},{"location":"Admin/CrossTenantMailboxMigrationValidation/#example-6","title":"EXAMPLE 6","text":".\\CrossTenantMailboxMigrationValidation.ps1 -SourceIsOffline -PathForCollectedData C:\\temp\\CTMMCollectedSourceData.zip -CheckOrgs -LogPath C:\\temp\\CTMMTarget.log\n
This will expand the CTMMCollectedSourceData.zip file contents into a folder with the same name within the zip location, will establish the EXO remote powershell session and also with AAD against the Target tenant, and will validate the migration endpoint on the target tenant, AAD applicationId on target tenant and the Organization relationship on both tenants.
"},{"location":"Admin/CrossTenantMailboxMigrationValidation/#example-7","title":"EXAMPLE 7","text":".\\CrossTenantMailboxMigrationValidation.ps1 -CollectSourceOnly -PathForCollectedData c:\\temp -LogPath C:\\temp\\CTMMCollectSource.log -CSV C:\\temp\\UsersToMigrate.csv\n
This will connect to the Source tenant against AAD and EXO, and will collect all the relevant information (config and user wise) so it can be used passed to the Target tenant admin for the Target validation to be done without the need to connect to the source tenant at the same time.
"},{"location":"Admin/Find-AmbiguousSids/","title":"Find-AmbiguousSids","text":"Download the latest release: Find-AmbiguousSids.ps1
Useful when Exchange throws NonUniqueRecipientException
, but doesn't log the objects causing it.
Find-AmbiguousSids.ps1\n [-GCName <string>]\n [-IgnoreWellKnown <bool>]\n [-Verbose]\n
"},{"location":"Admin/Find-AmbiguousSids/#examples","title":"Examples","text":"Find all ambiguous SIDs:
.\\Find-AmbiguousSids.ps1\n
Find all ambiguous SIDs while not ignoring the well-known ones, such as Everyone and other SIDs that always appear in multiple places:
.\\Find-AmbiguousSids.ps1 -IgnoreWellKnown $false\n
Show each object being checked:
.\\Find-AmbiguousSids.ps1 -Verbose\n
"},{"location":"Admin/Get-EASMailboxLogs/","title":"Get-EASMailboxLogs","text":"Download the latest release: Get-EASMailboxLogs.ps1
Used for when you need to get EAS Mailbox Logging over a long period of time. It will collect the logs and re-enable the Active Sync Logging enabled to avoid it being disabled after 72 hours.
"},{"location":"Admin/Get-EASMailboxLogs/#syntax","title":"Syntax","text":"Get-EASMailboxLogs.ps1\n [-Mailbox <string[]>]\n [-OutputPath <string>]\n [-Interval <int>]\n [-EnableMailboxLoggingVerboseMode <bool>]\n
"},{"location":"Admin/Get-EASMailboxLogs/#examples","title":"Examples","text":"The following example collects logs for two mailbox every hour:
.\\Get-EASMailboxLogs.ps1 -mailbox @(\"jim\",\"zeke\") -OutputPath C:\\EASLogs -interval 60\n
The following example collects logs for a mailbox:
.\\Get-EASMailboxLogs.ps1 -Mailbox \"jim\" -OutputPath c:\\EASLogs\n
The following example enables Verbose Logging on the current on premise server and collects logs for a mailbox:
.\\Get-EASMailboxLogs.ps1 -Mailbox \"jim\" -OutputPath c:\\EASLogs -EnableMailboxLoggingVerboseMode $true\n
"},{"location":"Admin/Get-SimpleAuditLogReport/","title":"Get-SimpleAuditLogReport","text":"Download the latest release: Get-SimpleAuditLogReport.ps1
Exchange admin audit logs are not readily human readable. All of the data needed to understand what Cmdlet has been run is in the data but it is not very easy to read. Get-SimpleAuditLogReport will take the results of an audit log search and provide a significantly more human readable version of the data.
It will parse the audit log and attempt to reconstruct the actual Cmdlet that was run.
"},{"location":"Admin/Get-SimpleAuditLogReport/#common-usage","title":"Common Usage","text":"$Search = Search-AdminAuditLog
$search | C:\\Scripts\\Get-SimpleAuditLogReport.ps1
Download the latest release: MonitorExchangeAuthCertificate.ps1
The MonitorExchangeAuthCertificate.ps1
PowerShell script can help you to manage the Auth Certificate used by multiple security features in Exchange Server. The script can be used to renew an already expired Auth Certificate or repair an invalid Auth Configuration in which the current Auth Certificate isn't available on all Exchange Servers running the Mailbox or Client Access Server (CAS) role. It can also manage rotation of the Auth Certificate to ensure a smooth transition to a new Auth Certificate.
The script comes with a manual execution mode and an automation mode that works using the Windows Task Scheduler.
"},{"location":"Admin/MonitorExchangeAuthCertificate/#requirements","title":"Requirements","text":"To run the script, you must be a member of the Organization Management
role group. The script must be run from an elevated Exchange Management Shell (EMS) command prompt on an Exchange Server running the Mailbox role. The script cannot be run on an Exchange Management Tools-only machine.
Each run of the script is logged to the following directory: <ExchangeInstallPath>\\Logging\\AuthCertificateMonitoring
The naming syntax of the log file is: <AuthCertificateMonitoringLog>_<Timestamp>.txt
NOTE: If the <ExchangeInstallPath>
directory doesn't exists, the log file will be written to the following directory: <$env:TEMP>\\Logging\\AuthCertificateMonitoring
The following syntax runs the script in validation-only mode. It will show you the required Auth Certificate renewal action that would be performed if the script is executed in renewal mode.
PS C:\\> .\\MonitorExchangeAuthCertificate.ps1\n
The following syntax executes the script in renewal mode with user interaction. The required Auth Certificate renewal action will be performed, and the administrator might see prompts that need to be confirmed before the script continues:
PS C:\\> .\\MonitorExchangeAuthCertificate.ps1 -ValidateAndRenewAuthCertificate $true\n
If you respond with 'Y', then the script will run in unattended mode and will not prompt you again.
It's recommended to recycle the WebApp Pools when the active Auth Certificate is replaced. You should respond with 'Y'.
It's not recommended to replace the internal transport certificate with the newly created Auth Certificate. You should respond with 'N'.
The following syntax executes the script in renewal mode without user interaction. The required Auth Certificate renewal action will be performed. In unattended mode the internal SMTP certificate is replaced with the new Auth Certificate and then set back to the previous one. The script also restarts the MSExchangeServiceHost
service and the MSExchangeOWAAppPool
and MSExchangeECPAppPool
WebApp Pools when the primary Auth Certificate has been replaced.
NOTE: The script creates a new internal transport certificate if the previously configured one wasn't found on the machine where the script is run.
PS C:\\> .\\MonitorExchangeAuthCertificate.ps1 -ValidateAndRenewAuthCertificate $true -Confirm:$false\n
The following syntax runs the script in renewal mode without user interaction. We only take the Exchange servers into account if they are reachable and will perform the renewal action if required.
PS C:\\> .\\MonitorExchangeAuthCertificate.ps1 -ValidateAndRenewAuthCertificate $true -IgnoreUnreachableServers $true -Confirm:$false\n
The following syntax executes the script in renewal mode without user interaction. The renewal action will be performed even when an Exchange hybrid configuration is detected.
NOTE: You must re-run the Hybrid Configuration Wizard (HCW) after the active Auth Certificate has been replaced.
PS C:\\> .\\MonitorExchangeAuthCertificate.ps1 -ValidateAndRenewAuthCertificate $true -IgnoreHybridConfig $true -Confirm:$false\n
The following syntax executes the script in scheduled task mode. In this mode, the script performs the following steps:
NOTE: It doesn't matter what you type into the Username
box, so you can enter, for example abc
. Make sure to use a password that complies with the password guidelines of your organization.
PS C:\\> .\\MonitorExchangeAuthCertificate.ps1 -ConfigureScriptToRunViaScheduledTask -Password (Get-Credential).Password\n
NOTE: The ConfigureScriptToRunViaScheduledTask
parameter can be combined with the IgnoreHybridConfig
and IgnoreUnreachableServers
parameter.
Auth Certificate Management
, which has the following roles assigned: View-Only Configuration
, View-Only Recipients
, Exchange Server Certificates
, Organization Client Access
SystemMailbox{b963af59-3975-4f92-9d58-ad0b1fe3a1a3}@contoso.local
Auth Certificate Management
Exchange Role Group<ExchangeInstallPath>\\Scripts
SystemMailbox{b963af59-3975-4f92-9d58-ad0b1fe3a1a3}@contoso.local
userThe following syntax runs the script in Active Directory (AD) account creation mode which can be useful when Exchange runs in AD Split Permissions mode. An AD administrator with sufficient permissions to create a user in AD (e.g., a Domain Admin) can run the script in this mode to create the SystemMailbox{b963af59-3975-4f92-9d58-ad0b1fe3a1a3}@contoso.local
account. The account can then be passed by the Exchange administrator via AutomationAccountCredential
parameter as outlined in the next example.
In this mode, the script can be executed from an elevated PowerShell command prompt (no EMS required) running on a non-Exchange Server machine with the ActiveDirectory PowerShell module installed, as it only uses cmdlets which are coming with this module.
NOTE: We recommend creating a user account in the same domain where Exchange was installed. You can specify the domain by using the ADAccountDomain
parameter.
PS C:\\> .\\MonitorExchangeAuthCertificate.ps1 -PrepareADForAutomationOnly -ADAccountDomain \"root.local\"\n
The following syntax executes the script in scheduled task mode, but it doesn't create the SystemMailbox{b963af59-3975-4f92-9d58-ad0b1fe3a1a3}@contoso.local
user account. Instead, the account passed via AutomationAccountCredential
parameter is used. Should a renewal action be performed, then email notifications will be sent to John.Doe@contoso.com\"
.
PS C:\\> .\\MonitorExchangeAuthCertificate.ps1 -ConfigureScriptToRunViaScheduledTask -AutomationAccountCredential (Get-Credential) -SendEmailNotificationTo \"John.Doe@contoso.com\"\n
The following syntax runs the script in Auth Certificate export mode. In this mode, the script exports the current and (if configured) the next Auth Certificate as DER (Distinguished Encoding Rules) binary encoded PKCS #12
files, using the .pfx
file name extension.
The naming syntax for the exported .pfx file is: <CertificateThumbprint>-<Timestamp>.pfx
PS C:\\> .\\MonitorExchangeAuthCertificate.ps1 -ExportAuthCertificatesAsPfx\n
The following syntax executes the script in update-only mode. In this mode, the script only checks for a more current version of the script and downloads it if found.
PS C:\\> .\\MonitorExchangeAuthCertificate.ps1 -ScriptUpdateOnly\n
"},{"location":"Admin/MonitorExchangeAuthCertificate/#parameters","title":"Parameters","text":"Parameter Description ValidateAndRenewAuthCertificate This optional parameter enables the validation and renewal mode which will perform the required actions to replace an invalid/expired Auth Certificate or configures a new next Auth Certificate if the current Auth Certificate expires in < 60 days or the certificate configured as next Auth Certificate expires in < 120 days. IgnoreUnreachableServers This optional parameter can be used to ignore if some of the Exchange servers within the organization cannot be reached. If this parameter is used, the script only validates the servers that can be reached and will perform Auth Certificate renewal actions based on the result. Parameter can be combined with the IgnoreHybridConfig
parameter and can also be used with the ConfigureScriptToRunViaScheduledTask
parameter to configure the script to run via scheduled task. IgnoreHybridConfig This optional parameter allows you to explicitly perform Auth Certificate renewal actions (if required) even if an Exchange hybrid configuration was detected. You need to run the HCW after the renewed Auth Certificate becomes the one in use. Parameter can be combined with the IgnoreUnreachableServers
parameter and can also be used with the ConfigureScriptToRunViaScheduledTask
parameter to configure the script to run via scheduled task. PrepareADForAutomationOnly This optional parameter can be used in AD Split Permission scenarios. It allows you to create the AD account which can then be used to run the Exchange Auth Certificate Monitoring script automatically via Task Scheduler. ADAccountDomain This optional parameter allows you to specify the domain which is then used by the script to generate the AD account used for automation. Parameter can be combined with the PrepareADForAutomationOnly
parameter. ConfigureScriptToRunViaScheduledTask This optional parameter can be used to automatically prepare the requirements in AD (user account), Exchange (email enable the account, hide the account from address book, create a new role group with limited permissions) and finally it creates the scheduled task on the computer on which the script was executed (it has to be an Exchange server running the mailbox role). AutomationAccountCredential This optional parameter can be used to provide a different user under whose context the script is then executed via scheduled task. SendEmailNotificationTo This optional parameter can be used to specify recipients which will then be notified in case that an Exchange Auth Certificate renewal action was performed. The script uses the EWS API
to send out email notifications. Make sure that the user in whose context the script is running is allowed to use EWS
. TrustAllCertificates This optional parameter can be used to trust all certificates when connecting to the EWS service to send out email notifications. TestEmailNotification This optional parameter can be used to test the email notification feature of the script. Password Parameter to provide a password to the script which is required in some scenarios. ExportAuthCertificatesAsPfx This optional parameter can be used to export all on the system available Auth Certificates as password protected .pfx file. ScriptUpdateOnly This optional parameter allows you to only update the script without performing any other actions. SkipVersionCheck This optional parameter can be used to skip the Auto Update feature to download the latest version of the script."},{"location":"Admin/Remove-CertExpiryNotifications/","title":"Remove-CertExpiryNotifications","text":"Download the latest release: Remove-CertExpiryNotifications.ps1
This script deletes all AsyncOperationNotification items from the Exchange SystemMailbox that contains them. This corrects the BlockedDeserializeTypeException error described in KB5013118.
NOTE: This script only supports Exchange 2016 and Exchange 2019. It will not work on Exchange 2013.
"},{"location":"Admin/Remove-CertExpiryNotifications/#syntax","title":"Syntax","text":"Remove-CertExpiryNotifications.ps1\n [-Server <string>]\n [[-Credential] <PsCredential>]\n [-WhatIf]\n [-Confirm]\n
"},{"location":"Admin/Remove-CertExpiryNotifications/#usage","title":"Usage","text":"NOTE: If an error occurs please see Common Errors.
The user running the script must be granted full access to the arbitration mailbox prior to running the script. That can be accomplished with this command:
Get-Mailbox -Arbitration \"SystemMailbox{e0dc1c29-89c3-4034-b678-e6c29d823ed9}\" | Add-MailboxPermission -User SomeAdmin -AccessRights FullAccess\n
Next, the same user that was granted access should run the script from Exchange Management Shell. Start by running the script with -WhatIf. Optionally, the -Credential switch can be provided. Otherwise, the current user will be used.
.\\Remove-CertExpiryNotifications.ps1 -Server exch1.contoso.com -WhatIf\n
If this succeeds, it will list all the messages that would be deleted. The output should look something like this:
To remove the messages, the script can be run without -WhatIf:
.\\Remove-CertExpiryNotifications.ps1 -Server exch1.contoso.com\n
This syntax will cause it to prompt for each message:
Or, the script can be run with -Confirm:$false to skip the prompts:
.\\Remove-CertExpiryNotifications.ps1 -Server exch1.contoso.com -Confirm:$false\n
After the script has run successfully, it should report that there are no messages present in the folder:
Finally, remember to remove the permission that was granted to the user:
Get-Mailbox -Arbitration \"SystemMailbox{e0dc1c29-89c3-4034-b678-e6c29d823ed9}\" | Remove-MailboxPermission -User SomeAdmin -AccessRights FullAccess\n
"},{"location":"Admin/Remove-CertExpiryNotifications/#common-errors","title":"Common errors","text":"Invoke-RestMethod : The underlying connection was closed: An unexpected error occurred on a send.\n
\"Unexpected error occurred on a send\" usually means that the name in the certificate on the target server does not match what was specified in the -Server parameter. In other words, navigating to https://the.server.you.specified/owa
must not return a certificate error. If it does, the script will fail. The specified server must be the name in the certificate bound to IIS.
Invoke-RestMethod : The remote server returned an error: (401) Unauthorized.\n
This can occur if the user running the script does not have full access to the mailbox. Be sure the Add-MailboxPermission command was successful.
This can also occur if the server name specified is the local server, due to the loopback check. This can be resolved by passing a different name.
"},{"location":"Admin/Reset-ScanEngineVersion/","title":"Reset-ScanEngineVersion","text":"Download the latest release: Reset-ScanEngineVersion.ps1
"},{"location":"Admin/Reset-ScanEngineVersion/#syntax","title":"Syntax","text":"Reset-ScanEngineVersion.ps1\n [-Force <switch>]\n [-EngineUpdatePath <string>]\n
"},{"location":"Admin/Reset-ScanEngineVersion/#usage","title":"Usage","text":"Copy the script to an affected Exchange server and run it with no parameters. It can be run from EMS or plain PowerShell.
In scenarios where centralized distribution of scan engines is used, add the -EngineUpdatePath switch to point to the share containing the engines. For example:
.\\Reset-ScanEngineVersion.ps1 -EngineUpdatePath \\\\FileServer1\\ScanEngineUpdates\n
"},{"location":"Admin/SetUnifiedContentPath/","title":"SetUnifiedContentPath","text":"Download the latest release: SetUnifiedContentPath.ps1
Sets the CleanupFolderREsponderFolderPaths in the AntiMalware.xml file that is responsible for having Exchange automatically clean up the Unified Content that is left behind.
If this isn't properly set, you can have large amount of files left on the computer that is just using up space and can cause issues with Exchange.
The script will keep the default values of D:\\ExchangeTemp\\TransportCts\\UnifiedContent
, C:\\Windows\\Temp\\UnifiedContent
, and $ExInstall\\TransportRoles\\data\\Temp\\UnifiedContent
within the value and will include TemporaryStoragePath
from the EdgeTransport.exe.config
if different from the install path.
In order for the new settings to take effect right away, use the -RestartService
switch to have the MSExchangeHM service take in the new changes right away.
The easiest way to run the script is against all the servers and restart the service.
Get-ExchangeServer | .\\SetUnifiedContentPath.ps1 -RestartService\n
If you don't want to change anything just yet, use the -WhatIf
switch to see what servers will have something changed.
Get-ExchangeServer | .\\SetUnifiedContentPath.ps1 -WhatIf\n
Or you can just run it locally on the server
.\\SetUnifiedContentPath.ps1 -RestartService\n
NOTE: The switch -RestartService
is only going to restart the service if a change has been detected and done. Otherwise, it will not restart the service.
The Windows AntiMalware Scan Interface (AMSI) is a versatile standard that allows applications and services to integrate with any AntiMalware product present on a machine. Seeing that Exchange administrators might not be familiar with AMSI, we wanted to provide a script that would make life a bit easier to test, enable, disable, or Check your AMSI Providers.
"},{"location":"Admin/Test-AMSI/#download","title":"Download","text":"Download the latest release: Test-AMSI.ps1
"},{"location":"Admin/Test-AMSI/#parameters","title":"Parameters","text":"Parameter Description TestAMSI If you want to test to see if AMSI integration is working. You can use a server, server list or FQDN of load balanced array of Client Access servers. IgnoreSSL If you need to test and ignoring the certificate check. CheckAMSIConfig If you want to see what AMSI Providers are installed. You can combine with ServerList, AllServers or Sites. EnableAMSI If you want to enable AMSI. Without any additional parameter it will apply at Organization Level. If combine with ServerList, AllServers or Sites it will apply at server level. DisableAMSI If you want to disable AMSI. Without any additional parameter it will apply at Organization Level. If combine with ServerList, AllServers or Sites it will apply at server level. RestartIIS If you want to restart the Internet Information Services (IIS). You can combine with ServerList, AllServers or Sites. Force If you want to restart the Internet Information Services (IIS) without confirmation. ServerList If you want to apply to some specific servers. AllServers If you want to apply to all server. Sites If you want to apply to all server on a sites or list of sites."},{"location":"Admin/Test-AMSI/#common-usage","title":"Common Usage","text":"After you download the script, you will need to run it within an elevated Exchange Management Shell Session
If you want to test to see if AMSI integration is working in a LB Array, you can run: .\\Test-AMSI.ps1 mail.contoso.com
If you want to test to see if AMSI integration is working in list of servers, you can run: .\\Test-AMSI.ps1 -ServerList server1, server2
If you want to test to see if AMSI integration is working in all server, you can run: .\\Test-AMSI.ps1 -AllServers
If you want to test to see if AMSI integration is working in all server in a list of sites, you can run: .\\Test-AMSI.ps1 -AllServers -Sites Site1, Site2
If you need to test and ignoring the certificate check, you can run: .\\Test-AMSI.ps1 -IgnoreSSL
If you want to see what AMSI Providers are installed on the local machine you can run: .\\Test-AMSI.ps1 -CheckAMSIConfig
If you want to enable AMSI at organization level, you can run: .\\Test-AMSI.ps1 -EnableAMSI
If you want to enable AMSI in an Exchange Server or Server List at server level, you can run: .\\Test-AMSI.ps1 -EnableAMSI -ServerList Exch1, Exch2
If you want to enable AMSI in all Exchange Server at server level, you can run: .\\Test-AMSI.ps1 -EnableAMSI -AllServers
If you want to enable AMSI in all Exchange Server in a site or sites at server level, you can run: .\\Test-AMSI.ps1 -EnableAMSI -AllServers -Sites Site1, Site2
If you want to disable AMSI on the Exchange Server, you can run: .\\Test-AMSI.ps1 -DisableAMSI
If you want to disable AMSI in an Exchange Server or Server List at server level, you can run: .\\Test-AMSI.ps1 -DisableAMSI -ServerList Exch1, Exch2
If you want to disable AMSI in all Exchange Server at server level, you can run: .\\Test-AMSI.ps1 -DisableAMSI -AllServers
If you want to disable AMSI in all Exchange Server in a site or sites at server level, you can run: .\\Test-AMSI.ps1 -DisableAMSI -AllServers -Sites Site1, Site2
If you want to restart the Internet Information Services (IIS), you can run: .\\Test-AMSI.ps1 -RestartIIS
If you want to restart the Internet Information Services (IIS) without confirmation, you can run: .\\Test-AMSI.ps1 -RestartIIS -Force
Download the latest release: Update-Engines.ps1
"},{"location":"Admin/Test-ExchangePropertyPermissions/#syntax","title":"Syntax","text":"Test-ExchangePropertyPermissions.ps1\n [-TargetObjectDN] <string>\n [-ComputerAccountDN] <string>\n [[-DomainController] <string>]\n [-OutputDebugInfo]\n [<CommonParameters>]\n
"},{"location":"Admin/Test-ExchangePropertyPermissions/#example","title":"Example","text":".\\Test-ExchangePropertyPermissions.ps1 -TargetObjectDN \"CN=SomeRecipient,OU=Users,DC=contoso,DC=com\" -ComputerAccountDN \"CN=SomeServerName,OU=Computers,DC=contoso,DC=com\"
This example retrieves the group memberships of the SomeServerName computer account and then examines the ACL of SomeRecipient to determine if that computer account can write to all expected attributes of that recipient.
"},{"location":"Admin/Test-ExchangePropertyPermissions/#description","title":"Description","text":"Test-ExchangePropertyPermissions is designed to detect certain schema issues which can manifest as permissions problems and can be challenging to identify manually, including:
Note that the script does not perform an exhaustive check for all possible schema issues. It is only designed to identify a specific subset of issues which we have encountered. For example, using AD Schema Analyzer as described here is one such scenario:
https://learn.microsoft.com/en-us/previous-versions/technet-magazine/dd547839(v=msdn.10)
As noted in that article, this is known to corrupt the Exchange attributes. This script is able to detect that scenario, and other similar scenarios.
Further, note that such issues cannot be fixed by the script. Using AD Schema Analyzer as described results in an unsupported forest that should be torn down.
"},{"location":"Admin/Update-Engines/","title":"Update-Engines","text":"Download the latest release: Update-Engines.ps1
The UpdateEngines script can be used to download the engine packages to be used by the Forefront Protection engine on Exchange Server and Sharepoint Server products.
"},{"location":"Admin/Update-Engines/#description","title":"Description","text":"Follow the steps given below to manually update the scan engines in Exchange Server. You may need to do so if you experience issues with accessing anti-malware updates online and want to download those definitions to a central location.
The manual update involves running the Update-Engines.ps1
PowerShell script. This script can be changed according to your needs.
The update path, list of engines, and list of platforms can be passed as parameters when the script is executed.
Note:
The script will default the engine update path to https://forefrontdl.microsoft.com/server/scanengineupdate/
. If this endpoint isn't available, you can change the script to use the failover endpoint https://amupdatedl.microsoft.com/server/scanengineupdate/
. If the previous endpoints aren't available, you can use http://amupdatedl.microsoft.com/server/amupdate/
as an alternative download location. By default, all engines will be downloaded for the 64-bit (amd64) platform.
Update-Engines.ps1\n [-EngineDirPath <string>]\n [-UpdatePathUrl <string>]\n [-FailoverPathUrl <string>]\n [-EngineDownloadUrlV2 <string>]\n [-Engines <string[]>]\n [-Platforms <string[]>]\n [-ScriptUpdateOnly <switch>]\n [-SkipVersionCheck <switch>]\n
"},{"location":"Admin/Update-Engines/#steps-to-update-scan-engines","title":"Steps to update scan engines","text":"Create a local directory structure on the computer on which you want to download the scan engine updates.
a. Create a directory. For example, create a directory named ScanEngineUpdates
. This directory must be passed via -EngineDirPath
parameter to the script.
b. Set the NTFS file system and share permissions on the directory so that the target Exchange servers have access to it.
Download the latest version of the script from here
Execute the Update-Engines.ps1
PowerShell script, providing any necessary parameters.
You can now configure the servers to download updates from the directory created in step 1) by using the UNC path of a share name, such as \\\\server_name\\share_name
.
The following syntax uses the directory C:\\ScanEngineUpdates\\
as the root engine's directory to store the update pattern.
Update-Engines.ps1 -EngineDirPath C:\\ScanEngineUpdates\\\n
The following syntax uses the directory C:\\ScanEngineUpdates\\
as the root engine's directory. It also tries to download the latest updates for the Microsoft
engine using the amd64
platform from http://forefrontdl.microsoft.com/server/scanengineupdate/
.
Update-Engines.ps1 -EngineDirPath C:\\ScanEngineUpdates\\ -UpdatePathUrl http://forefrontdl.microsoft.com/server/scanengineupdate/ -Engines Microsoft -Platforms amd64\n
"},{"location":"Admin/Update-Engines/#found-a-bug-or-want-to-update-the-script","title":"Found a bug or want to update the script?","text":"Please open a new work item here or reach out to us via: ExToolsFeedback@microsoft.com
"},{"location":"Calendar/Check-SharingStatus/","title":"Check-SharingStatus","text":"Download the latest release: Check-SharingStatus.ps1
This script runs a variety of PowerShell cmdlets to validate the sharing relationship between two users.
Terminology: Owner - this is the mailbox that owns the Calendar being shared. Receiver - this is the mailbox 'viewing' the owner calendar.
First item is to determine what kind of sharing relationship the users have. Modern Sharing (New Model Sharing) - Recipient gets a replicated copy of the Owners Calendar in their MB Old Model Sharing \u2013 Recipient is granted rights but have so connect to the Owners server to get Calendar information. External Sharing \u2013 Can be New or Old Model sharing, but outside of the Exchange Online Tenant / Organization. Publishing \u2013 Owner publishes a link to their calendar, which clients can pull.
Next you need to determine if the relationship is healthy. Look at the logs and output included in the script.
Last you need to look at how it is working. Generally, you will get Calendar Logs from Owner and Receiver for a copied meeting and check replication times, etc. See CalLogSummaryScript
"},{"location":"Calendar/Get-CalendarDiagnosticObjectsSummary/","title":"Get-CalendarDiagnosticObjectsSummary","text":"Download the latest release: Get-CalendarDiagnosticObjectsSummary.ps1
This script runs the Get-CalendarDiagnosticObjects script and returns a summarized timeline of actions into clear english. To run the script, you will need a valid SMTP Address for a user and a meeting Subject or MeetingID.
The script will display summarized timeline of actions and save the logs returned into a csv file in current directory.
Syntax:
Example to return timeline for a user with MeetingID
.\\Get-CalendarDiagnosticObjectsSummary.ps1 -Identity user@contoso.com -MeetingID 040000008200E00074C5B7101A82E0080000000010E4301F9312D801000000000000000010000000996102014F1D484A8123C16DDBF8603E\n
Example to return timeline for a user with Subject
.\\Get-CalendarDiagnosticObjectsSummary.ps1 -Identity user@contoso.com -Subject Test_OneTime_Meeting_Subject\n
"},{"location":"Calendar/Get-RBASummary/","title":"Get-RBASummary","text":"Download the latest release: Get-RBASummary.ps1
This script runs the Get-CalendarProcessing cmdlet and returns the output with more details in clear English, highlighting the key settings that affect RBA and some of the common errors in configuration.
The script will also validate the mailbox is the correct type for RBA to interact with (via the Get-Mailbox cmdlet) as well as check for any Delegate rules that would interfere with RBA functionality (via the Get-InboxRules cmdlet).
Syntax:
Example to display the setting of room mailbox.
.\\Get-RBASummary.ps1 -Identity Room1@Contoso.com\n\n.\\Get-RBASummary.ps1 -Identity Room1 -Verbose\n
High-level steps for RBA processing:
When the RBA receives a Meeting Request, the first thing that it will do is to determine if the meeting is in or out of policy. How does the RBA do this? The RBA compares the Meeting properties to the Policy Configuration. If all the checks 'pass', then the meeting request is In Policy, otherwise it is Out of Policy.
Whether the meeting is in or out of policy, the RBA will look up the configuration that will tell it what to do with the meeting. By default, all out of policy meetings are rejected, and all in policy meetings are accepted, but there is a larger range of customization that you can do to get the RBA to treat this resource the way you want it to.
If the meeting is accepted, the RBA will Post Process it based on the Post Processing configuration.
"},{"location":"Databases/Analyze-SpaceDump/","title":"Analyze-SpaceDump","text":"Download the latest release: Analyze-SpaceDump.ps1
This script reports the space taken up by various tables based on a database space dump.
"},{"location":"Databases/Analyze-SpaceDump/#usage","title":"Usage","text":"The space dump must be obtained while the database is dismounted, or on a suspended copy if the issue is happening there. To obtain the space dump, use the following syntax:
eseUtil /ms /v > C:\\SpaceDump.txt
Then, feed that file to this script as follows:
.\\Analyze-SpaceDump.ps1 -File C:\\SpaceDump.txt
This script will only work with Exchange 2013 and later space dumps.
"},{"location":"Databases/Compare-MailboxStatistics/","title":"Compare-MailboxStatistics","text":"Download the latest release: Compare-MailboxStatistics.ps1
"},{"location":"Databases/Compare-MailboxStatistics/#usage","title":"Usage","text":"This script compares two sets of mailbox statistics from the same database and highlights mailbox growth that occurred between the two snapshots.
For a growing database, a typical approach would be to start by exporting the statistics for the database:
Get-MailboxStatistics -Database DB1 | Export-CliXML C:\\stats-before.xml\n
After the initial export is obtained, wait until significant growth is observed. That could mean waiting an hour, or a day, depending on the scenario. At that point, compare the stats-before.xml with the live data by using this script as follows:
.\\Compare-MailboxStatistics.ps1 -Before (Import-CliXml C:\\stats-before.xml) -After (Get-MailboxStatistics -Database DB1)\n
This makes it easy to see which mailboxes grew the most.
"},{"location":"Databases/VSSTester/","title":"VSSTester","text":"Download the latest release: VSSTester.ps1
"},{"location":"Databases/VSSTester/#usage","title":"Usage","text":""},{"location":"Databases/VSSTester/#trace-while-using-a-third-party-backup-solution","title":"Trace while using a third-party backup solution","text":".\\VSSTester -TraceOnly -DatabaseName \"Mailbox Database 1637196748\"
Enables tracing of the specified database. The user may then attempt a backup of that database and use Ctrl-C to stop data collection after the backup attempt completes.
"},{"location":"Databases/VSSTester/#trace-a-snapshot-using-the-diskshadow-tool","title":"Trace a snapshot using the DiskShadow tool","text":".\\VSSTester -DiskShadow -DatabaseName \"Mailbox Database 1637196748\" -ExposeSnapshotsOnDriveLetters M, N
Enables tracing and then uses DiskShadow to snapshot the specified database. If the database and logs are on the same drive, the snapshot is exposed as M: drive. If they are on separate drives, the snapshots are exposed as M: and N:. The user is prompted to stop data collection and should typically wait until log truncation has occurred before doing so, so that the truncation is traced.
"},{"location":"Databases/VSSTester/#trace-a-snapshot-using-the-diskshadow-tool-by-volume-instead-of-by-database","title":"Trace a snapshot using the DiskShadow tool by volume instead of by Database","text":".\\VSSTester -DiskShadow -VolumesToBackup D:\\, E:\\ -ExposeSnapshotsOnDriveLetters M, N
Enables tracing and then uses DiskShadow to snapshot the specified volumes. To see a list of available volumes, including mount points, pass an invalid volume name, such as -VolumesToBackup foo
. The error will show the available volumes. Volume names must be typed exactly as shown in that output.
.\\VSSTester -WaitForWriterFailure -DatabaseName \"Mailbox Database 1637196748\"
Enables circular tracing of the specified database, and then polls \"vssadmin list writers\" once per minute. When the writer is no longer present, indicating a failure, tracing is stopped automatically.
"},{"location":"Databases/VSSTester/#more-information","title":"More information","text":"Note that script syntax and output has changed. Syntax and screenshots in the above articles are out of date.
"},{"location":"Databases/VSSTester/#missing-microsoft-exchange-writer","title":"Missing Microsoft Exchange Writer","text":"We have seen a few cases where the Microsoft Exchange Writer will disappear after an unspecified amount of time and restarting the Microsoft Exchange Replication service. Steps on how to resolve this are linked here:
Here are the steps to verify that the local Administrators group is allowed to the COM+ Security on the computer. The script will detect if this is a possibility if we can not see the Exchange Writers and we have the registry settings set that determine this is a possibility.
Download the latest release: ExTRA.ps1
The goal of this script is to replace the ExTRA UI that was included with older versions of Exchange. The script can be run on any machine where a modern browser (Edge/Chrome/Firefox) is set as the default browser. It does not need to be run on an Exchange server. It will not work if Internet Explorer is the default browser.
"},{"location":"Diagnostics/ExTRA/#usage","title":"Usage","text":"Generally, you will want to run this script on a user workstation and use it to generate the EnabledTraces.config file. Then, that file can be copied to the Exchange server, and a logman command can be used to start and stop the ExTRA trace.
The script can be run directly on a server if desired, but remember that IE cannot be the default browser in that case.
To use, download the latest release. Then run the script with no parameters:
.\\ExTRA.ps1\n
The default browser will launch with a tag selection interface. Once the desired tags are selected, click Save and go back to the PowerShell window. You should see some output indicating that the EnabledTraces.config file was saved in the folder. That EnabledTraces.config should be placed at the root of C:\\ on the server being traced.
The output also provides example logman syntax for creating, starting, and stopping the trace.
"},{"location":"Diagnostics/ExchangeLogCollector/","title":"Exchange Log Collector","text":"Download the latest release: ExchangeLogCollector.ps1
This script is intended to collect the Exchange default logging data from the server in a consistent manner to make it easier to troubleshoot an issue when large amounts of data is needed to be collected. You can specify what logs you want to collect by the switches that are available, then the script has logic built in to determine how to collect the data.
"},{"location":"Diagnostics/ExchangeLogCollector/#how-to-run","title":"How to Run","text":"The script must be run as Administrator in PowerShell session on an Exchange Server or Tools box. Supported to run and collected logs against Exchange 2013 and greater. The intent of the script is to collect logs only that you need from X servers quickly without needing to have to manually collect it yourself and label zip them all up for you. If you don't know what logs to collect, it is recommended to use -AllPossibleLogs
.
This script no longer supports collecting logs from Exchange 2010. However, the last release of v2 should still work just fine. You can download that here.
The script is able to collect from the large set of servers while using the Invoke-Command. Prior to executing the main script, we check to make sure the server is up and that we are able to use Invoke-Command against the server. If Invoke-Command works remotely, then we will allow you to attempt to collect the data. You can still utilize the script to collect locally as it used to be able to, if the target OS doesn't allow this.
Prior to collecting the data, we check to make sure that there is at least 10GB of free space at the location of where we are trying to save the data of the target server. The script will continue to keep track of all the logs and data that is being copied over and will stop if we have less than 10GB of free space.
You are able to use a config file to load up all the parameters you wish to choose and the servers you wish to run the script against. Just create a file called ExchangeLogCollector.ps1.json
and place at the same location as the script. Then provide the switches you would like to use in the file like so:
{\n \"Servers\": [\n \"ADT-E16A\",\n \"ADT-E16B\",\n \"ADT-E16C\"\n ],\n \"FilePath\": \"C:\\\\MS_Logs\",\n \"IISLogs\": true,\n \"AppSysLogsToXml\": false,\n \"ScriptDebug\": true\n}\n
NOTE: It is import that you use \\\\
for the file path otherwise the settings will fail to load.
This cmdlet will collect all default logs of the local Exchange Server and store them in the default location of \"C:\\MS_Logs_Collection\"
.\\ExchangeLogCollector.ps1 -AllPossibleLogs\n
This cmdlet will collect all relevant data regarding database fail overs from server EXCH1 and EXCH2 and store them at Z:\\Data\\Logs. Note: at the end of the collection, the script will copy over the data to the local host execution server to make data collection even easier.
.\\ExchangeLogCollector.ps1 -DatabaseFailoverIssue -Servers EXCH1,EXCH2 -FilePath Z:\\Data\\Logs\n
This cmdlet will collect all relevant data regarding IIS Logs (within the last 3 days by default) and all RPC type logs from the servers EXCH1 and EXCH2 and store them at the default location of \"C:\\MS_Logs_Collection\"
.\\ExchangeLogCollector.ps1 -Servers EXCH1,EXCH2 -IISLogs -RPCLogs\n
This cmdlet will collect all relevant data regarding Message Tracking Logs and Protocol Logs for the past 3 hours from the servers EXCH1 and EXCH2 and store them at the default location of \"C:\\MS_Logs_Collection\"
.\\ExchangeLogCollector.ps1 -Servers EXCH1,EXCH2 -MessageTrackingLogs -ProtocolLogs -LogAge \"03:00:00\"\n
"},{"location":"Diagnostics/ExchangeLogCollector/#parameters","title":"Parameters","text":"Parameter Description FilePath The Location of where you would like the data to be copied over to. This location must be the same and accessible on all servers if you use the Servers parameter. Default value: C:\\MS_Logs_Collection Servers An array of servers that you would like to collect data from. AcceptedRemoteDomain Enable to collect Get-AcceptedDomain
and Get-RemoteDomain
. ADDriverLogs Enable to collect AD Driver Logs. Location: V15\\Logging\\ADDriver
AppSysLogs Collects the Windows Event Application, System, and MSExchange Management Logs. Default value $true
AppSysLogsToXml Collects the Windows Event Application and System and saves them out to XML. The time range only is from the time the script run and the value set on LogAge
. Default value: $true
AutoDLogs Enable to collect AutoDiscover Logs. Location: V15\\Logging\\Autodiscover
and V15\\Logging\\HttpProxy\\Autodiscover
CollectFailoverMetrics Enable to run the CollectOverMetrics.ps1
script against the DAG. Only able to be run on an Exchange tools box or an Exchange Server. DAGInformation Enable to collect the DAG Information from all different DAGs that are in the list of servers. DailyPerformanceLogs Enable to collect Daily Performance Logs. Default Location: V15\\Logging\\Diagnostics\\DailyPerformanceLogs
DefaultTransportLogging Enables the following switches and their logs to be collected. AcceptedRemoteDomain
, FrontEndConnectivityLogs
, FrontEndProtocolLogs
, HubConnectivityLogs
, MailboxConnectivityLogs
, MailboxDeliveryThrottlingLogs
, MessageTrackingLogs
, PipelineTracingLogs
, QueueInformation
, ReceiveConnectors
, SendConnectors
, TransportConfig
, TransportRoutingTableLogs
, and TransportRules
EASLogs Enable to collect Exchange Active Sync Logging. Location: V15\\Logging\\HttpProxy\\Eas
ECPLogs Enable to collect ECP Logs. Location: V15\\Logging\\ECP
and V15\\Logging\\HttpProxy\\Ecp
EWSLogs Enable to collect EWS Logs. Location: V15\\Logging\\HttpProxy\\Ews
and V15\\Logging\\Ews
ExchangeServerInformation Enable to collect Exchange Information like Get-ExchangeServer, Get-MailboxServer, etc... This is also collected when -ServerInformation
is also enabled. ExMon Enable to collect ExMon data from the server. ExPerfWiz Enable to collect ExPerfWiz data if found. FrontEndConnectivityLogs Enable to collect the connectivity logging on the FE. Location: (Get-FrontendTransportService $server).ConnectivityLogPath
FrontEndProtocolLogs Enable to collect the protocol logging on the FE. Location: (Get-FrontendTransportService $server).ReceiveProtocolLogPath
and (Get-FrontendTransportService $server).SendProtocolLogPath
GetVDirs Enable to collect the Virtual Directories of the environment. HighAvailabilityLogs Enable to collect High Availability Logs. Windows Event Logs like: Microsoft-Exchange-HighAvailability
, Microsoft-Exchange-MailboxDatabaseFailureItems
, and Microsoft-Windows-FailoverClustering
HubConnectivityLogs Enable to collect the Hub connectivity logging. Location: (Get-TransportService $server).ConnectivityLogPath
HubProtocolLogs Enable to collect the protocol logging. Location: (Get-TransportService $server).ReceiveProtocolLogPath
and (Get-TransportService $server).SendProtocolLogPath
IISLogs Enable to collect IIS Logs and HTTPErr Logs from the Exchange Server. Default Location: C:\\InetPub\\logs\\LogFiles\\W3SVC1
, C:\\InetPub\\logs\\LogFiles\\W3SVC2
, and C:\\Windows\\System32\\LogFiles\\HTTPERR
. IISlogs do not collect all logs on CollectAllLogsBasedOnLogAge:$false, just works based on log age. ImapLogs Enable to collect IMAP logging. Location: (Get-ImapSettings -Server $server).LogFileLocation
MailboxAssistantsLogs Enable to collect Mailbox Assistants logging. Location: V15\\Logging\\MailboxAssistantsLog
, V15\\Logging\\MailboxAssistantsSlaReportLog
, and V15\\Logging\\MailboxAssistantsDatabaseSlaLog
MailboxConnectivityLogs Enable to collect the connectivity logging on the mailbox server. Location: (Get-MailboxTransportService $server).ConnectivityLogPath
MailboxDeliveryThrottlingLogs Enable to collect the mailbox delivery throttling logs on the server. Location: (Get-MailboxTransportService $server).MailboxDeliveryThrottlingLogPath
MailboxProtocolLogs Enable to collect protocol logging on the mailbox server. Location: (Get-MailboxTransportService $server).ReceiveProtocolLogPath
and (Get-MailboxTransportService $server).SendProtocolLogPath
ManagedAvailabilityLogs Enable to collect the Managed Availability Logs. Location: V15\\Logging\\Monitoring
and Windows Event logs like Microsoft-Exchange-ManagedAvailability
MapiLogs Enable to collect MAPI Logs. Location: V15\\Logging\\MAPI Client Access
, V15\\Logging\\MapiHttp\\Mailbox
, and V15\\Logging\\HttpProxy\\Mapi
MessageTrackingLogs Enable to collect the Message Tracking Logs. Location: (Get-TransportService $server).MessageTrackingLogPath
MitigationService Enable to collect the Mitigation Service logs. Location: V15\\Logging\\MitigationService
OABLogs Enable to collect OAB Logs. Location: V15\\Logging\\HttpProxy\\OAB
, V15\\Logging\\OABGeneratorLog
, V15\\Logging\\OABGeneratorSimpleLog
, and V15\\Logging\\MAPI AddressBook Service
OrganizationConfig Enable to collect the Organization Configuration from the environment. OWALogs Enable to collect OWA Logs. Location: V15\\Logging\\OWA
, Logging\\HttpProxy\\OwaCalendar
, and V15\\Logging\\HttpProxy\\Owa
PipelineTracingLogs Enable to collect the Pipeline Tracing Logs. Location (Get-TransportService $server).PipelineTracingPath
, and (Get-MailboxTransportService $server).PipelineTracingPath
PopLogs Enable to collect POP logging. Location: (Get-PopSettings -Server $server).LogFileLocation
PowerShellLogs Enable to collect the PowerShell Logs. Location: V15\\Logging\\HttpProxy\\PowerShell
QueueInformation Enable to collect the historical queue information. Location: (Get-TransportService $server).QueueLogPath
ReceiveConnectors Enable to collect the Receive Connector information from the server. RPCLogs Enable to collect RPC Logs. Location: V15\\Logging\\RPC Client Access
, V15\\Logging\\HttpProxy\\RpcHttp
, and V15\\Logging\\RpcHttp
SearchLogs Enable to collect Search Logs. Location: V15\\Bin\\Search\\Ceres\\Diagnostics\\Logs
, V15\\Bin\\Search\\Ceres\\Diagnostics\\ETLTraces
, V15\\Logging\\Search
. On 2019 only we also include V15\\Logging\\BigFunnelMetricsCollectionAssistant
, V15\\Logging\\BigFunnelQueryParityAssistant
, and V15\\Logging\\BigFunnelRetryFeederTimeBasedAssistant
SendConnectors Enable to collect the send connector information from the environment. ServerInformation Enable to collect general server information. TransportAgentLogs Enable to collect the Agent Logs. Location: (Get-TransportService $server).AgentLogPath
, (Get-FrontendTransportService $server).AgentLogPath
, (Get-MailboxTransportService $server).MailboxSubmissionAgentLogPath
, and (Get-MailboxTransportService $server).MailboxDeliveryAgentLogPath
TransportConfig Enable to collect the Transport Configuration files from the Server and Get-TransportConfig
from the org. Files: EdgeTransport.exe.config
, MSExchangeFrontEndTransport.exe.config
, MSExchangeDelivery.exe.config
, and MSExchangeSubmission.exe.config
TransportRoutingTableLogs Enable to collect the Routing Table Logs. Location: (Get-TransportService $server).RoutingTableLogPath
, (Get-FrontendTransportService $server).RoutingTableLogPath
, and (Get-MailboxTransportService $server).RoutingTableLogPath
TransportRules Enable to collect Get-TransportRule
. WindowsSecurityLogs Enable to collect the Windows Security Logs. Default Location: 'C:\\Windows\\System32\\WinEvt\\Logs\\Security.evtx'
AllPossibleLogs Enables the collection of all default logging collection on the Server. CollectAllLogsBasedOnLogAge Boolean to determine if you collect all the logs based off the log's age or all the logs in that directory. Default value $true
ConnectivityLogs Enables the following switches and their logs to be collected: FrontEndConnectivityLogs
, HubConnectivityLogs
, and MailboxConnectivityLogs
DatabaseFailoverIssue Enables the following switches and their logs to be collected. DAGInformation
, DailyPerformanceLogs
, ExchangeServerInformation
, ExPerfWiz
, HighAvailabilityLogs
, ManagedAvailabilityLogs
, and ServerInformation
. DaysWorth The number of days to go back to be included int the time span for log collection. Default value: 3 HoursWorth The number of hours to go back to be included in the time span for the log collection. Default Value 0. LogStartDate Set the starting time for the log collection (DateTime). LogEndDate Set the ending time for the log collection (DateTime). DisableConfigImport Enable to not import the ExchangeLogCollector.ps1.json
file if it exists. ExMonLogmanName A list of names that we want to collect for ExMon data. The default name is ExMon_Trace
. ExPerfWizLogmanName A list of names that we want to collect performance data logs from. The default names are Exchange_PerfWiz
, ExPerfWiz
, and SimplePerf
. (For both styles of ExPerfWiz) LogAge A Time Span value to use instead of the DaysWorth and HoursWorth parameters. Default Value: 3.00:00:00 OutlookConnectivityIssues Enables the following switches and their logs to be collected: AutoDLogs
, DailyPerformanceLogs
, EWSLogs
, ExPerfWiz
, IISLogs
, MAPILogs
, RPCLogs
, and ServerInformation
PerformanceIssues Enables the following switches and their logs to be collected: DailyPerformanceLogs
, ExPerfWiz
, and ManagedAvailabilityLogs
PerformanceMailFlowIssues Enables the following switches and their logs to be collected: DailyPerformanceLogs
, ExPerfWiz
, MessageTrackingLogs
, QueueInformation
, and TransportConfig
ProtocolLogs Enables the following switches and their logs to be collected: FrontEndProtocolLogs
, HubProtocolLogs
, and MailboxProtocolLogs
ScriptDebug Enable to display all the verbose lines in the script. SkipEndCopyOver If the Servers parameter is used, by default we will attempt to collect all the data back over to the local server after all the data was collected on each server."},{"location":"Diagnostics/ManagedAvailabilityTroubleshooter/","title":"ManagedAvailabilityTroubleshooter","text":"Download the latest release: ManagedAvailabilityTroubleshooter.ps1
"},{"location":"Diagnostics/Test-ExchAVExclusions/","title":"Test-ExchAVExclusions","text":"Download the latest release: Test-ExchAVExclusions.ps1
Assists with testing Exchange Servers to determine if AV Exclusions have been properly set according to our documentation.
AV Exclusions Exchange 2016/2019
AV Exclusions Exchange 2013
"},{"location":"Diagnostics/Test-ExchAVExclusions/#usage","title":"Usage","text":"Writes an EICAR test file to all paths specified in our AV Exclusions documentation and verifies all extensions in the documentation in a temporary folder.
If the file is removed then the path is not properly excluded from AV Scanning. IF the file is not removed then it should be properly excluded.
Once the files are created it will wait 5 minutes for AV to \"see\" and remove the file.
After finishing testing directories it will test Exchange Processes. Pulls all Exchange processes and their modules. Excludes known modules and reports all Non-Default modules.
Non-Default modules should be reviewed to ensure they are expected. AV Modules loaded into Exchange Processes indicate that AV Process Exclusions are NOT properly configured.
... .\\Test-ExchAVExclusions.ps1 ...
"},{"location":"Diagnostics/Test-ExchAVExclusions/#understanding-the-output","title":"Understanding the Output","text":""},{"location":"Diagnostics/Test-ExchAVExclusions/#file-output","title":"File Output","text":"Review the BadExclusions.txt file to see any file paths were identified as being scanned by AV. Work with the AV Vendor to determine the best way to exclude these file paths according to our documentation:
AV Exclusions Exchange 2016/2019
"},{"location":"Diagnostics/Test-ExchAVExclusions/#process-output","title":"Process Output","text":"Review NonDefaultModules.txt to determine if any Non-Default modules are loaded into Exchange processes. The output should have sufficient information to identity the source of the flagged modules.
[FAIL] - PROCESS: ExchangeTransport MODULE: scanner.dll COMPANY: Contoso Security LTT.
If the Module is from an AV or Security software vendor it is a strong indication that process exclusions are not properly configured on the Exchange server. Please work with the vendor to ensure that they are properly configured according to:
AV Exclusions Exchange 2016/2019
AV Exclusions Update
"},{"location":"Diagnostics/Test-ExchAVExclusions/#parameters","title":"Parameters","text":"Parameter Description WaitingTimeForAVAnalysisInMinutes Set the waiting time for AV to analyze the EICAR files. Default is 5 minutes. Recurse Places an EICAR file in all SubFolders as well as the root. OpenLog Opens the script log file. SkipVersionCheck Skip script version verification. ScriptUpdateOnly Just update script version to latest one."},{"location":"Diagnostics/Test-ExchAVExclusions/#outputs","title":"Outputs","text":"Log file: $PSScriptRoot\\ExchAvExclusions.log
List of Folders, extensions Scanned by AV and List of Non-Default Processes: $PSScriptRoot\\BadExclusions.txt
"},{"location":"Diagnostics/FindFrontEndActivity/FindFrontEndActivity/","title":"FindFrontEndActivity","text":"Download the latest release: FindFrontEndActivity.ps1
"},{"location":"Diagnostics/FindFrontEndActivity/FindFrontEndActivity/#synopsis","title":"Synopsis","text":"Find HttpProxy protocol activity for one or more users.
"},{"location":"Diagnostics/FindFrontEndActivity/FindFrontEndActivity/#syntax","title":"Syntax","text":".\\FindFrontEndActivity.ps1 -ServerName <String[]> -SamAccountName <String[]> [-LatencyThreshold <Int32>] [-Protocol <String[]>] [-IncludeNonExecutes] [-Quiet] [-TimeSpan <TimeSpan>] [<CommonParameters>]\n\n.\\FindFrontEndActivity.ps1 -ServerName <String[]> -SamAccountName <String[]> [-LatencyThreshold <Int32>] [-Protocol <String[]>] [-IncludeNonExecutes] [-Quiet] -StartTime <DateTime> -EndTime <DateTime> [<CommonParameters>]\n
"},{"location":"Diagnostics/FindFrontEndActivity/FindFrontEndActivity/#quick-start-examples","title":"Quick Start Examples","text":"[PS] C:\\>Get-ExchangeServer | .\\FindFrontEndActivity.ps1 -SamAccountName \"john.doe\" | ft\n\nDateTime AuthenticatedUser UrlStem ServerHostName TargetServer TotalRequestTime\n-------- ----------------- ------- -------------- ------------ ----------------\n2023-02-11T15:59:35.174Z contoso\\john.doe /mapi/emsmdb/ EXCH1 exch1.contoso.local 2214\n
[PS] C:\\>Get-ExchangeServer | .\\FindFrontEndActivity.ps1 -SamAccountName \"john.doe\" -LatencyThreshold 100 | ft\n\nDateTime AuthenticatedUser UrlStem ServerHostName TargetServer TotalRequestTime\n-------- ----------------- ------- -------------- ------------ ----------------\n2023-02-11T15:59:29.898Z contoso\\john.doe /mapi/emsmdb/ EXCH1 exch1.contoso.local 505\n2023-02-11T15:59:31.560Z contoso\\john.doe /mapi/emsmdb/ EXCH1 exch1.contoso.local 403\n2023-02-11T15:59:35.174Z contoso\\john.doe /mapi/emsmdb/ EXCH1 exch1.contoso.local 2214\n2023-02-11T15:59:35.488Z contoso\\john.doe /mapi/emsmdb/ EXCH1 exch1.contoso.local 161\n2023-02-11T15:59:38.133Z contoso\\john.doe /mapi/emsmdb/ EXCH1 exch1.contoso.local 399\n
[PS] C:\\>Get-ExchangeServer | .\\FindFrontEndActivity.ps1 -SamAccountName \"john.doe\" -Protocol \"ews\", \"mapi\" | ft\n\nDateTime AuthenticatedUser UrlStem ServerHostName TargetServer TotalRequestTime\n-------- ----------------- ------- -------------- ------------ ----------------\n2023-02-11T15:10:10.643Z contoso\\john.doe /EWS/Exchange.asmx EXCH1 exch1.contoso.local 1800019\n2023-02-11T15:40:44.254Z contoso\\john.doe /EWS/Exchange.asmx EXCH1 exch1.contoso.local 1800028\n2023-02-11T15:59:35.174Z contoso\\john.doe /mapi/emsmdb/ EXCH1 exch1.contoso.local 2214\n
Note the difference between -Quiet mode and the default:
[PS] C:\\>Get-ExchangeServer | .\\FindFrontEndActivity.ps1 -SamAccountName \"john.doe\" -Quiet\nEXCH1\nEXCH3\n[PS] C:\\>\n[PS] C:\\># Notice how we returned two servers when using -Quiet.\n[PS] C:\\>\n[PS] C:\\>Get-ExchangeServer | .\\FindFrontEndActivity.ps1 -SamAccountName \"john.doe\" | ft\n\nDateTime AuthenticatedUser UrlStem ServerHostName TargetServer TotalRequestTime\n-------- ----------------- ------- -------------- ------------ ----------------\n2023-02-11T16:25:14.508Z contoso\\john.doe /mapi/emsmdb/ EXCH1 exch1.contoso.local 1182\n\n\n[PS] C:\\># But only one in the default mode. This is because the default is intended\n[PS] C:\\># to look for calls that are slow and are Execute calls. To see everything,\n[PS] C:\\># we need to remove the latency filter and include non-execute activity,\n[PS] C:\\># but this will return a lot of noise.\n[PS] C:\\>\n[PS] C:\\>Get-ExchangeServer | .\\FindFrontEndActivity.ps1 -SamAccountName \"john.doe\" -LatencyThreshold 0 -IncludeNonExecutes | ft\n\nDateTime AuthenticatedUser UrlStem ServerHostName TargetServer TotalRequestTime\n-------- ----------------- ------- -------------- ------------ ----------------\n2023-02-11T16:00:07.619Z contoso\\john.doe /mapi/emsmdb/ EXCH3 exch1.contoso.local 17\n2023-02-11T16:01:10.555Z contoso\\john.doe /mapi/nspi/ EXCH1 exch1.contoso.local 22\n2023-02-11T16:05:11.132Z contoso\\john.doe /mapi/emsmdb/ EXCH1 exch1.contoso.local 659066\n2023-02-11T16:05:12.101Z contoso\\john.doe /mapi/nspi/ EXCH1 exch1.contoso.local 21\n...\n
To see all details, use fl *
:
[PS] C:\\>Get-ExchangeServer | .\\FindFrontEndActivity.ps1 -SamAccountName \"john.doe\" | fl *\n\n\nDateTime : 2023-02-11T16:25:14.508Z\nRequestId : 0aa7958e-c59a-4f0a-903f-ebbd6ed93c9a\nMajorVersion : 15\nMinorVersion : 2\nBuildVersion : 1118\n...\n
"},{"location":"Diagnostics/FindFrontEndActivity/FindFrontEndActivity/#description","title":"Description","text":"When an Exchange client experiences issues, the HttpProxy logs are often the starting point for determining whether the issue is with the client, the network, or the server. However, since an Exchange environment may have dozens of front-end servers, it can be difficult to find the relevant logs for a given user.
This script is designed to search the logs of all Exchange servers in parallel to quickly find the HttpProxy logs related to specified users.
The default mode of the script is intended for finding slow MAPI calls from Outlook clients. The -Protocol
switch can be used to search more protocols, while specifying -LatencyThreshold
allows the admin to filter more aggressively or remove the latency filter entirely. Running in -Quiet
mode skips the filtering and just reports any servers that have the specified users in the HttpProxy logs for the specified protocols. See the parameters and examples for more information.
-ServerName <String[]>\n The name of one or more Exchange servers to search. An easy way to search all Exchange\n servers in the forest is to simply pipe Get-ExchangeServer to the script.\n\n Required? true\n Position? named\n Default value\n Accept pipeline input? true (ByValue, ByPropertyName)\n Accept wildcard characters? false\n\n-SamAccountName <String[]>\n The samAccountNames of one or more users to search for.\n\n Required? true\n Position? named\n Default value\n Accept pipeline input? false\n Accept wildcard characters? false\n\n-LatencyThreshold <Int32>\n The minimum latency (in milliseconds) to search for. This is useful for filtering out\n noise from the logs. (Default: 1000). This parameter has no effect when -Quiet is used.\n\n Required? false\n Position? named\n Default value 1000\n Accept pipeline input? false\n Accept wildcard characters? false\n\n-Protocol <String[]>\n The protocols to search. Valid values are: Autodiscover, EAS, ECP, EWS, MAPI, OWA, PowerShell,\n RpcHttp. (Default: MAPI)\n\n Required? false\n Position? named\n Default value @('MAPI')\n Accept pipeline input? false\n Accept wildcard characters? false\n\n-IncludeNonExecutes [<SwitchParameter>]\n By default, NotificationWaits from the MAPI logs are not included, because these are slow\n by design. Specify this switch to include them.\n\n Required? false\n Position? named\n Default value False\n Accept pipeline input? false\n Accept wildcard characters? false\n\n-Quiet [<SwitchParameter>]\n This switch causes the script to only report the server names rather than the full log\n entries. This may be somewhat faster. However, there is no filtering for LatencyThreshold\n and NotificationWait when this option is used.\n\n Required? false\n Position? named\n Default value False\n Accept pipeline input? false\n Accept wildcard characters? false\n\n-TimeSpan <TimeSpan>\n Specify how far back to search the logs. This is a TimeSpan value, such as \"01:00\" for the\n last hour or \"00:30\" for the last 30 minutes. (Default: 15 minutes). Use this parameter to\n search the most recent logs. Use StartTime and EndTime to search older logs.\n\n Required? false\n Position? named\n Default value (New-TimeSpan -Minutes 15)\n Accept pipeline input? false\n Accept wildcard characters? false\n\n-StartTime <DateTime>\n Logs older than this time are not searched. This is a DateTime value, such as (Get-Date).AddDays(-1)\n or \"2023-02-11 08:00\". Use this parameter to search old logs. Use -TimeSpan to search the\n most recent logs.\n\n Required? true\n Position? named\n Default value\n Accept pipeline input? false\n Accept wildcard characters? false\n\n-EndTime <DateTime>\n Logs newer than this time are not searched. This is a DateTime value, such as (Get-Date).AddDays(-1)\n or \"2023-02-11 09:00\". Use this parameter to search old logs. Use -TimeSpan to search the\n most recent logs.\n\n Required? true\n Position? named\n Default value\n Accept pipeline input? false\n Accept wildcard characters? false\n\n<CommonParameters>\n This cmdlet supports the common parameters: Verbose, Debug,\n ErrorAction, ErrorVariable, WarningAction, WarningVariable,\n OutBuffer, PipelineVariable, and OutVariable. For more information, see\n about_CommonParameters (https://go.microsoft.com/fwlink/?LinkID=113216).\n
"},{"location":"Diagnostics/FindFrontEndActivity/FindFrontEndActivity/#example-1","title":"Example 1","text":"Get-ExchangeServer | .\\FindFrontEndActivity.ps1 -SamAccountName \"user1\", \"user2\" | ft\n
Show any MAPI HttpProxy activity that took more than 1 second for user1 or user2 within the last 15 minutes on all Exchange servers in the forest."},{"location":"Diagnostics/FindFrontEndActivity/FindFrontEndActivity/#example-2","title":"Example 2","text":"Get-ExchangeServer | .\\FindFrontEndActivity.ps1 -SamAccountName \"user1\", \"user2\" -Quiet\n
Show only the server names where user1 or user2 are found in the MAPI HttpProxy logs within the last 15 minutes."},{"location":"Diagnostics/FindFrontEndActivity/FindFrontEndActivity/#example-3","title":"Example 3","text":"Get-ExchangeServer | .\\FindFrontEndActivity.ps1 -SamAccountName \"user1\", \"user2\" -Protocol \"ews\", \"mapi\" -LatencyThreshold 100 -TimeSpan \"00:30\"\n
Show any EWS or MAPI HttpProxy activity that took more than 100 milliseconds for user1 or user2 within the last 30 minutes on all Exchange servers in the forest."},{"location":"Diagnostics/HealthChecker/","title":"HealthChecker","text":"Download the latest release: HealthChecker.ps1
The Exchange Server Health Checker script helps detect common configuration issues that are known to cause performance issues and other long running issues that are caused by a simple configuration change within an Exchange Environment. It also helps collect useful information of your server to help speed up the process of common information gathering of your server.
"},{"location":"Diagnostics/HealthChecker/#requirements","title":"Requirements","text":""},{"location":"Diagnostics/HealthChecker/#supported-exchange-server-versions","title":"Supported Exchange Server Versions:","text":"The script can be used to validate the configuration of the following Exchange Server versions: - Exchange Server 2013 - Exchange Server 2016 - Exchange Server 2019
"},{"location":"Diagnostics/HealthChecker/#required-permissions","title":"Required Permissions:","text":"Please make sure that the account used is a member of the Local Administrator
group. This should be fulfilled on Exchange servers by being a member of the Organization Management
group. However, if the group membership was adjusted or in case the script is executed on a non-Exchange system like a management server, you need to add your account to the Local Administrator
group. You also need to be a member of the following groups:
DCCoreRatio
parameter)HealthChecker.ps1\n [-Server <string[]>]\n [-OutputFilePath <string>]\n [-SkipVersionCheck]\n [-SaveDebugLog]\nHealthChecker.ps1\n [-Server <string[]>]\n [-MailboxReport]\n [-OutputFilePath <string>]\n [-SkipVersionCheck]\n [-SaveDebugLog]\nHealthChecker.ps1\n [-LoadBalancingReport]\n [-ServerList <string[]>]\n [-SiteName <string>]\n [-OutputFilePath <string>]\n [-SkipVersionCheck]\n [-SaveDebugLog]\nHealthChecker.ps1\n [-BuildHtmlServersReport]\n [-XMLDirectoryPath <string>]\n [-HtmlReportFile <string>]\n [-OutputFilePath <string>]\n [-SkipVersionCheck]\n [-SaveDebugLog]\nHealthChecker.ps1\n [-AnalyzeDataOnly]\n [-XMLDirectoryPath <string>]\n [-HtmlReportFile <string>]\n [-OutputFilePath <string>]\n [-SkipVersionCheck]\n [-SaveDebugLog]\nHealthChecker.ps1\n [-DCCoreRatio]\n [-OutputFilePath <string>]\n [-SkipVersionCheck]\n [-SaveDebugLog]\nHealthChecker.ps1\n [-ScriptUpdateOnly]\n [-OutputFilePath <string>]\n [-SaveDebugLog]\nHealthChecker.ps1\n [-VulnerabilityReport]\n [-OutputFilePath <string>]\n [-SkipVersionCheck]\n [-SaveDebugLog]\n
"},{"location":"Diagnostics/HealthChecker/#how-to-run","title":"How To Run","text":"This script must be run as Administrator in Exchange Management Shell on an Exchange Server. You can provide no parameters and the script will just run against the local server and provide the detail output of the configuration of the server.
"},{"location":"Diagnostics/HealthChecker/#examples","title":"Examples:","text":"This cmdlet with run Health Checker Script by default and run against the local server.
PS C:\\> .\\HealthChecker.ps1\n
This cmdlet will run the Health Checker Script against the specified server.
PS C:\\> .\\HealthChecker.ps1 -Server EXCH1\n
This cmdlet will run the Health Checker Script against a list of servers.
PS C:\\> .\\HealthChecker.ps1 -Server EXCH1,EXCH2,EXCH3\n
This cmdlet will build the HTML report for all the XML files located in the same location as the Health Checker Script.
PS C:\\> .\\HealthChecker.ps1 -BuildHtmlServersReport\n
This cmdlet will build the HTML report for all the XML files located in the directory specified in the XMLDirectoryPath Parameter.
PS C:\\> .\\HealthChecker.ps1 -BuildHtmlServersReport -XMLDirectoryPath C:\\Location\n
This cmdlet will run the Health Checker Load Balancing Report for all the Exchange 2013+ CAS (Front End connections only) and MBX servers (BackEnd connections) in the Organization.
PS C:\\> .\\HealthChecker.ps1 -LoadBalancingReport\n
This cmdlet will run the Health Checker Load Balancing Report for these Servers EXCH1, EXCH2, and EXCH3 CAS (Front End connections) and MBX (BackEnd Connections)
PS C:\\> .\\HealthChecker.ps1 -LoadBalancingReport -ServerList EXCH1,EXCH2,EXCH3\n
This cmdlet will run the Health Checker Load Balancing Report for the Exchange 2013+ servers in the site SiteA.
PS C:\\> .\\HealthChecker.ps1 -LoadBalancingReport -SiteName SiteA\n
This cmdlet will run the Health Checker Mailbox Report against the Server EXCH1
PS C:\\> .\\HealthChecker.ps1 -MailboxReport -Server EXCH1\n
This cmdlet will run the Health Checker against all your Exchange Servers, then run the HTML report and open it.
PS C:\\> Get-ExchangeServer | ?{$_.AdminDisplayVersion -Match \"^Version 15\"} | .\\HealthChecker.ps1; .\\HealthChecker.ps1 -BuildHtmlServersReport; .\\ExchangeAllServersReport.html\n
This cmdlet will run Health Checker Vulnerability Report feature against all your Exchange Servers. Then Export out the data to a json file.
PS C:\\> .\\HealthChecker.ps1 -VulnerabilityReport\n
"},{"location":"Diagnostics/HealthChecker/#parameters","title":"Parameters","text":"Parameter Description Server The server that you would like to run the Health Checker Script against. Parameter not valid with -BuildHTMLServersReport or LoadBalancingReport. Default is the localhost. OutputFilePath The output location for the log files that the script produces. Default is the current directory. MailboxReport Produces the Mailbox Report for the server provided. LoadBalancingReport Runs the Load Balancing Report for the Script ServerList Used in combination with the LoadBalancingReport switch for letting the script to know which servers to run against. SiteName Used in combination with the LoadBalancingReport switch for letting the script to know which servers to run against in the site. XMLDirectoryPath Used in combination with BuildHtmlServersReport switch for the location of the HealthChecker XML files for servers which you want to be included in the report. Default location is the current directory. BuildHtmlServersReport Switch to enable the script to build the HTML report for all the servers XML results in the XMLDirectoryPath location. HtmlReportFile Name of the HTML output file from the BuildHtmlServersReport. Default is ExchangeAllServersReport.html DCCoreRatio Gathers the Exchange to DC/GC Core ratio and displays the results in the current site that the script is running in. AnalyzeDataOnly Switch to analyze the existing HealthChecker XML files. The results are displayed on the screen and an HTML report is generated. VulnerabilityReport Switch to collect the Vulnerability Information for all the servers in the environment and export it out to json file. SkipVersionCheck No version check is performed when this switch is used. SaveDebugLog The debug log is kept even if the script is executed successfully. ScriptUpdateOnly Switch to check for the latest version of the script and perform an auto update if a newer version was found. Can be run on any machine with internet connectivity. No elevated permissions or EMS are required."},{"location":"Diagnostics/HealthChecker/ADSiteCount/","title":"AD Site Count Check","text":"In large environments that contains a lot of sites, can cause a performance issue with Exchange. In particular Autodiscover app pool will peg the CPU at 4-hour intervals when there are many AD sites.
It is recommended to reduce the number of AD Sites within the environment to address this issue. However, there is a workaround that would prevent the issue from occurring every 4-hours and just every 24-hours.
In the %ExchangeInstallPath%\\Bin\\Microsoft.Exchange.Directory.TopologyService.exe.config
file, change the ExchangeTopologyCacheLifetime
value to be 1.00:00:00,00:20:00
instead to have the cache lifetime increase from 4-hours to 24-hours. It is not recommended to go beyond 24-hours.
Included in HTML Report?
Yes
Additional resources:
Original Issue
"},{"location":"Diagnostics/HealthChecker/AMSIIntegration/","title":"AMSI Check","text":"The Windows AntiMalware Scan Interface (AMSI) is a versatile standard that allows applications and services to integrate with any AntiMalware product present on a machine. AMSI is vendor agnostic and designed to allow for the most common malware scanning and protection techniques provided by today's products to be integrated into applications.
It only scans the HTTP protocol, and is not meant to be a replacement to existing server-level or message hygiene protections.
AMSI integration is available on the following Operating System / Exchange Server version combinations: - Windows Server 2016, or higher - Exchange Server 2016 CU21, or higher - Exchange Server 2019 CU10, or higher - AMSI is not available on Edge Transport Servers
If you use Microsoft Defender, AV engine version at or higher than 1.1.18300.4 is also required. Alternatively, a compatible AMSI capable third-party AV provider.
This check verifies if an override exists which disables the AMSI integration with Exchange Server. It does that, by running the following query:
Get-SettingOverride | Where-Object { ($_.ComponentName -eq \"Cafe\") -and ($_.SectionName -eq \"HttpRequestFiltering\") }
Included in HTML Report?
Yes
Additional resources:
Released: June 2021 Quarterly Exchange Updates
More about AMSI integration with Exchange Server
"},{"location":"Diagnostics/HealthChecker/AuthCertificateCheck/","title":"Auth Certificate Check","text":""},{"location":"Diagnostics/HealthChecker/AuthCertificateCheck/#description","title":"Description","text":"The Auth Configuration and Auth Certificate are used by Microsoft Exchange server to enable server-to-server authentication using the Open Authorization (OAuth)
protocol standard. The Auth Certificate is also used by several Exchange Server security features which makes it important to be valid and available on all servers (except Edge Transport Servers) within the organization.
An invalid Auth Certificate can lead to these and other issues:
Access to OWA or ECP isn't working
Management of your Exchange servers via Exchange Management Shell isn't working as expected
The HealthChecker script validates multiple configurations which are having a dependency to the Auth Certificate. The script will show you if the Auth Certificate which is configured, was found on the server against which the script is currently running. It will also highlight if the certificate has been expired.
HealthChecker will display the certificate, which is configured as the next Auth Certificate (if there is one) and the effective date from which it becomes available for use by the AuthAdmin servicelet (Auth Certificate rotation to ensure a smooth transition to a new one).
Note: It's required to run the Hybrid Configuration Wizard (HCW), if you are running an Exchange Server hybrid configuration and the primary Auth Certificate has been replaced by a new one.
"},{"location":"Diagnostics/HealthChecker/AuthCertificateCheck/#included-in-html-report","title":"Included in HTML Report?","text":"Yes
"},{"location":"Diagnostics/HealthChecker/AuthCertificateCheck/#additional-resources","title":"Additional resources","text":"Maintain (rotate) the Exchange Server Auth Certificate
Replace the Auth Certificate if it has already expired or isn't available
Exchange OAuth authentication couldn't find the authorization certificate with thumbprint error when running Hybrid Configuration
MonitorExchangeAuthCertificate.ps1 script
"},{"location":"Diagnostics/HealthChecker/CTSProcessorAffinityPercentageCheck/","title":"CTS Processor Affinity Percentage Check","text":"Description:
We check if the CtsProcessorAffinityPercentage
DWORD value under HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\ExchangeServer\\V15\\Search\\SystemParameters
exists and is set to any other value than 0
. This setting can be used to limit CPU utilization of a process.
This can cause an impact to the server's search performance. This should never be used as a long term solution!
Included in HTML Report?
Yes
"},{"location":"Diagnostics/HealthChecker/CertificateCheck/","title":"Certificate Check","text":"This check retrieves all certificates from the Exchange server by using the Get-ExchangeCertificate
cmdlet. We display the following information:
We also perform the following checks:
Certificate lifetime check:
Weak key size check:
Weak hash algorithm check:
Valid Auth certificate check:
Included in HTML Report?
Yes
"},{"location":"Diagnostics/HealthChecker/CloudConnectorCheck/","title":"Cloud Connector Check","text":"This check performs testings against the Exchange Send- and Receive Connectors which are enabled for cloud usage if a hybrid configuration was detected. We run Get-HybridConfiguration
to validate if hybrid has been configured for the environment.
A proper configured Send- and Receive Connector is important - especially in hybrid scenarios. A misconfigured connector can lead to multiple issues including broken tenant attribution and email classification (internal / anonymous) which can then lead to false-positive/false-negative.
We to make sure that the mail flow between Exchange on-premises and Exchange Online works as expected
If a Send Connector has the following setting set, it means that the connector is eligible for cloud mail usage:
If a Receive Connector has the following setting set, it means that the connector is eligible for cloud mail usage:
We only perform testings for the Receive Connectors if:
We run the following checks:
Connector enabled check:
Send Connector configured to relay emails via M365 check:
TlsAuthLevel
is set to CertificateValidation
RequireTLS
is set to true
TlsDomain
is set (only performed if TlsAuthLevel
is set to DomainValidation
)TlsCertificateName configuration check:
Get-HybridConfiguration
<I>X.500Issuer<S>X.500Subject
Included in HTML Report?
Yes
Additional resources:
Certificate requirements for hybrid deployments
Demystifying and troubleshooting hybrid mail flow: when is a message internal?
Set up your email server to relay mail to the internet via Microsoft 365 or Office 365
"},{"location":"Diagnostics/HealthChecker/CredentialGuardCheck/","title":"Credential Guard Check","text":"Description:
In this check we validate, weather Credential Guard
was activated or not. Credential Guard
is not supported on an Exchange Server. This can cause a performance hit on the server.
Included in HTML Report?
Yes
Additional resources:
Manage Windows Defender Credential Guard
"},{"location":"Diagnostics/HealthChecker/DownloadDomainCheck/","title":"Download Domain Check","text":"Description:
In this check we validate if the Download Domain
feature was configured or not. This feature was introduced to address CVE-2021-1730
.
If the feature is enabled, we validate if the URL configured to download attachments, is not set to the same as the internal or external Outlook Web App (OWA) url.
CVE-2021-1730
will not be addressed if the url configured to be used by the Download Domain
feature points to the same url(s) which is/are used by OWA.
The Download Domain
feature is available on Microsoft Exchange Server 2016 and Microsoft Exchange Server 2019.
More details and configuration instructions can be found in the Microsoft Learn article, that is linked in the additional resource section.
Included in HTML Report?
Yes
Additional resources:
Configure Download Domains in Exchange Server
"},{"location":"Diagnostics/HealthChecker/EEMSCheck/","title":"Exchange Emergency Mitigation Service Check","text":"Description:
The Exchange Emergency Mitigation Server
also known as EEMS
or EM
was introduced with the Exchange Server 2019 Cumulative Update 11
and Exchange Server 2016 Cumulative Update 22
.
The Exchange Emergency Mitigation service helps to keep your Exchange Servers secure by applying mitigations to address any potential threats against your servers. It uses the cloud-based Office Config Service (OCS)
to check for and download available mitigations and to send diagnostic data to Microsoft.
The EM service runs as a Windows service on an Exchange Mailbox server. The EM service will be installed automatically on servers with the Mailbox role. The EM service will not be installed on Edge Transport servers.
The use of the EM service is optional. If you do not want Microsoft to automatically apply mitigations to your Exchange servers, you can disable the feature.
This check performs the following testings to highlight the configuration state of the EEMS:
Configuration Check
Windows Service Check
MSExchangeMitigation
Windows service startup type should be: Automatic
MSExchangeMitigation
Windows service status should be: Running
Pattern Service Check
https://officeclient.microsoft.com/GetExchangeMitigations
Mitigations Check
Diagnostic Data Check
Included in HTML Report?
Yes
Additional resources:
New security feature in September 2021 Cumulative Update for Exchange Server
Released: September 2021 Quarterly Exchange Updates
Addressing Your Feedback on the Exchange Emergency Mitigation Service
Exchange Emergency Mitigation (EM) service
Mitigations Cloud endpoint is not reachable
"},{"location":"Diagnostics/HealthChecker/ExchangeServerMaintenanceCheck/","title":"Exchange Server Maintenance Check","text":"Description:
We validate the Maintenance State for the Exchange server. We run the following checks:
Get-ServerComponentState
Get-ClusterNode
Component.State
is not Active
Component.LocalStates
and Component.RemoteStates
LocalStates
& RemoteStates
are the sameLocalStates
& RemoteStates
are differentWe show a green information Server is not in Maintenance Mode
if the server is not in maintenance mode.
We display a yellow warning Exchange Server Maintenance
if components in maintenance state are detected. We also show additional information about the Database Copy Maintenance
and Cluster Node
state.
Included in HTML Report?
Yes
Additional resources:
Determine the requestor that changed Server component state
"},{"location":"Diagnostics/HealthChecker/FIPFSCheck/","title":"FIP-FS Check","text":"Description:
We have addressed the issue causing messages to be stuck in transport queues of on-premises Exchange Server 2016
and Exchange Server 2019
. The problem relates to a date check failure with the change of the new year and it not a failure of the AV engine itself. This is not an issue with malware scanning or the malware engine, and it is not a security-related issue.
The version checking performed against the signature file is causing the malware engine to crash, resulting in messages being stuck in transport queues.
This check validates if the problematic signature file has already downloaded and processed. It shows a red warning indicating that the FIP-FS scan engine should be reset to avoid running into the transport or pattern update issue.
2112330001
) will be applied.2201010000
or greater exists under ExchangeInstallPath\\FIP-FS\\Data\\Engines\\amd64\\Microsoft\\Bin
.We also check if the server runs a fixed Exchange build (March 2022 Security Update or higher) that does not crash when the problematic version is used.
If we detect the problematic version folder and the server doesn't run a fixed build, we recommend to reset the scan engine version (see Email Stuck in Exchange On-premises Transport Queues
in the \"Additional resources\" section).
If we detect the problematic version folder but the server runs a fixed build, it should be safe to delete the folder without performing a scan engine reset. If the directory cannot be deleted, it means that the problematic version is in use. This is a problem because in this case, no new scan engine version will be applied. In this case, a reset of the scan engine must be performed.
Please follow the instructions in the references below to reset the scan engine.
Included in HTML Report?
Yes
Additional resources:
Email Stuck in Exchange On-premises Transport Queues
"},{"location":"Diagnostics/HealthChecker/GeneralHardwareInformation/","title":"General Hardware Information","text":"Description:
We show some general information about the Processor/Hardware of the Exchange server against which the script was executed.
Hardware Type:
We additionally show the following information, if HardwareType
is Physical
or AmazonEC2
: - Manufacturer - Model - Processor
Number of Processors:
ServerType
is VMWare
[1]2 Processors
installedNumber of Physical/Logical Cores:
24 Physical Cores
and running Exchange 2013/2016
[2]48 Physical Cores
and running Exchange 2019
[2]Hyper-Threading:
We show if Hyper-Threading is enabled or not.
NUMA BIOS Check:
We check to see if we can properly see all cores on the server. [3], [4]
Max Processor Speed:
We return the MaxMegacyclesPerCore
. This is the max speed that we can get out of the cores. We also check if the processor is throttled which may be a result of a misconfigured Power Plan.
Physical Memory:
We validate if the amount of installed memory meets our specifications. [5]
Included in HTML Report?
Yes
Additional resources:
1 - Does CoresPerSocket Affect Performance?
2 - Commodity servers
3 - CUSTOMER ADVISORY c04650594
4 - Exchange performance:HP NUMA BIOS settings
5 - Exchange 2013 Sizing
5 - Hardware requirements for Exchange 2016
5 - Hardware requirements for Exchange 2019
"},{"location":"Diagnostics/HealthChecker/HyperThreadingCheck/","title":"Hyper-Threading Check","text":"Description:
We validate if Hyper-Threading is enabled or not. We do this by checking if LogicalCores
is greater than PhysicalCores
which means that Hyper-Threading is enabled. We show a red error and recommend turning off Hyper-Threading.
Included in HTML Report?
Yes
Additional resources:
Exchange 2013 Sizing and Configuration Recommendations - Processing
"},{"location":"Diagnostics/HealthChecker/IISInformation/","title":"Exchange IIS Information","text":""},{"location":"Diagnostics/HealthChecker/IISInformation/#description","title":"Description","text":"We show some general information about your Exchange Server from the IIS perspective. This goes into detail to make sure that Sites and App Pools are started, which might not be easy to spot at a quick look a the server. It will also call out some common misconfiguration issues, that will cause problems with client connectivity.
"},{"location":"Diagnostics/HealthChecker/IISInformation/#sites","title":"Sites","text":"This provides the sites that we found and the following information:
Default Web Site
)NOTE: HSTS if enabled on the Back End will call out an issue.
"},{"location":"Diagnostics/HealthChecker/IISInformation/#app-pools","title":"App Pools","text":"This provides the application pools on the server with the following information:
This provides the different locations that you use for different connection endpoints with the following information:
default setting
will be provided if that is enabled Out of the Box on the server )NOTE: For each of the URL Rewrite rules, we will display additional information about the rule to let you know what it is doing. It is also recommended to remove any mitigation rules that you might have applied if you have the security fix installed on the server.
"},{"location":"Diagnostics/HealthChecker/IISInformation/#included-in-html-report","title":"Included in HTML Report?","text":"Yes
"},{"location":"Diagnostics/HealthChecker/IISWebConfigCheck/","title":"IIS Web Configuration Check","text":"Description:
After a CU or an SU install, sometimes there can be issues with the web.config or the SharedWebConfig.config file that causes issues with the virtual directories from working properly. Most of these issues are from SU installs where they are installed from double clicking on the msi file. This prevents the process from starting as administrator and can cause multiple issues.
This check detects to make sure all the default web.config and SharedWebConfig.config files exist and if they have any default variable values still set within it - %ExchangeInstallDir%
.
If Default Variable Detected
file is found, open up that file and replace the %ExchangeInstallDir%
with the Exchange Install path from (Get-ItemProperty HKLM:\\SOFTWARE\\Microsoft\\ExchangeServer\\v15\\Setup).MsiInstallPath
Included in HTML Report?
Yes, if issue detected
"},{"location":"Diagnostics/HealthChecker/IPv6EnabledCheck/","title":"IPv6 Enabled Check","text":"Description:
We check if IPv6 is enabled or not. If we determine that IPv6 has been disabled, we check to see if it's fully disabled as recommended. We determine if the IPv6 is fully disabled by checking to see if we have an IPv6 Address available on the NIC and that it matches what is found in the registry at SYSTEM\\CurrentControlSet\\Services\\TcpIp6\\Parameters\\DisabledComponents
.
If both places don't have IPv6 enabled/disabled properly a warning is thrown. This can cause communication issues if not properly disabled.
Included in HTML Report?
Yes
Additional resources:
Disabling IPv6 And Exchange \u2013 Going All The Way
Guidance for configuring IPv6 in Windows for advanced users
"},{"location":"Diagnostics/HealthChecker/InternalTransportCertificateCheck/","title":"Internal Transport Certificate","text":""},{"location":"Diagnostics/HealthChecker/InternalTransportCertificateCheck/#description","title":"Description","text":"The Internal Transport Certificate in Exchange Server is used in Exchange Server Front-End to Back-End MailFlow scenarios as well as in scenarios in which the Exchange Servers communicate with each other, using the SMTP (Simple Mail Transfer Protocol)
protocol. It is generated on a per-server base during the Exchange Server setup process and contains the computers NetBIOS (Network Basic Input/Output System)
name as well as the FQDN (Fully Qualified Domain Name)
.
A missing Internal Transport Certificate can lead to a broken MailFlow on or with the affected machine. It's therefore essential to have a valid certificate for this purpose on the machine. We recommend to not replace the self-signed certificate which was created by Exchange itself.
"},{"location":"Diagnostics/HealthChecker/InternalTransportCertificateCheck/#what-does-the-check-do","title":"What does the check do?","text":"The check queries the certificate which is marked as Internal Transport Certificate on the server against which the script is currently running. The script will throw a warning if the certificate cannot be found on the machine. It must then be recreated by the Exchange Server administrator and set as new Internal Transport Certificate.
"},{"location":"Diagnostics/HealthChecker/InternalTransportCertificateCheck/#how-to-create-a-new-internal-transport-certificate","title":"How to create a new Internal Transport Certificate?","text":"You can run the following PowerShell code from an elevated Exchange Management Shell (EMS). It will generate a new Internal Transport Certificate which replaces the existing one on the machine where the command was executed.
$newInternalTransportCertificateParams = @{\n Server = $env:COMPUTERNAME\n KeySize = 2048\n PrivateKeyExportable = $true\n FriendlyName = $env:COMPUTERNAME\n DomainName = $env:COMPUTERNAME\n IncludeServerFQDN = $true\n Services = \"SMTP\"\n Force = $true\n ErrorAction = \"Stop\"\n}\n\nNew-ExchangeCertificate @newInternalTransportCertificateParams\n
"},{"location":"Diagnostics/HealthChecker/InternalTransportCertificateCheck/#included-in-html-report","title":"Included in HTML Report?","text":"Yes
"},{"location":"Diagnostics/HealthChecker/InternalTransportCertificateCheck/#additional-resources","title":"Additional resources","text":"N/A
"},{"location":"Diagnostics/HealthChecker/LMCompatibilityLevelInformationCheck/","title":"LM Compatibility Level Information Check","text":"LAN Manager authentication level setting determines which challenge/response authentication protocol is used for network logons. This choice affects the authentication protocol level that clients use, the session security level that the computers negotiate, and the authentication level that servers accept.
Included in HTML Report?
Yes
Additional resources:
Network security: LAN Manager authentication level
"},{"location":"Diagnostics/HealthChecker/MAPIFrontEndAppPoolGCModeCheck/","title":"MAPI Front End App Pool GC Mode Check","text":"Description:
We validate the Garbage Collection (GC) configuration for MSExchangeMapiFrontEndAppPool
App Pool if the check is executed against an Exchange 2013 server that is not running the EdgeTransport role.
We check if:
The server has a total memory of 21474836480 MB
and gcServer.Enabled
set to false
\\ In this case we recommend to enable Server GC
.
gcServer.Enabled
is neither true
nor false
\\ This case should be investigated.
gcServer.Enabled
is false
In this case we're running Workstation GC.\\ You could be seeing some GC issues within the MSExchangeMapiFrontEndAppPool
App Pool. However, you don't have enough memory installed on the system to recommend switching the GC mode by default without consulting a support professional.
How to fix this:
MSExchangeMapiFrontEndAppPool_CLRConfig.config
\\ You can find the file by running %winDir%\\system32\\inetSrv\\AppCmd.exe list AppPool \"MSExchangeMapiFrontEndAppPool\" /text:\"CLRConfigFile\"
via cmd.exe
\\ It should be located here: %ExchangeInstallPath%\\bin\\MSExchangeMapiFrontEndAppPool_CLRConfig.config
notepad.exe
and change the gcServer Enabled
value from false
to true
MAPI Front End App Pool
by running: Restart-WebAppPool MSExchangeMapiFrontEndAppPool
via PowerShell
or by running:\\ %winDir%\\system32\\inetSrv\\AppCmd.exe RECYCLE AppPool \"MSExchangeMapiFrontEndAppPool\"
via cmd.exe
Included in HTML Report?
Yes
Additional resources:
Fundamentals of garbage collection
Workstation and server garbage collection
"},{"location":"Diagnostics/HealthChecker/May22SU/","title":"May 2022 Security Update","text":"In order to protect against CVE-2022-21978 within your environment /PrepareDomain
must be run against each domain that contains the MESO container within it.
Health Checker will query all the domains in the environment to see if it has a MESO container. If it does, it checks for a particular ACE or version number of the MESO container to see if we are secure. If we don't pass this check, it will provide what domains you need to run /PrepareDomain
against.
In order to protect your environment from CVE-2022-21978, you must install the May 2022 SU or a newer SU/CU that contains this security fix. All SUs and CUs after May 2022 contain this fix. After you have installed this security fix, you must run /PrepareDomain
or /PrepareAllDomains
from the Exchange bin directory.
Included in HTML Report?
Yes
Additional resources:
Exchange Team Blog - May SU 2022
"},{"location":"Diagnostics/HealthChecker/NETFrameworkSupportabilityCheck/","title":".NET Framework Supportability Check","text":"Description:
We check if the Exchange server is running a supported .NET Framework version. We do this based on the information provided by PG on Microsoft Docs (.NET Supportability Matrix).
Included in HTML Report?
Yes
Additional resources:
Microsoft .NET Framework Supportability Matrix
"},{"location":"Diagnostics/HealthChecker/NumaBiosCheck/","title":"NUMA BIOS / All Processor Cores Visible Check","text":"Description:
Check to see if the OS is able to see all the processor cores on the server. What normally happens is the OS is able to see 1 processor socket presented (aka half the number of cores)
This can become a major problem on a server if you do not see all the processor cores for a few reasons.
Logic is built into the Exchange Code to handle user workload management is based of the how much CPU the user is using or the process itself. When we aren't able to see all the cores on the system, the process can consume a higher amount than what logic dictates. We base this logic off of the number of cores presented to the OS by [System.Environment]::ProcessorCount
. Because the underlying hardware has full access to all the processor cores, the process can go above what Exchange calculated out to set the threshold to be at and then throttling can occur.
Sometimes the underlying setting isn't able to keep up and doesn't distribute the load between both the processor sockets, thus causing an issue because the application just lost half of its resources. You can see this occur when you look at the performance counter \"\\Processor Information(0,_Total)\\% Processor Time\" and \"\\Processor Information(1,_Total)\\% Processor Time\" as each one sees their own socket. One will go up while the other goes down. This might only happen for a few seconds, but there are health checks on the server that can be triggered to cause additional issues that will spiral the server.
Included in HTML Report?
Yes
Additional resources:
CUSTOMER ADVISORY c04650594
Exchange performance:HP NUMA BIOS settings
Exchange 2016 users unable to edit Distribution Group membership using Outlook
"},{"location":"Diagnostics/HealthChecker/OpenRelayDomain/","title":"Open Relay Domain","text":"Description:
We show a warning if we weren't able to run Get-AcceptedDomain
and provide an unknown
status. If we determine that an Open Relay Domain is set on the environment, we will throw an error in the results and provide which accepted domain ID is set with this. It is recommended to have an anonymous relay and scope down the receive connector for who can use it. Otherwise, you are allowing anybody to use your environment to send mail anywhere.
NOTE: After installing the September 2021 CUs for Exchange 2016/2019, you can see crashes occur on your system for the transport services that look like this:
Log Name: Application\nSource: MSExchange Common\nDate: 12/3/2021 12:40:35 PM\nEvent ID: 4999\nTask Category: General\nLevel: Error\nKeywords: Classic\nUser: N/A\nComputer: Contoso-E19A.Contoso.com\nDescription:\nWatson report about to be sent for process id: 10072, with parameters: E12IIS, c-RTL-AMD64, 15.02.0986.005, MSExchangeDelivery, M.Exchange.Transport, M.E.T.AcceptedDomainTable..ctor, System.FormatException, 28d7-DumpTidSet, 15.02.0986.005.\nErrorReportingEnabled: False\n
This is caused by having an Internal Relay with an Accepted Domain of *. This is not a recommended configuration.
Included in HTML Report?
Yes
Additional resources:
Allow anonymous relay on Exchange servers
"},{"location":"Diagnostics/HealthChecker/PacketsLossCheck/","title":"Packets Loss Check","text":"Description:
We check if there are any PacketsReceivedDiscarded
logged for the NIC. Large package loss can cause a performance impact on a system and should be investigated and fixed.
PacketsReceivedDiscarded
is 0
PacketsReceivedDiscarded
lower than 1000
PacketsReceivedDiscarded
greater than 1000
NOTE: This counter is accumulation from reboot, or if the NIC setting was changed, so the counter can be stale for some time. However, even though you might not be actively dropping packets, the counter should be at 0 in a healthy environment.
Included in HTML Report?
Yes
Additional Information
Large packet loss in the guest OS using VMXNET3 in ESXi (2039495)
Disable \"adaptive rx ring sizing\" to avoid random interface reset (78343)
"},{"location":"Diagnostics/HealthChecker/PagefileSizeCheck/","title":"Pagefile Size Check","text":"Description:
We check if the Pagefile is configured as recommended and that there is only 1 PageFile configured (multiple PageFiles can cause performance issues on Exchange server).
"},{"location":"Diagnostics/HealthChecker/PagefileSizeCheck/#exchange-2019","title":"Exchange 2019","text":"Set the paging file minimum and maximum value to the same size:
Less than 32 GB of RAM installed: Physical RAM plus 10MB, up to a maximum value of 32GB (32,778MB)
32 GB of RAM or more installed: 32GB
You can set the pagefile to a static size via wmic
whereas InitialSize
and MaximumSize
is the size in megabytes calculated based on the Exchange Server version and memory installed in the server:
wmic ComputerSystem set AutomaticManagedPagefile=False\nwmic PageFileSet set InitialSize=1024,MaximumSize=1024\n
Included in HTML Report?
Yes
Additional resources:
PageFile requirements for Exchange 2019
PageFile requirements for Exchange 2016
PageFile requirements for Exchange 2013
"},{"location":"Diagnostics/HealthChecker/ProcessorCheck/","title":"Number Of Processors","text":"Description:
Number of Processors is the number of processor sockets detected on the server. It is only recommended to have up to 2 processors on the server. [3]
An additional note is displayed if Type
is set to VMware
and greater than 2 processors. [1]
([array](Get-WmiObject -Class Win32_Processor)).count\n
"},{"location":"Diagnostics/HealthChecker/ProcessorCheck/#number-of-logical-and-physical-cores","title":"Number Of Logical and Physical Cores","text":"Show the number of Physical and Logical cores presented to the OS. This is provided by the WmiObject class Win32_Processor
.
24 Logical Cores
and running Exchange 2013/2016
[2]48 Logical Cores
and running Exchange 2019
[2]$processor = Get-WmiObject -Class Win32_Processor\n$processor |ForEach-Object {$logical += $_.NumberOfLogicalProcessors; $physical += $_.NumberOfCores}\nPS C:\\> $logical\n24\nPS C:\\> $physical\n12\n
"},{"location":"Diagnostics/HealthChecker/ProcessorCheck/#max-processor-speed","title":"Max Processor Speed","text":"Check to see what the Max Processor Speed is set to for the processor. If the processor is throttled which may be a result of a misconfigured Power Plan.
NOTE: If Power Plan isn't set to High Performance and the processor is being throttled, this will be flagged that Power Plan is the cause and to fix it ASAP.
"},{"location":"Diagnostics/HealthChecker/ProcessorCheck/#how-this-is-checked_2","title":"How This Is Checked","text":"$processor = Get-WmiObject -Class Win32_Processor\n$throttled = $processor | Where-Object {$_.CurrentClockSpeed -lt $_.MaxClockSpeed}\n\nif ($throttled) {\n Write-Host (\"Throttling your CPU\")\n}\n
Included in HTML Report?
Yes
Additional resources:
1 - Does CoresPerSocket Affect Performance?
2 - Commodity servers
3 - Hardware requirements for Exchange 2019
Exchange 2013 Sizing
Hardware requirements for Exchange 2016
"},{"location":"Diagnostics/HealthChecker/RPCMinConnectionTimeoutCheck/","title":"RPC Minimum Connection Timeout Check","text":"Description:
By default, Outlook Anywhere opens two default connections to the Exchange CAS called RPC_InData
and RPC_OutData
. The Outlook Anywhere client to server used a default timeout of 12 minutes (720 seconds)
of inactivity and the server to the client timeout is 15 minutes (900 seconds)
.
These default Keep-Alive intervals are not aggressive enough for some of today's home networking devices and/or aggressive network devices on the Internet. Some of those devices are dropping TCP connections after as little as 5 minutes (300 seconds)
of inactivity. When one or both of the two default connections are dropped, the connection to the Exchange server is essentially broken and not useable.
Included in HTML Report?
Yes
Additional resources:
Outlook Anywhere Network Timeout Issue
"},{"location":"Diagnostics/HealthChecker/RSSEnabledCheck/","title":"RSS Enabled Check","text":"Description:
We check on Windows 2012 R2
or newer whether RSS (if it's supported from the NIC) is enabled or not. This is collected by the Get-NetAdapterRss
cmdlet. We show a warning if it's supported on NIC-side but disabled.
The Get-NetAdapterRss cmdlet gets receive side scaling (RSS) properties of the network adapters that support RSS. RSS is a scalability technology that distributes the receive network traffic among multiple processors by hashing the header of the incoming packet and using an indirection table. Without RSS in Windows Server\u00ae 2012 and later, network traffic is received on the first processor which can quickly reach full utilization limiting receive network throughput. Various properties can be configured to optimize the performance of RSS.
Included in HTML Report?
Yes
Additional resources:
Introduction to Receive Side Scaling
"},{"location":"Diagnostics/HealthChecker/RebootPending/","title":"Reboot Pending","text":"Description:
We show a warning if we detect an outstanding pending reboot. We also display the type of pending reboot. We differentiate between:
It is best to reboot the server to address these issues. It may take some time after a reboot to have the keys automatically removed. However, if they don't remove automatically, follow these steps to address the issue for the keys that were provided to be a problem.
NOTE: With Component Based Servicing\\RebootPending
you need to do the same for Component Based Servicing\\PackagesPending
prior to RebootPending
NOTE: Follow the steps in this section carefully. Serious problems might occur if you modify the registry incorrectly. Before you modify it, back up the registry for restoration in case problems occur.
Included in HTML Report?
Yes
Additional resources:
Determine Pending Reboot Status\u2014PowerShell Style! Part 1
Determine Pending Reboot Status\u2014PowerShell Style! Part 2
"},{"location":"Diagnostics/HealthChecker/RunHCViaSchedTask/","title":"How to run the Exchange Health Checker via Scheduled Task","text":"Description:
You can run the Exchange Health Checker script by the help of a Scheduled Task on a daily, weekly or monthly base.
This article describes some of the ways how to run the script as task and how to create those tasks.
Note: We assume that the script is stored under C:\\Scripts\\HealthChecker
. Please make sure to adjust the path if you use a different one in your environment.
View-Only Organization Management
instead of Organization Management
. This should be sufficient for the script to run.Note: Using View-Only Organization Management
instead of Organization Management
requires you to add the account to the local Administrators
group on each server. This can be achieved by creating a dedicated Security Group
which is then added to the Administrators
group on each Exchange server (manually or via Group Policy
).
We need to create multiple objects and finally combining them to the Scheduled Task. We need a trigger
, settings
, action
and task
object.
Create a trigger that defines when the script should be executed:
$hcTrigger = New-ScheduledTaskTrigger -Daily -At 3am
$hcTrigger = New-ScheduledTaskTrigger -Weekly -WeeksInterval 4 -DaysOfWeek Monday -At 3am
Create a Scheduled Task setting object:
$hcSettings = New-ScheduledTaskSettingsSet
RestartCount
and RestartInterval
:$hcSettings = New-ScheduledTaskSettingsSet -RestartCount 3 -RestartInterval (New-TimeSpan -Minutes 60)
Define the actions to be executed via Scheduled Task:
$hcAction = New-ScheduledTaskAction -Execute 'powershell.exe' -WorkingDirectory \"C:\\Scripts\\HealthChecker\\\" -Argument '-NonInteractive -NoLogo -NoProfile -Command \".\\HealthChecker.ps1 -ScriptUpdateOnly; .\\HealthChecker.ps1; .\\HealthChecker.ps1 -BuildHtmlServersReport\"'
ExchSrv01
in this example):$hcAction = New-ScheduledTaskAction -Execute 'powershell.exe' -WorkingDirectory \"C:\\Scripts\\HealthChecker\\\" -Argument '-NonInteractive -NoLogo -NoProfile -Command \".\\HealthChecker.ps1 -ScriptUpdateOnly; .\\HealthChecker.ps1 -Server ExchSrv01; .\\HealthChecker.ps1 -BuildHtmlServersReport\"'
Create the Scheduled Task object using the pre-defined action, trigger and settings objects:
$hcTask = New-ScheduledTask -Action $hcAction -Trigger $hcTrigger -Settings $hcSettings
Create the Scheduled Task:
Register-ScheduledTask -TaskName 'HealthChecker Daily Run' -InputObject $hcTask -User (Read-Host \"Please enter username in format (Domain\\Username)\") -Password (Read-Host \"Please enter password\")
Additional resources:
New-ScheduledTaskTrigger
New-ScheduledTaskSettingsSet
New-ScheduledTaskAction
New-ScheduledTask
Register-ScheduledTask
"},{"location":"Diagnostics/HealthChecker/SMBv1Check/","title":"SMBv1 Check","text":"To make sure that your Exchange organization is better protected against the latest threats (for example Emotet, TrickBot or WannaCry to name a few) we recommend disabling SMBv1 if it's enabled on your Exchange (2013/2016/2019) server.
There is no need to run the nearly 30-year-old SMBv1 protocol when Exchange 2013/2016/2019 is installed on your system. SMBv1 isn't safe and you lose key protections offered by later SMB protocol versions.
This check verifies that SMBv1 is not installed (if OS allows) and that its activation is blocked.
Included in HTML Report?
Yes
Additional resources:
Exchange Server and SMBv1
"},{"location":"Diagnostics/HealthChecker/SerializedDataSigningCheck/","title":"PowerShell Serialization Payload Signing","text":""},{"location":"Diagnostics/HealthChecker/SerializedDataSigningCheck/#description","title":"Description","text":"Certificate-based signing of PowerShell Serialization Payload is a defense-in-depth security feature to prevent malicious manipulation of serialized data exchanged in Exchange Management Shell (EMS) sessions.
The Serialized Data Signing feature was introduced with the January 2023 Exchange Server Security Update (SU). It's available on Exchange Server 2013, Exchange Server 2016 and Exchange Server 2019 and enabled by default with the November 2023 Security Update.
The HealthChecker check validates that the feature is enabled on supported Exchange builds.
Documentation Moved
This documentation has been moved to Microsoft Learn. Please read Configure certificate signing of PowerShell serialization payloads in Exchange Server for more information.
"},{"location":"Diagnostics/HealthChecker/SerializedDataSigningCheck/#included-in-html-report","title":"Included in HTML Report?","text":"Yes
"},{"location":"Diagnostics/HealthChecker/SerializedDataSigningCheck/#additional-resources","title":"Additional resources","text":"Released: January 2023 Exchange Server Security Updates
Released: November 2023 Exchange Server Security Updates
MonitorExchangeAuthCertificate.ps1 script
"},{"location":"Diagnostics/HealthChecker/SettingOverridesCheck/","title":"Setting Overrides","text":""},{"location":"Diagnostics/HealthChecker/SettingOverridesCheck/#description","title":"Description","text":"Setting Overrides can be configured via New-SettingOverride
cmdlet and in certain cases with the help of registry values. They can be created to change default values for common Exchange services and features (e.g., the default run cycle of the Managed Folder Assistant).
Sometimes they are used to enable new features like the recently introduced Serialized Data Signing for PowerShell payload.
In very rare cases, Microsoft recommends to disable a feature or component by the help of an override (e.g., EWS web application pool stops after the February 2023 Security Update is installed) to work around known issues.
HealthChecker checks for known overrides which should be removed as a solution for to a particular problem is available.
Important
Incorrect usage of the setting override cmdlets can cause serious damage to your Exchange organization. This damage could require you to reinstall Exchange. Only use these cmdlets as instructed by product documentation or under the direction of Microsoft Customer Service and Support.
"},{"location":"Diagnostics/HealthChecker/SettingOverridesCheck/#setting-overrides_1","title":"Setting Overrides","text":"Feature Exchange Version(s) Controlled via Recommended setting BaseTypeCheckForDeserialization 2013, 2016, 2019 Registry Value DisabledEnable:
New-ItemProperty -Path HKLM:\\SOFTWARE\\Microsoft\\ExchangeServer\\v15\\Diagnostics -Name \"DisableBaseTypeCheckForDeserialization\" -Value 1 -Type String\n
Disable:
Remove-ItemProperty -Path HKLM:\\SOFTWARE\\Microsoft\\ExchangeServer\\v15\\Diagnostics -Name \"DisableBaseTypeCheckForDeserialization\"\n
Feature Exchange Version(s) Controlled via Recommended setting Strict Mode for ClientExtensionCollectionFormatter 2016, 2019 New-SettingOverride Enabled Enable:
Get-SettingOverride | Where-Object {$_.ComponentName -eq \"Data\" -and $_.SectionName -eq \"DeserializationBinderSettings\" -and $_.Parameters -eq \"LearningLocations=ClientExtensionCollectionFormatter\"} | Remove-SettingOverride\n
Disable:
New-SettingOverride -Name \"Adding learning location ClientExtensionCollectionFormatter\" -Component Data -Section DeserializationBinderSettings -Parameters @(\"LearningLocations=ClientExtensionCollectionFormatter\") -Reason \"Deserialization failed\"\n
"},{"location":"Diagnostics/HealthChecker/SettingOverridesCheck/#included-in-html-report","title":"Included in HTML Report?","text":"Yes
"},{"location":"Diagnostics/HealthChecker/SettingOverridesCheck/#additional-resources","title":"Additional resources","text":"New-SettingOverride
Remove-SettingOverride
"},{"location":"Diagnostics/HealthChecker/SleepyNICCheck/","title":"Sleepy NIC Check","text":"Description:
We validate the NIC power saving options. It's recommended to disable NIC power saving options as this may cause packet loss.
To detect the NIC power saving options, we're probing the sub keys under: HKLM\\SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002bE10318}
We then check if the PnPCapabilities
REG_DWORD exists and if it does, we're validating its value. If it's 24
or 280
, NIC power saving is disabled as we recommend it.
We skip this check for Multiplexor NIC adapters
and in case that the host system is Hyper-V
(because we're assuming that we don't support NIC power saving options on this platform).
NOTE: If the REG_DWORD doesn't exists, we're assuming that NIC power saving is not disabled or configured and show a warning.
Included in HTML Report?
Yes
Additional resources:
Information about power management setting on a network adapter
"},{"location":"Diagnostics/HealthChecker/TCPIPSettingsCheck/","title":"TCP/IP Settings Check","text":"Description:
We validate if a KeepAliveTime
DWORD value exists under HKEY_LOCAL_MACHINE\\System\\CurrentControlSet\\Services\\TcpIp\\Parameters
and verify that it is set to a recommended value.
Exchange TCP KeepAliveTime
registry entry should be set to a decimal value between 900000 and 1800000 (15 to 30 minutes in milliseconds). If there's no entry in the registry for KeepAliveTime
then the default value is 2 hours.
This value, if not set correctly, can affect both connectivity and performance. You must make sure that the load balancer and any other devices in the path from client to Exchange are configured correctly.
The goal is to set Exchange with the lowest value so that client sessions, when ended, are ended by Exchange and not by the device.
Example:
Client -> Firewall (1 hour) -> NLB (40 minutes) -> Exchange Servers (20 Minutes)
Included in HTML Report?
Yes
Additional resources:
Checklist for Troubleshooting Performance Related issues in Exchange 2013, 2016 and 2019 (on-prem)
"},{"location":"Diagnostics/HealthChecker/TLSConfigurationCheck/","title":"TLS Configuration Check","text":"We check and validate Exchange servers TLS 1.0 - 1.3 configuration. We can detect mismatches in TLS versions for client and server. This is important because Exchange can be both a client and a server.
We will also show a yellow warning, if TLS 1.0 and/or TLS 1.1 is enabled. Microsoft's TLS 1.0 implementation is free of known security vulnerabilities. Due to the potential for future protocol downgrade attacks and other TLS 1.0 vulnerabilities not specific to Microsoft's implementation, it is recommended that dependencies on all security protocols older than TLS 1.2 be removed where possible (TLS 1.1/1.0/ SSLv3/SSLv2).
At this time TLS 1.3 is not supported by Exchange and has been known to cause issues if enabled. If detected to be anything but disabled on Exchange, it will be thrown as an error and needs to be addressed right away.
We also check for the SystemDefaultTlsVersions registry value which controls if .NET Framework will inherit its defaults from the Windows Schannel DisabledByDefault registry values or not.
An invalid TLS configuration can cause issues within Exchange for communication.
Only the values 0 or 1 are accepted and determined to be properly configured. The reason being is this is how our documentation provides to configure the value only and it then depends on how the code reads the value from the registry interpret the value.
By not having the registry value defined, different versions of .NET Frameworks for what the code is compiled for will treat TLS options differently. Therefore, we throw an error if the key isn't defined and action should be taken to correct this as soon as possible. To correct this, you create the missing DWORD
registry key with the value you wish to have.
The Configuration
result can provide a value of Enabled
, Disabled
, Half Disabled
, or Misconfigured
. They are defined by the following conditions:
The location where we are checking for the TLS values are here:
SYSTEM\\CurrentControlSet\\Control\\SecurityProviders\\SCHANNEL\\Protocols\\TLS 1.0\\Client
SYSTEM\\CurrentControlSet\\Control\\SecurityProviders\\SCHANNEL\\Protocols\\TLS 1.0\\Server
SYSTEM\\CurrentControlSet\\Control\\SecurityProviders\\SCHANNEL\\Protocols\\TLS 1.1\\Client
SYSTEM\\CurrentControlSet\\Control\\SecurityProviders\\SCHANNEL\\Protocols\\TLS 1.1\\Server
SYSTEM\\CurrentControlSet\\Control\\SecurityProviders\\SCHANNEL\\Protocols\\TLS 1.2\\Client
SYSTEM\\CurrentControlSet\\Control\\SecurityProviders\\SCHANNEL\\Protocols\\TLS 1.2\\Server
SYSTEM\\CurrentControlSet\\Control\\SecurityProviders\\SCHANNEL\\Protocols\\TLS 1.3\\Client
SYSTEM\\CurrentControlSet\\Control\\SecurityProviders\\SCHANNEL\\Protocols\\TLS 1.3\\Server
At each location, we are looking at the value of Enabled
and DisabledByDefault
. If the key isn't present, Enabled
is set to true
and DisabledByDefault
is set to false
. With the exception of TLS 1.3, if that isn't present it is disabled by default.
The location for the .NET Framework TLS related settings are located here:
SOFTWARE\\Wow6432Node\\Microsoft\\.NETFramework\\v4.0.30319
SOFTWARE\\Microsoft\\.NETFramework\\v4.0.30319
SOFTWARE\\Wow6432Node\\Microsoft\\.NETFramework\\v2.0.50727
SOFTWARE\\Microsoft\\.NETFramework\\v2.0.50727
At each location, we are looking at the value of SystemDefaultTlsVersions
and SchUseStrongCrypto
. If the key isn't present, both are set to false
.
Included in HTML Report?
Yes
Additional resources:
Exchange Server TLS configuration best practices
Solving the TLS 1.0 Problem, 2nd Edition
TLS 1.2 support at Microsoft
Exchange Server TLS guidance, part 1: Getting Ready for TLS 1.2
Exchange Server TLS guidance Part 2: Enabling TLS 1.2 and Identifying Clients Not Using It
Exchange Server TLS guidance Part 3: Turning Off TLS 1.0/1.1
"},{"location":"Diagnostics/HealthChecker/VisualCRedistributableVersionCheck/","title":"Visual C++ Redistributable Version Check","text":"Description:
We check if the the latest Visual C++ Redistributable version, required for the installed Exchange server role, is installed or not.
Included in HTML Report?
Yes
Additional resources:
Microsoft Visual C++ Redistributable Latest Supported Downloads
Exchange Server 2019 prerequisites
Exchange Server 2016 prerequisites
"},{"location":"Diagnostics/HealthChecker/VulnerabilityCheck/","title":"Vulnerability Check","text":"The script performs different checks to detect vulnerabilities which may lead into a security issue for the Exchange server.
Vulnerability checks performed:
CVE-2020-0796
SMBv3 vulnerabilityCVE-2020-1147
.NET Core & .NET Framework vulnerabilityCVE-2021-1730
Download Domains stateIncluded in HTML Report?
Yes
"},{"location":"Hybrid/Test-HMAEAS/","title":"Validating Hybrid Modern Authentication setup for Outlook for iOS and Android","text":"Download the latest release: Test-HMAEAS.ps1
This script allows you to check and see if your on-premises Exchange environment is configured correctly to use Hybrid Modern Authentication (HMA) with Outlook for iOS and Android. For this to work correctly, you will need to enable HMA and follow HMA Outlook for iOS and Android guidance to configure this feature properly.
To run the script, at minimum you will need a valid SMTP Address for a user that is located on-premises.
To test basic AutoDiscover and a Empty Bearer Authorization check you can run:
.\\Test-HMAEAS.ps1 user@contoso.com\n
To test basic AutoDiscover with a custom AutoDiscover Name and also do Empty Bearer Authorization check you can run:
.\\Test-HMAEAS.ps1 user@contoso.com -CustomAutoD autodiscover.contoso.com\n
To test basic EAS Connectivity you can run (you will need to use the users credentials for this test):
.\\Test-HMAEAS.ps1 user@contoso.com -TestEAS\n
"},{"location":"M365/DLT365Groupsupgrade/","title":"DLT365GroupsUpgrade","text":"Download the latest release: DLT365GroupsUpgrade.ps1
"},{"location":"M365/DLT365Groupsupgrade/#validating-distribution-group-eligibility-for-upgrade-to-o365-group","title":"Validating Distribution group eligibility for upgrade to O365 Group","text":"This script allows you to check Distribution to O365 Group migration eligibility for a specific distribution group SMTP, for more information over the Distribution to O365 Group migration blockers please check: https://docs.microsoft.com/en-us/microsoft-365/admin/manage/upgrade-distribution-lists?view=o365-worldwide
The script will prompt for global administrator username & password to connect to EXO Then the script will ask for required group smtp Then start to check and provide feedback in case group migration blockers found as illustrated below:
"},{"location":"NewUserGuide/","title":"New User Guide","text":""},{"location":"NewUserGuide/#introduction","title":"Introduction","text":"If you are new to Git and GitHub, and you want to contribute to CSS-Exchange, you've come to the right place.
There are many, many resources on how to use Git and GitHub. We recommend starting with Pro Git. Reading chapters 1 to 3 provides a great foundation for understanding and using Git.
This page will serve as a quick start that leads you through submitting a Pull Request to CSS-Exchange step by step.
This page will not cover the use of any GUI that attempts to insulate the user from the Git command line. In this author's opinion, the only way to really learn Git is to use the command line, so that's all we'll cover here.
"},{"location":"NewUserGuide/#before-you-start","title":"Before You Start","text":"If you are considering a large change to a script or a brand new script, it's often a good idea to open an Issue first to discuss the change. This will allow the repository owners to provide feedback on whether they would accept this type of change. By getting feedback before you spend days on a complex change, you can ensure that you're not wasting your time.
"},{"location":"NewUserGuide/#installation","title":"Installation","text":"The first step is to fork the repository on GitHub. Unless you have Write access to CSS-Exchange, you can't push directly to our repo. Creating a fork creates your own copy of the repo on GitHub, so you have somewhere to push your changes.
To fork the repository, use the Fork icon at the top right of the repository page.
You'll be prompted for a name and description. The defaults are fine. When the fork is complete, you'll be taken to the new repository page. At the top left, you should see that you are now on your own fork.
"},{"location":"NewUserGuide/#cloning-the-repository","title":"Cloning the repository","text":"Now you're ready to start using the git command line. To clone the repository, drop down the Code button and copy the URL:
Then use that URL to clone the repository using the command line:
git clone <url>\n
This creates a folder called CSS-Exchange
in your current directory.
Change into the folder that was just created. Your shell should now look something like this.
Because we have PoshGit loaded, it's showing our current branch name in the prompt - main. Let's create a new branch for our work. It's nice to use a descriptive name. For example, if we're updating this guide, we might call name it like so:
"},{"location":"NewUserGuide/#making-changes","title":"Making changes","text":"Now that you're on your own branch, you're ready to make your changes. You can technically use any tool you like - notepad, vim, whatever. But, if you open the repo root folder in Visual Studio Code, many of the repository formatting settings will be applied automatically. You can also shift-alt-F to reformat a file according to the settings. This may save you some time later.
For this example, I created a new script called New-Script.ps1.
After making our changes, it's a good idea to verify that git sees everything we changed, and that we haven't changed any files we didn't intend to. Because we have PoshGit, just hitting Enter to get a new prompt shows us some information about how many files have changed. We can also run git status
to see some details.
This looks good. My intent was to add one script file, and that's the only change shown here.
"},{"location":"NewUserGuide/#formatting-changes","title":"Formatting changes","text":"CSS-Exchange has some formatting requirements to ensure consistency, and these checks are integrated into our build process. Before committing changes, let's run .build\\CodeFormatter.ps1
to see if our new script meets the requirements.
CodeFormatter highlighted a few problems here:
CodeFormatter will fix some problems automatically if the -Save switch is included. Let's run it again with -Save.
Here we see CodeFormatter automatically fixed all of these issues when run with the -Save switch. Running a second time, we can confirm everything was fixed, as it generates no output at all.
"},{"location":"NewUserGuide/#staging-changes","title":"Staging changes","text":"We're almost ready to commit our changes, but first we should stage them. Staging gives us a chance to sanity-check what we're about to commit before we actually commit. It's especially useful when we have modified several files for testing, but we only intend to commit some of them.
If we run git status
again, we should once again see that only one file is modified for our simple test case. Then we can stage our file with git add
, and check the result again with git status
.
When we have many files to commit, we can use git add .
to stage all files in the current folder and SubFolders, or git add :/
to stage all files everywhere. When using those options, it's especially important to check git status
to make sure we haven't staged something we didn't intend to.
If git status
shows that the correct files are staged, we can commit them with git commit
. This will open the default editor, which will be Visual Studio Code if you chose it when installing Git as described earlier.
The top line should be the title of the commit. Then skip a line and add further details as necessary. Close the tab, choose Save when prompted, and we see the following output.
Now our changes are committed to our local copy of our branch, but we need to push those to GitHub.
"},{"location":"NewUserGuide/#pushing-the-changes","title":"Pushing the changes","text":"Because this is the first time we're pushing changes for our new branch, we have to provide a few details. On our first push of our new branch, the syntax will be git push -u origin <branch name>
.
Origin means we're pushing to the location we cloned from - this is the name of the remote repo by default. The -u
parameter tells it to set this as our upstream for this branch. We only have to do this the first time. If we make additional changes on this branch and commit them, we can now push them to the server with a simple git push
, since we have now told it that origin will be our upstream going forward.
Now we're ready to request that our changes be pulled into the official repo.
"},{"location":"NewUserGuide/#creating-a-pull-request","title":"Creating a Pull Request","text":"There are a few ways to create a Pull Request. We can see in the previous screenshot that GitHub helpfully shows us a URL we can visit to start a Pull Request. You can also manually navigate to the Pull Request tab of the official repo, and create a new Pull Request there. You might even see a prompt to create a PR for the branch you just pushed. Either of these methods will work.
At this point we're presented with a form to provide some details about the PR. Be sure that at the top of the PR form, we see the official repo and the main
branch on the left, followed by your fork and the branch you created on the right.
Fill in the details and hit Create Pull Request.
"},{"location":"NewUserGuide/#responding-to-feedback","title":"Responding to feedback","text":"The repository owners will often request some changes to our code by commenting on the Pull Request. To update the code in the Pull Request, simply make the additional changes in your local files, stage them, and commit them just as before. Then, git push
. Remember, we don't need any other parameters on the push this time. After pushing new changes, we should see the PR update almost instantly.
Once the owners are satisfied with the changes, they will approve and merge the PR. And we're done!
"},{"location":"NewUserGuide/#cleaning-up","title":"Cleaning up","text":"Once the PR is merged, we can delete our fork and delete the folder containing our local clone. We can keep the fork around if we intend to contribute further, but the main
branch of the fork will not automatically pull in the latest changes from the official repo. It will get further and further out of date, which may cause problems with future pull requests. To avoid this, we'll need to pull in the changes from the main
branch of the official repo into our fork. This is out of scope for this guide, so we'll leave this an exercise for the reader.
Download the latest release: ExPerfAnalyzer.ps1
"},{"location":"Performance/ExPerfAnalyzer/#running-the-script","title":"Running the script","text":".\\ExPerfAnalyzer.ps1 .\\EXSERVER01_FULL_000001.BLG\n
"},{"location":"Performance/ExPerfAnalyzer/#registering-script-as-a-default-handler","title":"Registering script as a default handler","text":".\\ExPerfAnalyzer.ps1 -RegisterHandler\n
PowerShell must be running as an administrator for this command to work. The script will register itself as a shell handler for perfmon .blg files. You can then right-click any .blg file and select ExPerfAnalyzer to quickly parse the file.
"},{"location":"Performance/ExPerfAnalyzer/#inspiration","title":"Inspiration","text":"This script was inspired by Performance Analysis of Logs (PAL) and PMA.VBS (an internal tool used by Windows support).
"},{"location":"Performance/ExPerfAnalyzer/#faq","title":"FAQ","text":"This takes forever to run.
It's faster than PAL.
Why don't I just use PAL?
You could, but PAL takes even longer to run and throws a lot of false positives.
What's the expected running time?
v0.2.2 and an Intel Core i7-4810MQ @ 2.8Ghz processed a 1GB perfmon sitting on an SSD in 11 seconds.
Can I edit this script however I'd like?
Yes, that's the magic of open source software!
Do you accept pull requests? Can I contribute to the script?
Of course!
Download the latest release: ExPerfWiz.ps1
ExPerfWiz is a PowerShell based script to help automate the collection of performance data on Exchange 2013, 2016 and 2019 servers.\u00a0 Supported operating systems are Windows 2012, 2012 R2, 2016 and 2019 Core and Standard.
"},{"location":"Performance/ExPerfWiz/#initial-run","title":"Initial Run","text":"Run .\\ExPerfWiz.ps1 from an elevated shell.
Once a prompt is returned all of the ExPerfWiz functions will now be available to run.
"},{"location":"Performance/ExPerfWiz/#common-usage","title":"Common Usage","text":"New-ExPerfWiz -FolderPath C:\\PerfWiz -StartOnCreate
The following functions are provided by ExPerfWiz to manage data collection.
"},{"location":"Performance/ExPerfWiz/#get-experfwiz","title":"Get-ExPerfWiz
","text":"Gets ExPerfWiz data collector sets
Switch Description Default Name Name of the Data Collector set Exchange_PerfWiz Server Name of the Server Local Machine ShowLog Displays the ExPerfWiz Log file NA"},{"location":"Performance/ExPerfWiz/#new-experfwiz","title":"New-ExPerfWiz
","text":"Creates an ExPerfWiz data collector set Will overwrite any existing sets with the same name
Switch Description Default Circular Enabled or Disable circular logging Disabled Duration How long should the performance data be collected 08:00:00 FolderPath Output Path for performance logs NA Interval How often the performance data should be collected. 5s MaxSize Maximum size of the perfmon log in MegaBytes (256-4096) 1024Mb Name The name of the data collector set Exchange_PerfWiz Server Name of the server where the perfmon collector should be created Local Machine StartOnCreate Starts the counter set as soon as it is created False StartTime Daily time to start perfmon counter NA Template XML perfmon template file that should be loaded to create the data collector set. Exch_13_16_19_Full.xml Threads Includes threads in the counter set. False"},{"location":"Performance/ExPerfWiz/#set-experfwiz","title":"Set-ExPerfWiz
","text":"Modifies the configuration of an existing data collector set.
Switch Description Default Duration How long should the performance data be collected 08:00:00 Interval How often the performance data should be collected. 5s MaxSize Maximum size of the perfmon log in MegaBytes (256-4096) 1024Mb Name The name of the data collector set Exchange_PerfWiz Server Name of the server where the perfmon collector should be created Local Machine StartTime Daily time to start perfmon counter NA Quiet Suppress output False"},{"location":"Performance/ExPerfWiz/#remove-experfwiz","title":"Remove-ExPerfWiz
","text":"Removes an ExPerfWiz data collector set
Switch Description Default Name Name of the Perfmon Collector set Exchange_PerfWiz Server Name of the server to remove the collector set from Local Machine"},{"location":"Performance/ExPerfWiz/#start-experfwiz","title":"Start-ExPerfWiz
","text":"Starts an ExPerfWiz data collector set
Switch Description Default Name The Name of the Data Collector set to start Exchange_PerfWiz Server Name of the remote server to start the data collector set on. Local Machine"},{"location":"Performance/ExPerfWiz/#stop-experfwiz","title":"Stop-ExPerfWiz
","text":"Stops an ExPerfWiz data collector set
Switch Description Default Name Name of the data collector set to stop. Exchange_PerfWiz Server Name of the server to stop the collector set on. Local Machine"},{"location":"Performance/ExPerfWiz/#example-usage","title":"Example Usage","text":""},{"location":"Performance/ExPerfWiz/#default-usage-for-data-gathering","title":"Default usage for data gathering","text":"New-ExPerfWiz -FolderPath C:\\ExPerfWiz -StartOnCreate
Stop-ExPerfWiz
New-ExPerfWiz -FolderPath C:\\ExPerfWiz -server RemoteExchServer
Get-ExchangeServer | Foreach {New-ExPerfWiz -FolderPath C:\\ExPerfWiz -StartOnCreate -Server $_.name}
Download the latest release: SimplePerf.ps1
This script is a stripped-down and streamlined performance log collector for Exchange Server.
"},{"location":"Performance/SimplePerf/#common-examples","title":"Common Examples","text":".\\SimplePerf.ps1 -Start\n
Starts a collector using Exchange counter defaults. The collector is non-circular, will run for 8 hours, has a 5-second interval, has a max file size of 1 GB, and saves the logs to C:\\SimplePerf. .\\SimplePerf.ps1 -Start -IncludeCounters \"\\Thread\"\n
Starts a collector using Exchange counter defaults plus all \\Thread counters. The collector is non-circular, will run for 8 hours, has a 5-second interval, has a max file size of 1 GB, and saves the logs to C:\\SimplePerf. .\\SimplePerf.ps1 -Start -Duration 02:00:00 -Interval 30 -MaximumSizeInMB 512 -OutputFolder C:\\PerfLogs\n
Starts a collector using Exchange counter defaults. The collector is non-circular, will run for 2 hours, has a 30-second interval, has a max file size of 512 MB, and saves the logs to C:\\PerfLogs. .\\SimplePerf.ps1 -Start -Duration 02:00:00 -Interval 30 -MaximumSizeInMB 1024 -Circular -OutputFolder C:\\PerfLogs\n
Starts a collector using Exchange counter defaults. The collector is circular, will run for 2 hours, has a 30-second interval, has a max file size of 1024 MB, and saves the logs to C:\\PerfLogs. .\\SimplePerf.ps1 -Stop\n
Stops a running SimplePerf. Get-ExchangeServer | .\\SimplePerf.ps1 -Start\n
Starts a SimplePerf with the default options on all Exchange servers. \"SRV1\", \"SRV2\", \"SRV3\" | .\\SimplePerf.ps1 -Start\n
Starts a SimplePerf with the default options on the three named servers. \"SRV1\", \"SRV2\", \"SRV3\" | .\\SimplePerf.ps1 -Stop\n
Stops a running SimplePerf on the three named servers."},{"location":"Performance/SimplePerf/#using-named-collectors","title":"Using Named Collectors","text":"It is possible to run several SimplePerf collectors on the same computer at the same time by providing the -CollectorName parameter. For example:
.\\SimplePerf -Start -Interval 60 -CollectorName \"Minute\"\n.\\SimplePerf -Start -Interval 5 -CollectorName \"FiveSeconds\"\n
When using collector names, the same name must be provided to the -Stop command:
.\\SimplePerf -Stop -CollectorName \"Minute\"\n.\\SimplePerf -Stop -CollectorName \"FiveSeconds\"\n
"},{"location":"Performance/SimplePerf/#counter-name-filters","title":"Counter Name Filters","text":"The counters collected by SimplePerf can be controlled with a combination of three parameters: -Scenario, -IncludeCounters, and -ExcludeCounters.
Currently, there are only two scenarios: Exchange and None. The Exchange scenario is a common set of counters for Exchange Server, similar to what ExPerfWiz would collect. None is a completely empty counter set.
-IncludeCounters and -ExcludeCounters perform a StartsWith match against the counter name. This makes it possible to collect a large number of counters with minimal syntax. For example:
.\\SimplePerf.ps1 -Start -IncludeCounters \"\\MSExchange\", \"\\Microsoft Exchange\"\n
This example starts a SimplePerf using the Exchange scenario, but then it includes every counter starting with either MSExchange or Microsoft Exchange. .\\SimplePerf.ps1 -Start -IncludeCounters \"\\MSExchange\", \"\\Microsoft Exchange\" -Scenario \"None\"\n
This example starts a SimplePerf collecting all the matching Exchange counters without including any default counters at all, because the None scenario was specified. .\\SimplePerf.ps1 -Start -ExcludeCounters \"\\MSExchange Transport\"\n
In this example, we use the Exchange scenario as a starting point, but then we remove all counters starting with MSExchange Transport. Note that individual counters can be excluded even if the counter set has been included. To illustrate:
In this screenshot we see all the counters that exist for the Thread set.
If we tell SimplePerf to include \"\\Thread\", then it simply collects the whole object.
However, if we tell it to Include \"\\Thread\" but exclude \"\\Thread(*)\\Priority\", we see that it has correctly expanded the Thread object and is collecting all counters except \"Priority Current\" and \"Priority Base\".
This filtering mechanism makes it easy to customize the counter set with minimal text. To check the result of your counter filters, add the -Verbose switch, or check the counters txt file in $env:TEMP.
Note that the resulting set can only show counters that exist on the local machine. For instance, you won't see any Exchange counters in the Verbose output if the script is not running on an Exchange Server.
"},{"location":"Performance/SimplePerf/#language-support","title":"Language Support","text":"SimplePerf works regardless of the current language. It does this by translating the provided counter filters to whatever the current server language happens to be. This means that counter names must always be provided in English, even when the current language is not English.
For example, here is the same command from the earlier example running on a server where Spanish is the current language:
"},{"location":"PublicFolders/SourceSideValidations/","title":"SourceSideValidations","text":"Download the latest release: SourceSideValidations.ps1
This script performs pre-migration public folder checks for Exchange 2013, 2016, and 2019. For Exchange 2010, please use previous script found here.
"},{"location":"PublicFolders/SourceSideValidations/#syntax","title":"Syntax","text":"SourceSideValidations.ps1\n [-StartFresh <bool>]\n [-SlowTraversal]\n [-ResultsFile <string>]\n [-SkipVersionCheck]\n [-Tests <string[]>]\n [<CommonParameters>]\nSourceSideValidations.ps1 -RemoveInvalidPermissions\n [-ResultsFile <string>]\n [-SkipVersionCheck]\n [<CommonParameters>]\nSourceSideValidations.ps1 -SummarizePreviousResults\n [-ResultsFile <string>]\n [-SkipVersionCheck]\n [<CommonParameters>]\n
"},{"location":"PublicFolders/SourceSideValidations/#output","title":"Output","text":"The script will generate the following files. Usually the only one we care about is ValidationResults.csv. The others are purely for saving time on subsequent runs.
File Name Content Use IpmSubtree.csv A subset of properties of all Public Folders Running with -StartFresh $false loads this file instead of retrieving fresh data Statistics.csv EntryID, item count, and size of every folder Running with -StartFresh $false loads this file instead of retrieving fresh data NonIpmSubtree.csv A subset of properties of all System Folders Running with -StartFresh $false loads this file instead of retrieving fresh data ValidationResults.csv Information about any issues found. This is file we want to examine to understand any issues found. The script will display a summary of what it found, and in many cases it will provide an example command that uses input from this file to fix the problem."},{"location":"PublicFolders/SourceSideValidations/#tests","title":"Tests","text":"The script performs the following tests. The ValidationResults.csv can be filtered by ResultType to identify the respective folders.
Test Category ResultType Criteria DumpsterMapping BadDumpsterMapping DumpsterEntryId is null, or the dumpster is not in \\NON_IPM_SUBTREE\\DUMPSTER_ROOT, or the DumpsterEntryId of the dumpster does not point back to the folder. Limit ChildCount The folder has more than 10,000 direct child folders. Limit EmptyFolder The folder and all its child folders (recursive) have no items. Limit FolderPathDepth The folder path is greater than 299 folders deep. Limit HierarchyCount There are more than 250,000 total folders in the hierarchy. Limit HierarchyAndDumpsterCount There are more than 250,000 total folders if you count both the folders and their dumpsters. Limit ItemCount The folder has more than 1,000,000 items. Limit NoStatistics Get-PublicFolderStatistics did not return any statistics for these folders. ItemCount, TotalItemSize, and EmptyFolder tests were skipped. Limit TotalItemSize The items directly in this folder (not child folders) add up to more than 25 GB. MailEnabledFolder MailDisabledWithProxyGuid The folder is not mail-enabled, but it has the GUID of an Active Directory object in its MailRecipientGuid property. MailEnabledFolder MailEnabledSystemFolder The folder is a system folder, which should not be mail-enabled. MailEnabledFolder MailEnabledWithNoADObject The folder is mail-enabled, but it has no Active Directory object. MailEnabledFolder OrphanedMPF An Active Directory object exists, but it is not linked to any folder. MailEnabledFolder OrphanedMPFDuplicate An Active Directory object exists, but it points to a public folder which points to a different object. MailEnabledFolder OrphanedMPFDisconnected An Active Directory object exists, but it points to a public folder that is mail-disabled. FolderName SpecialCharacters Folder name contains @, /, or \\. Permission BadPermission The permission does not refer to a valid entity."},{"location":"PublicFolders/SourceSideValidations/#usage","title":"Usage","text":"Typically, the script should be run with no parameters:
.\\SourceSideValidations.ps1\n
Progress indicators are displayed as it collects data and validates the results.
The final test, which checks permissions, will usually take much longer than the other tests.
When all the tests are done, the script provides a summary of what it found, along with example commands that fix some issues.
In this example output, the script calls out four issues.
First, it points out that we have 111,124 folders that are completely empty (this is a lab). Note the ResultType of EmptyFolder. If we want to see the list of empty folders, we can open up ValidationResults.csv in Excel, filter for a ResultType of EmptyFolder, and then we see all those results:
For these folders, no action is required. The script is just giving us information.
The next thing it calls out is that 4 folders have problematic characters in the name. The output tells us these have a ResultType of SpecialCharacters. Filtering for that in the CSV, we see the folders.
Fortunately, the script gives us a command we can run to fix all the names. We can copy and paste the command it gave us, let it run, and then spot check the result.
Now that the names are fixed, we move on to the next item.
The script tells us we have a mail public folder object for a public folder that is mail-disabled. For this type of problem, we need to examine the folder and figure out what we want to do. The CSV file gives us the DN of the mail object and the entry ID of the folder, which we can use to examine the two objects.
The folder says MailEnabled is False, yet we have a MailPublicFolder which points to it. We need to decide whether we want the folder to receive email or not. For this lab, I decide I do want the folder to be mail-enabled, so I remove the orphaned MailPublicFolder and then mail-enable the folder.
I also confirm the new object has the same email address as the old one. This might need to be adjusted manually in some cases, but here I didn't have to.
Finally, the script says we have 9,850 invalid permissions. Fortunately, this is another one that is easy to fix, as the script provides a command.
This one is going to take a while. Once completed, we can rerun SourceSideValidations to make sure all the issues are resolved.
If you close the shell and you need to see the summary results again, use the -SummarizePreviousResults switch.
.\\SourceSideValidations -SummarizePreviousResults\n
The script reads the output file and repeats the instructions on what to do. You can also summarize the results from previous runs, or point to files in other locations, by providing the -ResultsFile parameter.
"},{"location":"PublicFolders/ValidateEXOPFDumpster/","title":"ValidateExoPfDumpster","text":"Download the latest release: ValidateExoPfDumpster.ps1
This script investigates public folders/items deletion operations failures & propose FIXes for mitigation. The script is working to validate the below conditions over the affected public folder
"},{"location":"PublicFolders/ValidateEXOPFDumpster/#checks-run","title":"Checks run:","text":"ValidateExoPfDumpster.ps1\n [-PFolder <string[]>]\n [-AffectedUser <string[]>]\n [-ExportPath <string[]>]\n
"},{"location":"PublicFolders/ValidateEXOPFDumpster/#output","title":"Output","text":"The script will generate the public folder validation checks failures & proposed Fixes results on screen and will generate same results on ValidatePFDumpsterREPORT.txt file as well. There are other files generated for either script logging purposes or sometimes for logs to be shared with Microsoft personnel in case issues encountered requires microsoft support team intervention.
File Name Content Use ValidatePFDumpsterREPORT.txt Information about any blockers found The script will display what it found, and in many cases it will provide a mitigation to fix the problem ValidatePFDumpsterChecksLogging.csv Information about the reason of script failure to run The file will display errors encountered on running the script and at which stage PublicFolderInfo.xml All required information about the affected public folder This log file to be shared with Microsoft personnel"},{"location":"PublicFolders/ValidateEXOPFDumpster/#usage","title":"Usage","text":"Typically, the script should run with PFolder identity parameter as illustrated below:
.\\ValidateExoPfDumpster.ps1 -PFolder \\pf1\n
The script will prompt for affected public folder identity/EntryID if it wasn't provided using PFolder parameter then it will prompt for global administrator username & password to connect to EXO by default it validates if the issue is specific to the Public folder \"e.g. all users are affected\"
If the issue happens only with a specific user on that case an affected user smtp address is required to be provided
In this example output, the script calls out two blockers.
It points out the below blockers: - Neither user nor Default user have sufficient permissions to delete items inside the public folder - Public folder size has exceeded Individual Public Folder ProhibitPostQuota value
In this example output, the script calls out four blockers.
It points out the below issues: - Public folder & its dumpster doesn't have the same content public folder mailbox - Public folder EntryId & DumpsterEntryID values are not mapped properly - Public folder size has exceeded Organization DefaultPublicFolderProhibitPostQuota value - Public folder dumpster has 1 subfolder
The script created a log file containing all the required information \"PublicFolderInfo.xml\" to be shared with Microsoft personnel for the first two blockers & provided mitigation for the last two blockers and you can see same results under ValidatePFDumpsterREPORT.txt file.
"},{"location":"PublicFolders/ValidateMailEnabledPublicFolders/","title":"ValidateMailEnabledPublicFolders","text":"
Download the latest release: ValidateMailEnabledPublicFolders.ps1
This script performs pre-migration checks on mail-enabled folders on Exchange 2010 and up. Note that these checks are also included in the new SourceSideValidations.ps1 for 2013 and up.
"},{"location":"Retention/Get-MRMDetails/","title":"Get-MRMDetails","text":"Download the latest release: Get-MRMDetails.ps1
This script will gather the MRM configuration for a given user. It will collect the current MRM Policy and Tags for the Exchange Organization, the current MRM Policy and Tags applied to the user, the current Exchange Diagnostics Logs for the user, and Exchange Audit logs for the mailbox selected. The resulting data will allow you to see what tags are applied to the user and when the Managed Folder Assistant has run against the user. It also will grab the Admin Audit log so that we can tell if the Tags or Polices have been modified and who modified them.
To run the script, at minimum you will need a valid SMTP Address for a user. Then you can review the associated logs that are generated from the script.
Syntax:
.\\Get-MRMDetails.ps1 -Mailbox <user>\n
Example to collect the MRM Details from rob@contoso.com:
.\\Get-MRMDetails.ps1 -Mailbox rob@contoso.com\n
"},{"location":"Search/Troubleshoot-ModernSearch/","title":"Troubleshoot-ModernSearch","text":"Download the latest release: Troubleshoot-ModernSearch.ps1
This script is still in development. However, this should be able to quickly determine if an item is indexed or not and why it isn't indexed. Just provide the full message subject and the mailbox identity and it will dump out the information needed to determine if the message is indexed or not.
"},{"location":"Search/Troubleshoot-ModernSearch/#parameters","title":"Parameters","text":"Parameter Description MailboxIdentity Provide the identity of the mailbox that you wish to be looking at. If you are able to find it viaGet-Mailbox
it is able to be used here. ItemSubject Provide the message's subject name. Must be exact if -MatchSubjectSubstring
isn't used. This includes if there is a trailing space at the end of the message subject. MatchSubjectSubstring Enable to perform a like
search in the mailbox with the value that is passed with -ItemSubject
. FolderName If you want to scope the search to a folder for better and faster results, include the name of the folder that the message is in. DocumentId If you already know the document ID number for the mailbox, provide this. This can not be use with -ItemSubject
parameter. Category Provides a breakdown of the messages in the mailbox for that index category state. Possible options are: All
, Indexed
, PartiallyIndexed
, NotIndexed
, Corrupted
, Stale
, and ShouldNotBeIndexed
. NOTE: Depending the item count, this can take a long while to complete. GroupMessages To group the messages by Indexing Error Message and Permanent failure state or not. By Disabling this, you get more properties displayed of the message as well. Server Provide a list of possible servers that you wish to get mailbox statistics for all the active databases on that server. SortByProperty Provide the property that you wish to have the information sorted by in the output to screen. Default is to sort by FullyIndexPercentage
ExcludeFullyIndexedMailboxes When look at the multiple mailbox statistics, we don't want to view the mailboxes that are fully indexed without any indexing problems. QueryString Include a string that you are using to try to find this item, we will run an instant query against it to see if we can find it. IsArchive Enable if you want to look at the archive mailbox. IsPublicFolder Enable if you want to look at a public folder mailbox."},{"location":"Search/Troubleshoot-ModernSearch/#examples","title":"Examples","text":"This is an example of how to run a basic query again a single item.
.\\Troubleshoot-ModernSearch.ps1 -MailboxIdentity han@solo.com -ItemSubject \"Test Message\"\n
This is an example of how to run the script when you want to query multiple items with a similar subject name.
.\\Troubleshoot-ModernSearch.ps1 -MailboxIdentity \"Zelda01\" -ItemSubject \"Initial Indexing\" -MatchSubjectSubstring\n
This is an example of how to run the script against an Archive Mailbox.
.\\Troubleshoot-ModernSearch.ps1 -MailboxIdentity han@solo.com -ItemSubject \"Test Message\" -IsArchive\n
This is an example of how to run the script against a Public Folder Mailbox
.\\Troubleshoot-ModernSearch.ps1 -MailboxIdentity PFMailbox2 -ItemSubject \"My Item Test\" -IsPublicFolder\n
This is an example of how to run the script to get all the index state categories
.\\Troubleshoot-ModernSearch.ps1 -MailboxIdentity \"Zelda02\" -Category \"All\"\n
This is an example of how to run the script to get all the non indexed items
.\\Troubleshoot-ModernSearch.ps1 -MailboxIdentity \"Zelda02\" -Category \"NotIndexed\"\n
This is an example of how to run the script to get all the active mailboxes on a server
.\\Troubleshoot-ModernSearch.ps1 -Server \"Solo-E19A\"\n
"},{"location":"Security/CVE-2023-21709/","title":"CVE-2023-21709","text":"Download the latest release: CVE-2023-21709.ps1
Note
Microsoft has released the Windows Server October 2023 security update to address the TokenCacheModule vulnerability. While the script can still be used to mitigate the vulnerability, the recommended solution is to install the Windows Server October 2023 (or later) security update instead. The update and more information can be found here: CVE-2023-36434
The CVE-2023-21709.ps1
script can be used to mitigate the CVE-2023-21709
and CVE-2023-36434
vulnerability by removing the TokenCacheModule
from IIS. It can also be used to restore a previously removed TokenCacheModule
.
Note
The script doesn't perform any check if the Windows Server October 2023 (or later) security update has been installed before restoring the TokenCacheModule. Make sure to install the update before restoring the module.
The script allows you to explicitly specify a subset of Exchange servers on which the TokenCacheModule
should be removed or restored. It's also possible to exclude a subset of Exchange servers from the operation performed by the script.
This script must be run as Administrator in Exchange Management Shell (EMS)
. The user must be a member of the Organization Management
role group.
This syntax removes the TokenCacheModule
from all Exchange servers within the organization.
.\\CVE-2023-21709.ps1\n
This syntax removes the TokenCacheModule
from ExchangeSrv01
and ExchangeSrv02
.
.\\CVE-2023-21709.ps1 -ExchangeServerNames ExchangeSrv01, ExchangeSrv02\n
This syntax removes the TokenCacheModule
from all Exchange servers within the organization except ExchangeSrv02
.
.\\CVE-2023-21709.ps1 -SkipExchangeServerNames ExchangeSrv02\n
This syntax restores the TokenCacheModule
on all Exchange servers within the organization.
.\\CVE-2023-21709.ps1 -Rollback\n
"},{"location":"Security/CVE-2023-21709/#parameters","title":"Parameters","text":"Parameter Description ExchangeServerNames A list of Exchange servers that you want to run the script against. This can be used for applying or rollback the CVE-2023-21709
configuration change. SkipExchangeServerNames A list of Exchange servers that you don't want to execute the TokenCacheModule
configuration action. Rollback Switch parameter to rollback the CVE-2023-21709
configuration change and add the TokenCacheModule
back to IIS. ScriptUpdateOnly Switch parameter to only update the script without performing any other actions. SkipVersionCheck Switch parameter to skip the automatic version check and script update."},{"location":"Security/EOMT/","title":"Exchange On-premises Mitigation Tool (EOMT)","text":"Download the latest release: EOMT.ps1
This script contains mitigations to help address the following vulnerabilities.
This is the most effective way to help quickly protect and mitigate your Exchange Servers prior to patching. We recommend this script over the previous ExchangeMitigations.ps1 script. The Exchange On-premises Mitigation Tool automatically downloads any dependencies and runs the Microsoft Safety Scanner. This a better approach for Exchange deployments with Internet access and for those who want an attempt at automated remediation. We have not observed any impact to Exchange Server functionality via these mitigation methods. EOMT.ps1 is completely automated and uses familiar mitigation methods previously documented. This script has four operations it performs:
This a better approach for Exchange deployments with Internet access and for those who want an attempt at automated remediation. We have not observed any impact to Exchange Server functionality via these mitigation methods nor do these mitigation methods make any direct changes that disable features of Exchange.
Use of the Exchange On-premises Mitigation Tool and the Microsoft Safety Scanner are subject to the terms of the Microsoft Privacy Statement: https://aka.ms/privacy
"},{"location":"Security/EOMT/#requirements-to-run-the-exchange-on-premises-mitigation-tool","title":"Requirements to run the Exchange On-premises Mitigation Tool","text":"The Exchange On-premises Mitigation Tool runs the Microsoft Safety Scanner in a quick scan mode. If you suspect any compromise, we highly recommend you run it in the FULL SCAN mode. FULL SCAN mode can take a long time but if you are not running Microsoft Defender AV as your default AV, FULL SCAN will be required to remediate threats.
"},{"location":"Security/EOMT/#exchange-on-premises-mitigation-tool-examples","title":"Exchange On-premises Mitigation Tool Examples","text":"The default recommended way of using EOMT.ps1. This will determine if your server is vulnerable, mitigate if vulnerable, and run MSERT in quick scan mode. If the server is not vulnerable only MSERT quick scan will run.
.\\EOMT.ps1
To run a Full MSERT Scan - We only recommend this option only if the initial quick scan discovered threats. The full scan may take hours or days to complete.
.\\EOMT.ps1 -RunFullScan -DoNotRunMitigation
To run the Exchange On-premises Mitigation Tool with MSERT in detect only mode - MSERT will not remediate detected threats.
.\\EOMT.ps1 -DoNotRemediate
To roll back the Exchange On-premises Mitigation Tool mitigations
.\\EOMT.ps1 -RollbackMitigation
Note: If ExchangeMitigations.ps1 was used previously to apply mitigations, Use ExchangeMitigations.ps1 for rollback.
+NEW EOMT will now AutoUpdate by downloading the latest version from GitHub. To prevent EOMT from fetching updates to EOMT.ps1 from the internet.
.\\EOMT.ps1 -DoNotAutoUpdateEOMT
Question: What mode should I run EOMT.ps1 in by default?
Answer: By default, EOMT.ps1 should be run without any parameters:
This will run the default mode which does the following: 1. Checks if your server is vulnerable based on the presence of the SU patch or Exchange version. 2. Downloads and installs the IIS URL rewrite tool (only if vulnerable). 3. Applies the URL rewrite mitigation (only if vulnerable). 4. Runs the Microsoft Safety Scanner in \"Quick Scan\" mode (vulnerable or not).
Question: What if I run a full scan and it's affecting the resources of my servers?
Answer: You can terminate the process of the scan by running the following command in an Administrative PowerShell session.
Stop-Process -Name msert
Question: What is the real difference between this script (EOMT.PS1) and the previous script Microsoft released (ExchangeMitigations.Ps1).
Answer: The Exchange On-premises Mitigation Tool was released to help pull together multiple mitigation and response steps, whereas the previous script simply enabled mitigations. Some details on what each do:
"},{"location":"Security/EOMT/#eomtps1","title":"EOMT.PS1","text":"Question: What if I do not have an external internet connection from my Exchange server?
Answer: If you do not have an external internet connection, you can still use the legacy script (ExchangeMitigations.ps1) and other steps from the mitigation blog post: Microsoft Exchange Server Vulnerabilities Mitigations \u2013 March 2021
Question: If I have already ran the mitigations previously, will the Exchange On-premises Mitigation Tool roll back any of the mitigations?
Answer: No, please use the legacy script (ExchangeMitigations.ps1) to do rollback. The legacy script supports rollback for the mitigations the Exchange On-premises Mitigation Tool applied.
"},{"location":"Security/EOMTv2/","title":"Exchange On-premises Mitigation Tool v2 (EOMTv2)","text":"Please read carefully
The vulnerability addressed by this mitigation script has been addressed in latest Exchange Server Security Updates (starting with November 2022 SU). Mitigations can become insufficient to protect against all variations of an attack. Thus, installation of an applicable SU is the only way to protect your servers. Once you install the updates, you can rollback the mitigation as described in the Exchange On-premises Mitigation Tool v2 Examples section.
Download the latest release: EOMTv2.ps1
The Exchange On-premises Mitigation Tool v2 script (EOMTv2.ps1) can be used to mitigate CVE-2022-41040. This script does the following:
Use of the Exchange On-premises Mitigation Tool v2 is subject to the terms of the Microsoft Privacy Statement: https://aka.ms/privacy
"},{"location":"Security/EOMTv2/#requirements-to-run-the-exchange-on-premises-mitigation-tool-v2","title":"Requirements to run the Exchange On-premises Mitigation Tool v2","text":"NOTE: The script has to be executed individually for each server.
"},{"location":"Security/EOMTv2/#exchange-on-premises-mitigation-tool-v2-examples","title":"Exchange On-premises Mitigation Tool v2 Examples","text":"The default recommended way of using EOMTv2.ps1. This will apply the URL rewrite mitigation. If IIS URL rewrite module is not installed, this will also download and install the module.
.\\EOMTv2.ps1\n
To roll back EOMTv2 mitigations run
.\\EOMTv2.ps1 -RollbackMitigation\n
"},{"location":"Security/ExchangeExtendedProtectionManagement/","title":"ExchangeExtendedProtectionManagement","text":"Download the latest release: ExchangeExtendedProtectionManagement.ps1
The Exchange Extended Protection Management is a script to help automate the Extended Protection feature on the Windows Authentication Module on Exchange Servers. Prior to configuration, it validates that all servers that we are trying to enable Extended Protection on and the servers that already have Extended Protection enabled have the same TLS settings and other prerequisites that are required for Extended Protection to be enabled successfully.
Tip
The Exchange Server Extended Protection documentation can be found on the Microsoft Learn platform: Configure Windows Extended Protection in Exchange Server
"},{"location":"Security/ExchangeExtendedProtectionManagement/#requirements","title":"Requirements","text":"The user must be in Organization Management
and must run this script from an elevated Exchange Management Shell (EMS) command prompt.
This syntax enables Extended Protection on all Exchange Servers that are online that we can reach.
PS C:\\> .\\ExchangeExtendedProtectionManagement.ps1\n
This syntax enables Extended Protection on only the Exchange Servers specified in the -ExchangeServerNames parameter. However, TLS checks will still occur against all servers, and the script will confirm that the TLS settings are correct on all servers with Extended Protection enabled and all servers specified in the -ExchangeServerNames parameter.
PS C:\\> .\\ExchangeExtendedProtectionManagement.ps1 -ExchangeServerNames <Array_of_Server_Names>\n
This syntax enables Extended Protection on all Exchange Servers that are online that we can reach, excluding any servers specified in the -SkipExchangeServerNames parameter. As above, TLS checks will still occur against all servers, and the script will confirm that the TLS settings are correct on all servers with Extended Protection enabled and all servers being enabled.
PS C:\\> .\\ExchangeExtendedProtectionManagement.ps1 -SkipExchangeServerNames <Array_of_Server_Names>\n
This syntax collects the possible IP addresses to be used for the IP restriction for a virtual directory. Plus the location to store the file.
NOTE: This is only to assist you with the IP collections. You must verify the list to make sure it is accurate and contains all the required IP addresses.
PS C:\\> .\\ExchangeExtendedProtectionManagement.ps1 -FindExchangeServerIPAddresses -OutputFilePath \"C:\\temp\\ExchangeIPs.txt\"\n
This syntax will enable Extended Protection for all virtual directories and set EWS Backend virtual directory to None and then proceed to set IP restriction for the EWS Backend virtual directory for all servers online, while providing the IP address list.
PS C:\\> .\\ExchangeExtendedProtectionManagement.ps1 -RestrictType \"EWSBackend\" -IPRangeFilePath \"C:\\temp\\ExchangeIPs.txt\"\n
This syntax will verify the IP restrictions for the EWS Backend virtual directory.
PS C:\\> .\\ExchangeExtendedProtectionManagement.ps1 -ValidateType \"RestrictTypeEWSBackend\" -IPRangeFilePath \"C:\\temp\\ExchangeIPs.txt\"\n
This syntax rolls back the Extended Protection configuration for all the Exchange Servers that are online where Extended Protection was previously configured.
NOTE: This is done by restoring the applicationHost.config file back to the previous state before Extended Protection was configured. If other changes occurred after this configuration, those changes will be lost.
PS C:\\> .\\ExchangeExtendedProtectionManagement.ps1 -RollbackType \"RestoreIISAppConfig\"\n
This syntax rolls back the Extended Protection mitigation of IP restriction for the EWS Backend virtual directory of all the Exchange Server that are online where Extended Protection was previously configured.
PS C:\\> .\\ExchangeExtendedProtectionManagement.ps1 -RollbackType \"RestrictTypeEWSBackend\"\n
This syntax displays the current Extended Protection configuration for all the Exchange Servers that are online.
PS C:\\> .\\ExchangeExtendedProtectionManagement.ps1 -ShowExtendedProtection\n
"},{"location":"Security/ExchangeExtendedProtectionManagement/#parameters","title":"Parameters","text":"Parameter Description ExchangeServerNames A list of servers to pass that you want to run the script against. This can be used for configuration or rollback. SkipExchangeServerNames A list of server to pass that you don't want to execute the script for configuration or rollback. ShowExtendedProtection Show the current configuration of Extended Protection for the passed server list. FindExchangeServerIPAddresses Use this to collect a list of the Exchange Server IPs that should be used for IP Restriction. OutputFilePath Is a custom file path to be used to export the list of Exchange Server IPs collected from FindExchangeServerIPAddresses
. Default value is the local location IPList.txt
. IPRangeFilePath Is the path to the file that contains all the IP Addresses or subnets that are needed to be in the IP Allow list for Mitigation. RestrictType To enable a IP Restriction on a virtual directory. Must be used with IPRangeFilePath
. The following values are allowed: EWSBackend
ValidateType To verify if the IP Restrictions have been applied correctly. Must be used with IPRangeFilePath
. The following values are allowed: RestrictTypeEWSBackend
RollbackType Using this parameter will allow you to rollback using the type you specified. The following values are allowed: RestoreIISAppConfig
, RestrictTypeEWSBackend
SkipAutoUpdate Skips over the Auto Update feature to download the latest version of the script."},{"location":"Security/ExchangeMitigations/","title":"ExchangeMitigations","text":"Download the latest release: ExchangeMitigations.ps1
This script contains 4 mitigations to help address the following vulnerabilities:
For more information on each mitigation please visit https://aka.ms/exchangevulns
This should only be used as a temporary mitigation until your Exchange Servers can be fully patched, recommended guidance is to apply all of the mitigations at once.
For this script to work you must have the IIS URL Rewrite Module installed which can be done via this script using the -FullPathToMSI parameter.
For IIS 10 and higher URL Rewrite Module 2.1 must be installed, you can download version 2.1 here:
For IIS 8.5 and lower Rewrite Module 2.0 must be installed, you can download version 2.0 here:
x86 - https://www.microsoft.com/en-us/download/details.aspx?id=5747
x64 - https://www.microsoft.com/en-us/download/details.aspx?id=7435
Installing URL Rewrite version 2.1 on IIS versions 8.5 and lower may cause IIS and Exchange to become unstable. If there is a mismatch between the URL Rewrite module and IIS version, ExchangeMitigations.ps1 will not apply the mitigation for CVE-2021-26855. You must uninstall the URL Rewrite module and reinstall the correct version.
Script requires PowerShell 3.0 and later and must be executed from an elevated PowerShell Session.
Download the latest release here:
Download ExchangeMitigations.ps1
To apply all mitigations with MSI install
.\\ExchangeMitigations.ps1 -FullPathToMSI \"FullPathToMSI\" -WebSiteNames \"Default Web Site\" -ApplyAllMitigations
To apply all mitigations without MSI install
.\\ExchangeMitigations.ps1 -WebSiteNames \"Default Web Site\" -ApplyAllMitigations -Verbose
To rollback all mitigations
.\\ExchangeMitigations.ps1 -WebSiteNames \"Default Web Site\" -RollbackAllMitigation
To apply multiple or specific mitigations (out of the 4)
.\\ExchangeMitigations.ps1 -WebSiteNames \"Default Web Site\" -ApplyECPAppPoolMitigation -ApplyOABAppPoolMitigation
To rollback multiple or specific mitigations
.\\ExchangeMitigations.ps1 -WebSiteNames \"Default Web Site\" -RollbackECPAppPoolMitigation -RollbackOABAppPoolMitigation
Documentation Moved
This documentation has been moved to Microsoft Learn. Please read Configure Windows Extended Protection in Exchange Server for more information.
"},{"location":"Security/Test-CVE-2021-34470/","title":"Test-CVE-2021-34470","text":"Download the latest release: Test-CVE-2021-34470.ps1
Environments running supported versions of Exchange Server should address CVE-2021-34470 by applying the CU and/or SU for the respective versions of Exchange, as described in Released: July 2021 Exchange Server Security Updates.
Environments where the latest version of Exchange Server is any version before Exchange 2013, or environments where all Exchange servers have been removed, can use this script to address the vulnerability.
"},{"location":"Security/Test-CVE-2021-34470/#examples","title":"Examples","text":"Check for the vulnerability:
.\\Test-CVE-2021-34470.ps1
Fix the vulnerability if found:
.\\Test-CVE-2021-34470.ps1 -ApplyFix
Note that the user must be a Schema Admin to use the -ApplyFix switch.
"},{"location":"Security/Test-ProxyLogon/","title":"Test-ProxyLogon.ps1","text":"Download the latest release: Test-ProxyLogon.ps1
Formerly known as Test-Hafnium, this script automates all four of the commands found in the Hafnium blog post. It also has a progress bar and some performance tweaks to make the CVE-2021-26855 test run much faster.
"},{"location":"Security/Test-ProxyLogon/#usage","title":"Usage","text":"The most typical usage of this script is to check all Exchange servers and save the reports, by using the following syntax from Exchange Management Shell:
Get-ExchangeServer | .\\Test-ProxyLogon.ps1 -OutPath $home\\desktop\\logs
To check the local server only, just run the script:
.\\Test-ProxyLogon.ps1 -OutPath $home\\desktop\\logs
To check the local server and copy the identified logs and files to the OutPath:
.\\Test-ProxyLogon.ps1 -OutPath $home\\desktop\\logs -CollectFiles
To display the results without saving them, pass -DisplayOnly:
.\\Test-ProxyLogon.ps1 -DisplayOnly
The script says it found suspicious files, and it lists a bunch of zip files. What does this mean?
The script will flag any zip/7x/rar files that it finds in ProgramData. As noted in this blog post, web shells have been observed using such files for exfiltration. An administrator should review the files to determine if they are valid. Determining if a zip file is a valid part of an installed product is outside the scope of this script, and whitelisting files by name would only encourage the use of those specific names by attackers.
I'm having trouble running the script on Exchange 2010.
If PowerShell 3 is present, the script can be run on Exchange 2010. It will not run-on PowerShell 2. One can also enable PS Remoting and run the script remotely against Exchange 2010. However, the script has minimal functionality in these scenarios, as Exchange 2010 is only affected by one of the four announced exploits - CVE-2021-26857. Further, this exploit is only available if the Unified Messaging role is present. As a result, it is often easier to simply run the Get-EventLog command from the blog post, rather than using Test-ProxyLogon.
"},{"location":"Security/CVE-2023-23397/","title":"CVE-2023-23397 script","text":"Download the latest release: CVE-2023-23397.ps1
CVE-2023-23397.ps1 is a script that checks Exchange messaging items (mail, calendar and tasks) to see whether a property is populated with a non empty string value. It is up to the admin to determine if the value is malicious or not. If required, admins can use this script to clean up the property for items that are malicious or even delete the items permanently. Please see CVE-2023-23397 for more information.
There are two modes for the script: Audit and Cleanup.
Audit Mode: Script provides a CSV file with details of items that have the property populated.
Cleanup Mode: Script performs cleanup on detected items by either clearing the property or deleting the item.
"},{"location":"Security/CVE-2023-23397/#steps-to-run-the-script","title":"Steps to run the script:","text":"Run the script in audit mode.
For organizations with large number of mailboxes: It is recommended to break up the mailbox list into multiple files, so the script can be run against mailboxes in batches. Here is an example of how to break up the mailboxes into batches of 1000:
$batchSize = 1000; $batchNumber = 1; $count = 0; Get-Mailbox -ResultSize Unlimited | Select PrimarySmtpAddress | % {\n if ($count++ -ge $batchSize) { $batchNumber++; $count = 0; }\n Export-Csv -InputObject $_ -Path \"Batch$batchNumber.csv\" -Append\n}\n\n# Then run against the batches similar to this:\nImport-Csv .\\BatchFileName.csv | .\\CVE-2023-23397.ps1 -Environment Online\n
If the script execution finishes with \"No vulnerable item found\", no further action is required.
To run this script in an on-premises Exchange Server environment, you need to use an account with the ApplicationImpersonation
management role. You can create a new role group with the required permissions by running the following PowerShell command in an elevated Exchange Management Shell (EMS):
New-RoleGroup -Name \"CVE-2023-23397-Script\" -Roles \"ApplicationImpersonation\" -Description \"Permission to run the CVE-2023-23397 script\"\nAdd-RoleGroupMember -Identity \"CVE-2023-23397-Script\" -Member \"<UserWhoRunsTheScript>\"\n
The script uses Exchange Web Services (EWS) to fetch items from user mailboxes. So, the machine on which the script is run should be able to make EWS calls to your Exchange server. You can also create a new Throttling Policy to prevent the user who runs the script from being throttled. Make sure to revert the throttling policy after you're done running the script.
Please note that this is for Exchange on-premises environments only.
New-ThrottlingPolicy \"CVE-2023-23397-Script\"\nSet-ThrottlingPolicy \"CVE-2023-23397-Script\" -EWSMaxConcurrency Unlimited -EWSMaxSubscriptions Unlimited -CPAMaxConcurrency Unlimited -EwsCutoffBalance Unlimited -EwsMaxBurst Unlimited -EwsRechargeRate Unlimited\nSet-Mailbox -Identity \"<UserWhoRunsTheScript>\" -ThrottlingPolicy \"CVE-2023-23397-Script\"\n
"},{"location":"Security/CVE-2023-23397/#prerequisites-to-run-the-script-for-exchange-online","title":"Prerequisites to run the script for Exchange Online","text":"To run this script in an Exchange Online environment, you need to be a Global Administrator
or an Application Administrator
. The script will create an application with full access permission on all the mailboxes.
Furthermore it is possible to use a certificate to run the script in Audit
and Cleanup
mode. This is called Certificate Based Authentication (CBA)
. The steps are outlined in the FAQ section.
NOTE: The script uses Microsoft.Exchange.WebServices.dll to make EWS calls. The script will try to download the DLL and use it. However, if it is unable to, you will need to download the DLL and specify the path.
"},{"location":"Security/CVE-2023-23397/#steps-to-download-microsoftexchangewebservicesdll","title":"Steps to Download Microsoft.Exchange.WebServices.dll:","text":"-DLLPath
parameter when running the script.The script accepts the following parameters:
Parameter Description Environment Specify the environment where you are running the script. This parameter is required. CreateAzureApplication Use this parameter to create an Azure AD application that can be used for running the script in Exchange Online. DeleteAzureApplication Use this parameter to delete the Azure AD application. UserMailboxes Use this parameter to provide a list of user primary SMTP addresses. You can pipe the addresses while running. This parameter is required in Audit mode. StartTimeFilter Use this parameter to provide start time filter. (Format: \"mm/dd/yyyy hh:mm:ss\") EndTimeFilter Use this parameter to provide end time filter. (Format: \"mm/dd/yyyy hh:mm:ss\") CleanupAction Use this parameter to provide type of cleanup action you want to perform (ClearProperty/ClearItem). CleanupInfoFilePath Use this parameter to provide path to the CSV file containing the details of messages to be cleaned up. EWSExchange2013 Use this switch if you are running on Exchange Server 2013 mailboxes. DLLPath Provide the path to Microsoft.Exchange.WebServices.dll. This is an optional parameter. AzureApplicationName Provide the name of the application which the script should create. This is an optional parameter. The default name is CVE-2023-23397Application. CertificateThumbprint Provide the thumbprint of the certificate which was uploaded to the Azure application. The certificate must exist under the 'Cert:\\CurrentUser\\My' path on the machine. It can only be used if the private key exists and is accessible. AppId Provide the ID of the application which was created in Azure and which is required to run the script in audit or cleanup mode. The ID can be found within the Azure application under 'Overview' and is labeled as: 'Application (client) ID'. If you don't specify this parameter but specify theCertificateThumbprint
parameter, the script will ask you to logon to query the required information. Organization Provide the ID of your organization. It can be provided in GUID format or by using your onmicrosoft.com domain. If you don't specify this parameter but specify the CertificateThumbprint
parameter, the script will ask you to logon to query the required information. AzureEnvironment Provide the Azure Environment name. This is an optional parameter. The default value is Global
. MaxCSVLength Provide the maximum number of rows the script should create in the CSV while running in Audit mode. This is an optional parameter. The default is 200,000. EWSServerURL Provide the EWS endpoint. If not provided, the script will make an Autodiscover call to get it. This parameter works only with Exchange Server. ScriptUpdateOnly This optional parameter allows you to only update the script without performing any other actions. SkipVersionCheck This optional parameter allows you to skip the automatic version check and script update. IgnoreCertificateMismatch This optional parameter lets you ignore TLS certificate mismatch errors. Credential This optional parameter lets you pass admin credentials when running on Exchange Server. UseSearchFolders This parameter causes the script to use deep-traversal search folders, significantly improving performance. SearchFolderCleanup This parameter cleans up any search folders left behind by the asynchronous search feature. It must be used together with the UseSearchFolders
parameter. SkipSearchFolderCreation This parameter skips the creation of search folders. It must be used together with the UseSearchFolders
parameter. TimeoutSeconds This optional parameter specifies the timeout on the EWS ExchangeService object. The default is 300 seconds (5 minutes)."},{"location":"Security/CVE-2023-23397/#set-exchange-online-cloud-specific-values","title":"Set Exchange Online Cloud Specific values:","text":"You can use the AzureEnvironment
parameter to specify the cloud against which the script runs. By default, the script will run against the Global (worldwide) service. Supported values are:
Execute the script in audit mode as an admin with the ApplicationImpersonation management role. For scanning on-premises mailboxes, the Environment value should be \"Onprem\" and you should provide the EWS URL of your Exchange server in EWSServerURL property. The script will ask for a login prompt, and the username must be provided.
Note
The username which is passed to the script, must be specified in the UPN format where the domain-part is a domain accepted by the Exchange Server.
Optionally, you can use the Credential flag to provide admin credentials in PSCredential format. Set the EWSServerURL parameter to specify the EWS URL if the Autodiscover call fails.
"},{"location":"Security/CVE-2023-23397/#examples","title":"Examples:","text":"This syntax runs the script to audit all the mailboxes.
PS C:\\> Get-Mailbox -ResultSize Unlimited | .\\CVE-2023-23397.ps1 -Environment Onprem\n
Note: If there are Exchange 2013 servers in the environment with Exchange 2016 or 2019, the script may not be able to open mailboxes on Exchange 2013 and may give the following error:
If the above error appears, run the script with an additional parameter EWSExchange2013, as shown below.
PS C:\\> Get-Mailbox -ResultSize Unlimited | .\\CVE-2023-23397.ps1 -Environment Onprem -EWSExchange2013\n
This syntax runs the script to audit all mailboxes for items that were created during a specific period.
PS C:\\> Get-Mailbox -ResultSize Unlimited | .\\CVE-2023-23397.ps1 -Environment Onprem -StartTimeFilter \"01/01/2023 00:00:00\" -EndTimeFilter \"01/01/2024 00:00:00\"\n
"},{"location":"Security/CVE-2023-23397/#cleanup-mode","title":"Cleanup Mode:","text":"The script provides a list of all the messages containing the problematic property in the mailboxes of users specified in an AuditResult_timestamp.CSV file. Admins should analyze this file and mark (with a \"Y\") messages for which either the property is to be cleaned or the message must be removed.
Step 1 Mark the messages for cleanup by entering \"Y\" instead of \"N\" in the cleanup column of CSV file.
Step 2 Choose either to remove the message or only the problematic property in the next step by specifying CleanupAction as \"ClearItem\" or \"ClearProperty.\" Execute the script as follows to remove the message or property marked with Y in the CSV file.
"},{"location":"Security/CVE-2023-23397/#examples_1","title":"Examples:","text":"This syntax runs the script to clear the problematic property from messages:
PS C:\\> .\\CVE-2023-23397.ps1 -Environment Onprem -CleanupAction ClearProperty -CleanupInfoFilePath <Path to modified CSV>\n
This syntax runs the script to delete messages containing the malicious property
PS C:\\> .\\CVE-2023-23397.ps1 -Environment Onprem -CleanupAction ClearItem -CleanupInfoFilePath <Path to modified CSV>\n
"},{"location":"Security/CVE-2023-23397/#running-against-exchange-online-mailboxes","title":"Running Against Exchange Online Mailboxes","text":"First, execute the script in Audit mode as an admin with Global Administrator
or Application Administrator
role. For scanning online mailboxes, the Environment parameter should be \"Online.\"
While scanning Exchange Online mailboxes, the script needs an Azure AD app that has delegate permissions for all Exchange Online mailboxes. You can create the application using the script. And once the application is no longer required, you can delete the application using the script as well.
"},{"location":"Security/CVE-2023-23397/#managing-azureadapplication","title":"Managing AzureADApplication:","text":""},{"location":"Security/CVE-2023-23397/#examples_2","title":"Examples:","text":"This syntax runs the script to create an Azure application
PS C:\\> .\\CVE-2023-23397.ps1 -CreateAzureApplication\n
This syntax runs the script to delete the Azure application created by the script
PS C:\\> .\\CVE-2023-23397.ps1 -DeleteAzureApplication\n
"},{"location":"Security/CVE-2023-23397/#audit-mode_1","title":"Audit Mode:","text":""},{"location":"Security/CVE-2023-23397/#examples_3","title":"Examples:","text":"This syntax runs the script to Audit all mailboxes in Exchange Online.
NOTE: Connect to EXO with Exchange Online PowerShell session
PS C:\\> Get-EXOMailbox -ResultSize Unlimited | .\\CVE-2023-23397.ps1 -Environment \"Online\"\n
This syntax runs the script to Audit all mailboxes for items that were during a specific period.
PS C:\\> Get-EXOMailbox -ResultSize Unlimited | .\\CVE-2023-23397.ps1 -Environment \"Online\" -StartTimeFilter \"01/01/2023 00:00:00\" -EndTimeFilter \"01/01/2024 00:00:00\"\n
This syntax runs the script to Audit all mailboxes by using a certificate to authenticate and using the improved SearchFolder functionality.
PS C:\\> Get-EXOMailbox -ResultSize Unlimited | .\\CVE-2023-23397.ps1 -Environment Online -CertificateThumbprint <Thumbprint of the certificate> -AppId <Application Id of the 'CVE-2023-23397Application' app> -Organization contoso.onmicrosoft.com -UseSearchFolders\n
"},{"location":"Security/CVE-2023-23397/#cleanup-mode_1","title":"Cleanup Mode:","text":""},{"location":"Security/CVE-2023-23397/#examples_4","title":"Examples:","text":"This syntax runs the script to clear the problematic property from messages.
PS C:\\> .\\CVE-2023-23397.ps1 -Environment \"Online\" -CleanupAction ClearProperty -CleanupInfoFilePath <Path to modified CSV>\n
This syntax runs the script to delete messages containing the problematic property.
PS C:\\> .\\CVE-2023-23397.ps1 -Environment \"Online\" -CleanupAction ClearItem -CleanupInfoFilePath <Path to modified CSV>\n
This syntax runs the script to delete messages containing the problematic property. It uses a certificate to acquire the required tokens.
PS C:\\> .\\CVE-2023-23397.ps1 -Environment \"Online\" -CleanupAction ClearItem -CleanupInfoFilePath <Path to modified CSV> -CertificateThumbprint <Thumbprint of the certificate> -AppId <Application Id of the 'CVE-2023-23397Application' app> -Organization contoso.onmicrosoft.com\n
"},{"location":"Security/CVE-2023-23397/#script-execution-errors-and-troubleshooting","title":"Script execution errors and troubleshooting","text":""},{"location":"Security/CVE-2023-23397/#exchange-server-doesnt-support-the-requested-version","title":"Exchange Server doesn't support the requested version","text":"If there are Exchange 2013 servers in an environment with Exchange 2016 or Exchange 2019, the script may not be able to open mailboxes on Exchange 2013 and may give the following error:
If the above error appears, run the script with the EWSExchange2013 parameter:
PS C:\\> Get-Mailbox -ResultSize Unlimited | .\\CVE-2023-23397.ps1 -Environment Onprem -EWSExchange2013\n
"},{"location":"Security/CVE-2023-23397/#blocked-autodiscover-redirection","title":"Blocked Autodiscover redirection","text":"If Autodiscover fails due to a redirection error and the above error appears, provide the EWS URL using the EWSServerURL parameter.
"},{"location":"Security/CVE-2023-23397/#invalid-client-secret-provided","title":"Invalid client secret provided","text":"While running the script in Exchange Online, you might see the above error intermittently. Re-running the script should resolve the issue. If it occurs frequently, then remove the Azure application you have created using -DeleteAzureApplication parameter and then recreate it using -CreateAzureApplication parameter.
"},{"location":"Security/CVE-2023-23397/#cannot-convert-the-microsoftexchangewebservicesdatawebcredentials","title":"\"Cannot convert the \"Microsoft.Exchange.WebServices.Data.WebCredentials\"","text":"Incorrect link was provided to download Microsoft.Exchange.WebServices.dll originally that is causing this issue. Follow these steps to correct this problem.
lib\\40\\Microsoft.Exchange.WebServices.dll
)You are getting a 401 unauthorized when trying to provide the -EWSServerURL
parameter to the script. The possible causes can be due to bad credentials provided or the URL endpoint is not working correctly. Try to provide the credentials again to start off with. If that doesn't work, does the URL work when using a browser? You should get a result like this:
If you don't get a response looking like this after you are prompted for a username and password, then this could be the problem. Try to see if either the FQDN, https://localhost/ews/exchange.asmx
, or https://127.0.0.1/ews/exchange.asmx
works instead. If one of those do, use that instead for the -EWSServerURL
parameter.
NOTE: Make sure to include -IgnoreCertificateMismatch
if using localhost or 127.0.0.1
This feature changes the way Audit mode works to be dramatically faster in most environments. The original approach searches folders synchronously one by one. When using the new switch, we perform two passes. In the first pass, we create a search folder that searches the whole mailbox. In the second pass, we collect the results. This often reduces the time to run the Audit mode by 80% or more.
To use the new feature, use the same syntax as before, but add -UseSearchFolders. For example:
NOTE: Connect to EXO with Exchange Online PowerShell session
Get-EXOMailbox -ResultSize Unlimited | .\\CVE-2023-23397.ps1 -Environment Online -UseSearchFolders\n
This switch only applies to Audit mode. Cleanup mode has no syntax changes. To take maximum advantage of the search folders, it's best to leave them in place until cleanup is done, so you can repeatedly and quickly search for any new items. After cleanup is completed, the search folders can be removed with:
Get-EXOMailbox -ResultSize Unlimited | .\\CVE-2023-23397.ps1 -Environment Online -UseSearchFolders -SearchFolderCleanup\n
"},{"location":"Security/CVE-2023-23397/FAQ/#what-is-the-relationship-of-exchange-server-march-2023-su-and-outlook-fix-for-cve-2023-23397","title":"What is the relationship of Exchange Server March 2023 SU and Outlook fix for CVE-2023-23397?","text":"Those two updates are completely independent from each other. Exchange SUs address Exchange vulnerabilities and security improvements. We mentioned the Outlook\u00a0CVE-2023-23397 update in the Exchange March SU release to raise the awareness to our customers, as we know most use Outlook for Windows. Exchange March SU does not address CVE-2023-23397, you need to install Outlook update to address this vulnerability in Outlook.
"},{"location":"Security/CVE-2023-23397/FAQ/#does-the-account-running-the-script-need-to-be-part-of-organization-management","title":"Does the account running the script need to be part of Organization Management?","text":"In OnPrem environments, the account running the script only needs the EWS Impersonation role, which is provided by adding that user to the group as described in the docs.
In Online environments, the account running the script in -CreateAzureApplication mode needs Global Admin role in order to create the Azure application used for impersonation.
"},{"location":"Security/CVE-2023-23397/FAQ/#in-onprem-does-the-script-need-to-be-executed-on-the-exchange-server","title":"In OnPrem, does the script need to be executed on the Exchange Server?","text":"No, the script can be executed from a workstation. There are essentially two parts to running the script. First, we have to get a list of mailboxes. Second, we have to run the script against them. These steps do not necessarily need to be performed by the same user or on the same machine.
If we just want to run the script against a few users, the email addresses can be specified manually:
.\\CVE-2023-23397.ps1 -Environment OnPrem -UserMailboxes \"user1@contoso.com\", \"user2@contoso.com\"\n
For a large number of mailboxes, an Exchange Organization Administrator could create a CSV of mailboxes to process using a command like this:
Get-Mailbox -ResultSize Unlimited | Export-Csv .\\Mailboxes.csv\n
Then, the script could be run against the CSV file on a different machine by a different user using a command like this:
Import-Csv .\\Mailboxes.csv | .\\CVE-2023-23397.ps1 -Environment OnPrem\n
The default script execution appears to be limited to processing 1000 mailboxes, how to execute the script for more than 1000 mailboxes? You can use following steps to break up the mailboxes into multiple files, so the script can be run against mailboxes in batches. Here is an example of how to break up the mailboxes into batches of 1000: $batchSize = 1000; $batchNumber = 1; $count = 0; Get-Mailbox -ResultSize Unlimited | Select PrimarySmtpAddress | % {\n if ($count++ -ge $batchSize) { $batchNumber++; $count = 0; }\n Export-Csv -InputObject $_ -Path \"Batch$batchNumber.csv\" -Append\n}\n
"},{"location":"Security/CVE-2023-23397/FAQ/#in-onprem-does-the-credential-parameter-need-to-be-upn-or-domainuser","title":"In OnPrem, does the -Credential parameter need to be UPN or domain\\user?","text":"Either format can be used. However, by default, the script will attempt to use the username to perform Autodiscover. If Autodiscover does not work for your UPN, or if domain\\user is being specified, then Autodiscover can be skipped by providing the -EWSServerUrl parameter.
.\\CVE-2023-23397.ps1 -Environment OnPrem -EWSServerUrl \"https://exch1.contoso.com/EWS/Exchange.asmx\"\n
"},{"location":"Security/CVE-2023-23397/FAQ/#in-onprem-does-the-impersonation-account-need-to-have-a-mailbox","title":"In OnPrem, does the impersonation account need to have a mailbox?","text":"The latest version of the script no longer requires the impersonation account to have a mailbox if running on Exchange 2016 or later. Exchange 2013 still requires that the impersonation user have a mailbox on prem.
"},{"location":"Security/CVE-2023-23397/FAQ/#why-does-my-output-file-contain-entries-with-empty-pidlidreminderfileparameter-column-or-reminderwav-is-this-an-issue","title":"Why does my output file contain entries with empty PidLidReminderFileParameter column or 'reminder.wav'. Is this an issue?","text":"The search query is only determining if the property PidLidReminderFileParameter is set, including empty values is a set property. It is up to the admin to determine if they to take actions against this particular item.
NOTE: Script version 23.03.22.1926 and after only provide results for non-empty string values. So the columns should no longer be empty when running the audit mode.
"},{"location":"Security/CVE-2023-23397/FAQ/#why-does-my-output-file-only-contain-some-of-my-mailboxes-that-we-searched-against","title":"Why does my output file only contain some of my mailboxes that we searched against?","text":"It will only export individual items that contain the PidLidReminderFileParameter properties set. If the mailbox doesn't have any items that contains this property, it will not be exported out.
"},{"location":"Security/CVE-2023-23397/FAQ/#why-does-my-output-file-contain-multiple-entries-for-the-same-mailbox","title":"Why does my output file contain multiple entries for the same mailbox?","text":"For each individual item that does contain the PidLidReminderFileParameter property, it will be exported out with a item ID that is needed to possibly take action against.
"},{"location":"Security/CVE-2023-23397/FAQ/#what-are-the-required-steps-to-prepare-the-cve-2023-23397application-application-to-support-certificate-based-authentication-cba","title":"What are the required steps to prepare the 'CVE-2023-23397Application' application to support Certificate Based Authentication (CBA)","text":"Step 1: Create the Azure application by running the script with the CreateAzureApplication
. This step must be performed by someone who is Global Administrator
or an Application Administrator
.
Step 2: Generate a new self-signed certificate and export the public part:
$cert = New-SelfSignedCertificate -Subject $env:COMPUTERNAME -CertStoreLocation \"Cert:\\CurrentUser\\My\"\n$cert | Export-Certificate -FilePath MySelfSignedCertificate.cer\n$cert.Thumbprint\n
Important
The certificate must be kept confidential as it allows the owner to access the Azure application without further authentication.
Step 3: Upload the certificate to the CVE-2023-23397Application
Azure application
Go to the Azure Active Directory and search for App registrations
. Select the CVE-2023-23397Application
application and go to Certificates & secrets
. From here, select Certificates
and click on Upload certificate
. Select the MySelfSignedCertificate.cer
file which was created in Step 2, add a descriptive description. Complete the process by clicking on Add
.
The application is now ready for CBA.
"},{"location":"Setup/CopyMissingDlls/","title":"CopyMissingDlls","text":"Download the latest release: CopyMissingDlls.ps1
This script is used to copy over missing dlls that might have occurred during a CU install. This script has a mapping of the location of where the .dll should be on the server and where it should be on the ISO and will attempt to copy it over if the file is detected to be missing on the install location.
Parameter Type Description IsoRoot string The Root location of the ISO. Example:D:
"},{"location":"Setup/FixInstallerCache/","title":"FixInstallerCache","text":"Download the latest release: FixInstallerCache.ps1
This script is used to copy over the missing MSI files from the installer cache.
Parameter Type Description CurrentCuRootDirectory string The root location of the current CU that you are on. MachineName string array One or more machine names from which to copy the required MSI files."},{"location":"Setup/Set-ExchAVExclusions/","title":"Set-ExchAVExclusions","text":"Download the latest release: Set-ExchAVExclusions.ps1
The Script will assist in setting the Antivirus Exclusions according to our documentation for Microsoft Exchange Server.
AV Exclusions Exchange 2016/2019
AV Exclusions Exchange 2013
If you use Windows Defender you can Set the exclusions executing the script without parameters but if you have any other Antivirus solution you can get the full list of Expected Exclusions.
"},{"location":"Setup/Set-ExchAVExclusions/#requirements","title":"Requirements","text":""},{"location":"Setup/Set-ExchAVExclusions/#supported-exchange-server-versions","title":"Supported Exchange Server Versions:","text":"The script can be used to validate the configuration of the following Microsoft Exchange Server versions: - Microsoft Exchange Server 2013 - Microsoft Exchange Server 2016 - Microsoft Exchange Server 2019
The server must have Microsoft Defender to set it and enable it to be effective.
"},{"location":"Setup/Set-ExchAVExclusions/#required-permissions","title":"Required Permissions:","text":"Please make sure that the account used is a member of the Local Administrator
group. This should be fulfilled on Exchange servers by being a member of the Organization Management
group.
This script must be run as Administrator in Exchange Management Shell on an Exchange Server. You do not need to provide any parameters and the script will set the Windows Defender exclusions for the local Exchange server.
If you want to get the full list of expected exclusions you should use the parameter ListRecommendedExclusions
You can export the Exclusion List with the parameter FileName
This will run Set-ExchAVExclusions Script against the local server.
.\\Set-ExchAVExclusions.ps1\n
This will run Set-ExchAVExclusions Script against the local server and show in screen the expected exclusions on screen without setting them.
.\\Set-ExchAVExclusions.ps1 -ListRecommendedExclusions\n
This will run Set-ExchAVExclusions Script against the local server and show in screen the expected exclusions on screen without setting them and write them in the defined FileName
.
.\\Set-ExchAVExclusions.ps1 -ListRecommendedExclusions -FileName .\\Exclusions.txt\n
This will run Set-ExchAVExclusions Script against the local server and write them in the defined FileName
.
.\\Set-ExchAVExclusions.ps1 -FileName .\\Exclusions.txt\n
"},{"location":"Setup/Set-ExchAVExclusions/#outputs","title":"Outputs","text":"Exclusions List File: FileName
Log file: $PSScriptRoot\\SetExchAvExclusions.log
"},{"location":"Setup/SetupLogReviewer/","title":"SetupLogReviewer","text":"Download the latest release: SetupLogReviewer.ps1
This script is meant to be run against the Exchange Setup Logs located at C:\\ExchangeSetupLogs\\ExchangeSetup.log
. You can run this on the server, or on a personal computer.
It currently checks for common prerequisite issues, clearly calling out if you need up run /PrepareAD in your environment and calls out where it needs to be run. It also checks for some other common issue that we have seen in support that we call out and display the actions to the screen.
Parameter Description [string]SetupLog The location of the Exchange Setup Log that needs to be reviewed [switch]DelegatedSetup Use this switch if you are troubleshooting Prerequisites of a Delegated Setup issue"},{"location":"Setup/SetupAssist/","title":"SetupAssist","text":"Download the latest release: SetupAssist.ps1
This script is meant to be run on the system where you are running setup from. It currently checks and displays the following when just running it:
Domain Admins
Schema Admins
Enterprise Admins
Organization Management
Additional Parameters are used for when they are called out from the SetupLogReviewer.ps1
When the CN=Computers container has been renamed or removed from the root of an Active Directory domain, /PrepareAD will fail for certain Cumulative Updates. Please see https://support.microsoft.com/help/5005319 for details.
"},{"location":"Setup/SetupAssist/InstallWatermark/","title":"Install Watermark","text":"After a failed install attempt of Exchange, we can leave behind a watermark that then prevents you from trying to run setup again when trying use unattended mode. To get around this issue, run Setup.exe from the GUI and not the command line. From the GUI, it is able to detect that we had a watermark and tries to pick up where we left off. However, unattended mode fails in the prerequisites check section prior to running and the GUI skips over this section.
Warning
Do NOT remove the watermark from the registry as you will run into more setup issues trying to run steps the server already completed. Run setup from the GUI to allow setup to pick up where the watermark is set at.
"},{"location":"Setup/SetupAssist/ReadOnlyDomainControllerContainer/","title":"Read Only Domain Controller - Domain Controllers OU","text":"A Read Only Domain Controller appears to be in the container other than CN=Domain Controllers. This will cause setup to fail if we attempt to domain prep that domain. The path to the RODC must be CN=DCName,CN=Domain Controllers....
"},{"location":"Setup/SetupAssist/RebootPending/","title":"Reboot Pending","text":"It is best to reboot the server to address these issues. It may take some time after a reboot to have the keys automatically removed. However, if they don't remove automatically, follow these steps to address the issue for the keys that were provided to be a problem.
NOTE: With Component Based Servicing\\RebootPending
you need to do the same for Component Based Servicing\\PackagesPending
prior to RebootPending
NOTE: Follow the steps in this section carefully. Serious problems might occur if you modify the registry incorrectly. Before you modify it, back up the registry for restoration in case problems occur.
"},{"location":"Transport/Compute-TopExoRecipientsFromMessageTrace/","title":"Compute-TopExoRecipientsFromMessageTrace","text":"Download the latest release: Compute-TopExoRecipientsFromMessageTrace.ps1
This script aggregates message trace events hourly and generates a report with the top o365 recipients
"},{"location":"Transport/Compute-TopExoRecipientsFromMessageTrace/#parameters","title":"Parameters","text":"-StartDate
The StartDate parameter specifies the end date of the date range
-EndDate
The EndDate parameter specifies the end date of the date range. It is recommended to limit the start-end date range to a range of hours. i.e. an ~ 5 to 7 hours.
-TimeoutAfter
The TimeoutAfter parameter specifies the number of minutes before the script stop working. This is to make sure that the script does not run for infinity. The default value is 30 minutes.
-Threshold
The Threshold parameter specifies the min threshold for the received limit. It is used to filter the hourly aggregation. The default value is 3600 messages.
"},{"location":"Transport/Compute-TopExoRecipientsFromMessageTrace/#examples","title":"Examples","text":"$results = Compute-TopExoRecipientsFromMessageTrace -StartDate (Get-Date).AddHours(-7) -EndDate (Get-Date)\n
"},{"location":"Transport/Compute-TopExoRecipientsFromMessageTrace/#output","title":"Output","text":"$results.TopRecipients : hourly report for top recipients over the threshold $results.HourlyReport : hourly aggregated message events without applying the threshold $results.MessageTraceEvents: all downloaded message trace events without aggregations
"},{"location":"Transport/ReplayQueueDatabases/","title":"ReplayQueueDatabases","text":"Download the latest release: ReplayQueueDatabases.ps1
When Transport crashes, in some scenarios it will move the current queue database to Messaging.old- and create a new empty database. The old database is usually not needed, unless shadow redundancy was failing. In that case, it can be useful to drain the old queue file to recover those messages.
This script automates the process of replaying many old queue files created by a series of crashes.
"},{"location":"Transport/ReplayQueueDatabases/#syntax","title":"Syntax","text":"ReplayQueueDatabases.ps1\n [-MaxAgeInDays <int>]\n [-RemoveDeliveryDelayedMessages]\n
"},{"location":"Transport/ReplayQueueDatabases/#parameters","title":"Parameters","text":"-MaxAgeInDays <Int32>\n Only replay queue databases newer than this date\n\n Required? false\n Position? 1\n Default value 7\n\n-RemoveDeliveryDelayedMessages [<SwitchParameter>]\n Attempt to remove delivery delay notifications so user mailboxes do not fill up with these while we replay old messages\n\n Required? false\n Position? named\n Default value False\n
"},{"location":"Transport/ReplayQueueDatabases/#usage","title":"Usage","text":"The script must be run from Exchange Management Shell locally on the server where queue databases are being replayed. Preliminary steps before running this script:
Set-MailboxServer $env:ComputerName -DatabaseCopyAutoActivationPolicy Blocked
When the script is run, it takes the following actions.
The EdgeTransport.exe.config is copied to EdgeTransport.exe.config.before-replay.
Begin looping over the folders that were under MaxAgeInDays, starting with the most deeply nested folder.
Continue to the next folder.
When finished with all the folders, stop the Transport services.
Note that when the script is run without -Confirm:$false, it will prompt for nearly every step of this process. This is probably the best approach for most scenarios, so that each step of the script is visible and understood by the user. \"Yes to All\" can be used to remove most of the prompting within the script. However, even with \"Yes to All\", prompts to start and stop services between replays of each database will occur.
If there are many databases to replay, -Confirm:$false can be used to remove all prompting.
"},{"location":"Transport/ReplayQueueDatabases/#cleanup","title":"Cleanup","text":"If the script fails out or is terminated in the middle, the following steps may be needed in order to run the script again and/or return the environment to a normal state.