Generates a report of the maximum message delay for all messages in an Message Tracking Log output.
+
DESCRIPTION
+
Gather message tracking log details of all message to / from a given recipient for a given time range. Useful for determining if a "slow" message was a one off or a pattern.
+
Exchange Online
+
Recommend using Start-HistoricalSearch in EXO to gather a detailed Message Tracking Log for processing.
Note: If you provide a raw message tracking log to the script it WILL generate significant errors since many RECEIVE events and DELIVERY events occur on different servers.
+
PARAMETER
+
-MTLFile
+
CSV output of Message Tracking Log to process.
+
-ReportPath
+
Folder path for the output file.
+
Outputs
+
CSV File
+
+
+
+
Header
+
Description
+
+
+
+
+
MessageID
+
ID of the Message
+
+
+
TimeSent
+
First time we see the message in the MTL
+
+
+
TimeReceived
+
Last delivery time in the MTL
+
+
+
MessageDelay
+
How long before the message was delivered
+
+
+
+
Statistical Summary
+
+
+
+
Statistic
+
Description
+
+
+
+
+
EmailCount
+
Number of email found in the MTL
+
+
+
MaximumDelay
+
Longest delivery delay found in the MTL
+
+
+
MinimumDelay
+
Shortest delivery delay found in the MTL
+
+
+
AverageDelay
+
Average of all delivery delays across all email in the MTL
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 8/23/2024 August 2024 update for Windows After installing the August 2024 update for Windows, MS Exchange Transport service may start crashing Please follow steps in this KB 4/23/2024 March 2024 Security Update for Exchange 2019,2016 After installing the March 2024 Security Update, Search in Outlook (cached mode) may show \"We're having trouble fetching results from the server...\". The search works fine in OWA or Outlook online mode. Please install April 2024 Hotfix Update 4/23/2024 March 2024 Security Update for Exchange 2019,2016 After installing the Security Update, add-ins may stop working with following error \"Add-in Error Something went wrong and we couldn't start this add-in. Please try again later or contact your system administrator Please install April 2024 Hotfix Update 4/23/2024 March 2024 Security Update for Exchange 2019,2016 After installing the March 2024 Security Update, Unread envelope icon is not getting updated after applying March 2024 SU Please install April 2024 Hotfix Update 4/23/2024 March 2024 Security Update for Exchange 2019,2016 After installing the March 2024 Security Update, preview of Office documents in OWA may fail with error \"Sorry, there was a problem and we can't open this document.\" Please install April 2024 Hotfix Update 2/20/2024 CU 14 for Exchange 2019 Environments that are using SSL offloading configuration may face issues with Outlook connectivity issues after upgrading to Exchange 2019 CU14. As announced in August 2023 , by default, starting with CU14, Setup enables the Windows Extended Protection (EP) feature on the Exchange server being installed. Extended Protection isn't supported in environments that use SSL Offloading. SSL termination during SSL Offloading causes Extended Protection to fail. To enable Extended Protection in your Exchange environment, you must not be using SSL offloading with your Load Balancers. Please check this link for more details 2/20/2024 CU 14 for Exchange 2019 Environments that are using SSL offloading configuration may face issues with Outlook connectivity issues after upgrading to Exchange 2019 CU14. As announced in August 2023 , by default, starting with CU14, Setup enables the Windows Extended Protection (EP) feature on the Exchange server being installed. Extended Protection isn't supported in environments that use SSL Offloading. SSL termination during SSL Offloading causes Extended Protection to fail. To enable Extended Protection in your Exchange environment, you must not be using SSL offloading with your Load Balancers. Please check this link for more details 2/19/2024 CU 14 for Exchange 2019 Exchange 2019 CU14 RecoverServer fails while creating \"New-PushNotificationsVirtualDirectory\" with following error: Exception setting \"ExtendedProtectionTokenChecking\": \"Cannot convert null to type \"Microsoft.Exchange.Data.Directory.SystemConfiguration.ExtendedProtectionTokenCheckingMode\" due to enumeration values that are not valid. Please follow the steps from this KB to resolve the issue 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 vulnerability
Updated 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 issue
Updated 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 event Watson 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.
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:
Making sure the source mailbox object is a member of the Mail-Enabled Security Group defined on the MailboxMovePublishedScopes of the source organization relationship
Making sure the source mailbox object ExchangeGuid attribute value matches the one from the target MailUser object, and give you the option to set it
Making sure the source mailbox object ArchiveGuid attribute (if there's an Archive enabled) value matches the one from the target MailUser object, and give you the option to set it
Making sure the source mailbox object has no more than 12 auxArchives
Making sure the source mailbox object has no hold applied
Making sure the source mailbox object TotalDeletedItemsSize is not bigger than Target MailUser recoverable items size
Making sure the source mailbox object LegacyExchangeDN attribute value is present on the target MailUser object as an X500 proxyAddress, and give you the option to set it, as long as the Target MailUser is not DirSynced
Making sure the source mailbox object X500 addresses are also present on the target MailUser object.
Checking if the source mailbox object has an Archive enabled, and if so, check if there's any content on the SubstrateHolds folder of the archive mailbox.
Making sure the target MailUser object PrimarySMTPAddress attribute value is part of the target tenant accepted domains and give you the option to set it to be like the UPN if not true, as long as the Target MailUser is not DirSynced
Making sure the target MailUser object EmailAddresses are all part of the target tenant accepted domains and give you the option to remove them if any doesn't belong to are found, as long as the Target MailUser is not DirSynced
Making sure the target MailUser object ExternalEmailAddress attribute value points to the source Mailbox object PrimarySMTPAddress and give you the option to set it if not true, as long as the Target MailUser is not DirSynced
Verifying if there's a T2T license assigned on either the source or target objects.
Checking if there's an AAD app as described on https://docs.microsoft.com/en-us/microsoft-365/enterprise/cross-tenant-mailbox-migration?view=o365-worldwide#prepare-the-target-destination-tenant-by-creating-the-migration-application-and-secret
Checking if the AAD app on Target has been consented in Source tenant as described on https://docs.microsoft.com/en-us/microsoft-365/enterprise/cross-tenant-mailbox-migration?view=o365-worldwide#prepare-the-source-current-mailbox-location-tenant-by-accepting-the-migration-application-and-configuring-the-organization-relationship
Checking if the target tenant has an Organization Relationship as described on https://docs.microsoft.com/en-us/microsoft-365/enterprise/cross-tenant-mailbox-migration?view=o365-worldwide#prepare-the-target-tenant-by-creating-the-exchange-online-migration-endpoint-and-organization-relationship
Checking if the target tenant has a Migration Endpoint as described on https://docs.microsoft.com/en-us/microsoft-365/enterprise/cross-tenant-mailbox-migration?view=o365-worldwide#prepare-the-target-tenant-by-creating-the-exchange-online-migration-endpoint-and-organization-relationship
Checking if the source tenant has an Organization Relationship as described on https://docs.microsoft.com/en-us/microsoft-365/enterprise/cross-tenant-mailbox-migration?view=o365-worldwide#prepare-the-source-current-mailbox-location-tenant-by-accepting-the-migration-application-and-configuring-the-organization-relationship including a Mail-Enabled security group defined on the MailboxMovePublishedScopes property.
Gather all the necessary information for troubleshooting and send it to Microsoft Support if needed
Because not all scenarios allow access to both tenants by the same person, this will also allow you to collect the source tenant and mailbox information and wrap it into a zip file so the target tenant admin can use it as a source to validate against.
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.
Please make sure you have at least the Exchange Online V2 Powershell module (https://docs.microsoft.com/en-us/powershell/exchange/exchange-online-powershell-v2?view=exchange-ps#install-and-maintain-the-exo-v2-module)
You would need the Microsoft Graph Module (https://learn.microsoft.com/en-us/powershell/microsoftgraph/installation?view=graph-powershell-1.0)
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.
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
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:
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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
"},{"location":"Admin/MonitorExchangeAuthCertificate/#how-to-run","title":"How To Run","text":""},{"location":"Admin/MonitorExchangeAuthCertificate/#examples","title":"Examples:","text":"
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:
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.
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.
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.
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.
NOTE: The ConfigureScriptToRunViaScheduledTask parameter can be combined with the IgnoreHybridConfig and IgnoreUnreachableServers parameter.
It creates a new Exchange Role Group, Auth Certificate Management, which has the following roles assigned: View-Only Configuration, View-Only Recipients, Exchange Server Certificates, Organization Client Access
It creates a new user account with the following User Principal Name (UPN): SystemMailbox{b963af59-3975-4f92-9d58-ad0b1fe3a1a3}@contoso.local
The user account is mail-enabled and hidden from address lists
The user account is added to the local Administrators group on the Exchange Server where the script is executed
The user account is added to the Auth Certificate Management Exchange Role Group
The script is copied to <ExchangeInstallPath>\\Scripts
A new scheduled task is registered to run the script in context of the SystemMailbox{b963af59-3975-4f92-9d58-ad0b1fe3a1a3}@contoso.local user
The 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.
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\".
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
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.
"},{"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.
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:
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.
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.
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:
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.
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/#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
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.
Test-ExchangePropertyPermissions is designed to detect certain schema issues which can manifest as permissions problems and can be challenging to identify manually, including:
Scenarios where a property set does not include all the expected properties.
Scenarios where an objectClass definition is missing expected properties.
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:
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.
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.
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.
"},{"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. 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/#general-overview-of-looking-at-sharing-issues","title":"General Overview of looking at Sharing Issues:","text":"
The first thing to determine is what kind of sharing relationship the users have.
Modern Sharing (New Model Sharing / REST) - Recipient gets a replicated copy of the Owners Calendar in their Mailbox.
Old Model Sharing \u2013 Recipient is granted rights but has to 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 (ICS) \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 output from 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.
Download the latest release: Get-CalendarDiagnosticObjectsSummary.ps1
This script runs the Get-CalendarDiagnosticObjects cmdlet and returns a summarized timeline of actions into clear English. It will also output an easier to read version of the CalLogs (enhanced) as well as a Raw copy of the logs for Developers.
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 in csv format in the current directory. New -ExportToExcel highly recommended for ease of use (all logs in one file, color coding, etc.). First time use will request installing the ImportExcel module. See https://github.com/dfinke/ImportExcel for more information on the ImportExcel module.
Parameters: Explanation: -Identity One (or more) SMTP Address of EXO User Mailbox to query. -Subject Subject of the meeting to query, only valid if Identity is a single user. -MeetingID MeetingID of the meeting to query. - Preferred way to get CalLogs. -TrackingLogs Populate attendee tracking columns in the output. - Only useable with the MeetingID parameter. -Exceptions Include Exception objects in the output. - Only useable with the MeetingID parameter. -ExportToExcel - [NEW Feature] Export the output to an Excel file with formatting. - Running the script for multiple users will create three tabs in the Excel file for each user. If you want to add more users to the Excel file, close the file and rerun with new user. - one tab for Enhanced CalLog - one tab for the TimeLine - Tab one for Raw CalLog -CaseNumber Case Number to include in the Filename of the output. - PrePend <CaseNumber>_ to filename. -ShortLogs Limit Logs to 500 instead of the default 2000, in case the server has trouble responding with the full logs. ---"},{"location":"Calendar/Get-CalendarDiagnosticObjectsSummary/#syntax","title":"Syntax:","text":"
Example to return timeline for a user with MeetingID:
Will create file like .\\123456_CalLogSummary_<MeetingID>.xlsx in current directory."},{"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).
"},{"location":"Calendar/Get-RBASummary/#high-level-steps-for-rba-processing","title":"High-level steps for RBA processing:","text":"
Determine if the Meeting Request is in policy or out of policy.
If the meeting request is Out of Policy, see if the user has rights to create an Out of Policy request and if so, forward it to the Delegates.
If it is In Policy, then either book it or forward it to the delegate based on the settings.
Lastly the RBA does the configured Post Processing steps to format the meeting (delete attachments, rename meeting, etc.)
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.
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.
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:
"},{"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":"
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.
"},{"location":"Databases/VSSTester/#trace-in-circular-mode-until-the-microsoft-exchange-writer-fails","title":"Trace in circular mode until the Microsoft Exchange Writer fails","text":"
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.
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.
Run \"dcomCnFg\" from the run box or command prompt on the problem machine
Expand Component Services then Computers
Right Click on My Computer and select Properties
Select the COM Security tab and select Edit Default... under Access Permissions
If the local Administrators group is not here for Allow for Local and Remote Access, click Add... to add the local Administrators group to the Default Security permissions
Change the locations to the computer name
Type in \"Administrators\" and select Check Names. Making sure the computer account comes up
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.
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.
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:
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.
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\"
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\"
"},{"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 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. 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 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 MailboxDeliveryThrottlingLogs Enable to collect the mailbox delivery throttling logs on the server. Location: (Get-MailboxTransportService $server).MailboxDeliveryThrottlingLogPath 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 TransportConnectivityLogs Aliases ConnectivityLogs, FrontEndConnectivityLogs, HubConnectivityLogs, and MailboxConnectivityLogs. Enable to collect the logs that was set at the following locations: (Get-FrontendTransportService $server).ConnectivityLogPath, (Get-TransportService $server).ConnectivityLogPath, and (Get-MailboxTransportService $server).ConnectivityLogPath TransportLogging Enables the following switches and their logs to be collected. AcceptedRemoteDomain, TransportConnectivityLogs, TransportProtocolLogs, MailboxDeliveryThrottlingLogs, MessageTrackingLogs, PipelineTracingLogs, QueueInformation, ReceiveConnectors, SendConnectors, TransportConfig, TransportRoutingTableLogs, and TransportRules TransportProtocolLogs Aliases ProtocolLogs, FrontEndProtocolLogs, HubProtocolLogs, and MailboxProtocolLogs. Enable to collect the logs that was set at the following locations: (Get-FrontendTransportService $server).ReceiveProtocolLogPath, (Get-FrontendTransportService $server).SendProtocolLogPath, (Get-TransportService $server).ReceiveProtocolLogPath, (Get-TransportService $server).SendProtocolLogPath, (Get-MailboxTransportService $server).ReceiveProtocolLogPath, and (Get-MailboxTransportService $server).SendProtocolLogPath 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 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 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
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:
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.
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. SkipVersionCheck Skip script version verification. ScriptUpdateOnly Just update script version to latest one."},{"location":"Diagnostics/Test-ExchAVExclusions/#outputs","title":"Outputs","text":"
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
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
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":"
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":"
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 2016 - Exchange Server 2019
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:
Organization Management
Domain Admins (only necessary for the DCCoreRatio parameter)
"},{"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.
This cmdlet will run the Health Checker Load Balancing Report for all the Exchange CAS (Front End connections only) and MBX servers (BackEnd connections) in the Organization.
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)
"},{"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-yyyyMMddHHmmss.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.
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:
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
"},{"location":"Diagnostics/HealthChecker/AuthCertificateCheck/#what-does-the-check-do","title":"What does the check do?","text":"
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":"
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!
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:
CloudServicesMailEnabled
If a Receive Connector has the following setting set, it means that the connector is eligible for cloud mail usage:
TlsDomainCapabilities
We only perform testings for the Receive Connectors if:
TransportRole is set to FrontendTransport
We run the following checks:
Connector enabled check:
We show a yellow warning, if the connector is not enabled
Send Connector configured to relay emails via M365 check:
If TlsAuthLevel is set to CertificateValidation
If RequireTLS is set to true
If TlsDomain is set (only performed if TlsAuthLevel is set to DomainValidation)
TlsCertificateName configuration check:
We check if TlsCertificateName has been set
We check if the certificate which is configured in TlsCertificateName exists on the server
If a certificate was configured and detected on the system, we then check if it expires within the next 60 days
If a certificate was configured, we compare it with the TlsCertificateName returned by Get-HybridConfiguration
If a certificate was configured, we check if the syntax is correct and not corrupt. Expected syntax: <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
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.
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
Shows if the EEMS is enabled or not on Organizational level
Shows if the EEMS is enabled or not on Server level
Windows Service Check
MSExchangeMitigation Windows service startup type should be: Automatic
MSExchangeMitigation Windows service status should be: Running
Pattern Service Check
We validate if we can reach the OCS which is used to serve the latest mitigations
OCS Mitigation Service url: https://officeclient.microsoft.com/GetExchangeMitigations
Mitigations Check
Shows which mitigations are currently being applied
Shows which mitigations are currently being blocked
Diagnostic Data Check
Shows if the service is configured to provide diagnostic data to Microsoft or not
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/ExchangeComputerMembership/","title":"Exchange Server Computer Membership","text":""},{"location":"Diagnostics/HealthChecker/ExchangeComputerMembership/#description","title":"Description:","text":"
Checks for the computer object to be members of the Exchange Trusted Subsystem and Exchange Servers security groups by default. It will also make sure the default local system account has the Exchange Trusted Subsystem a member of it as well in order to have the correct access to local system files.
This check is done by using the ADModule with using the cmdlets Get-LocalGroupMember -SID \"S-1-5-32-544\" and running Get-ADPrincipalGroupMembership (Get-ADComputer $env:COMPUTERNAME).DistinguishedName
If an issue is detected, the group will display with where the problem is located. Either Local System Membership if the group isn't part of the local system account or AD Group Membership if the computer object isn't a member of the group provided.
Included in HTML Report?
Yes
"},{"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:
We query the server component state by running Get-ServerComponentState
We query cluster node information by running Get-ClusterNode
We then check for each component if Component.State is not Active
If this is the case, we query the Component.LocalStates and Component.RemoteStates
We validate if both states LocalStates & RemoteStates are the same
We add the information, if LocalStates & RemoteStates are different
We 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
This is a simple check that can be performed from the Exchange On Prem side to quickly determine if the EXO connector is misconfigured. This does not completely determine if the connector is misconfigured, as Health Checker script is not designed to connect to Exchange Online to properly determine if everything is correctly configured for the way you want your mail flow to work.
A Send Connector is determined to be destined for Exchange Online if one of the following is true:
SmartHost endpoint has a *.mail.protection.outlook.com
AddressSpaces address has a *.mail.onmicrosoft.com
For those connectors, we then determine a misconfiguration if one of the following is true:
TLSCertificateName is not set
CloudServicesMailEnabled is not set to true
These are now being flagged as an issue due to some recent changes within Exchange Online.
Some additional configuration concerns are also warned about if one of the following is true:
TLSAuthLevel is not set to CertificateValidation or DomainValidation
TLSDomain is not set to mail.protection.outlook.com if TLSAuthLevel is set to DomainValidation
"},{"location":"Diagnostics/HealthChecker/ExoConnectorCheck/#included-in-html-report","title":"Included in HTML Report?","text":"
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.
Exchange 2013 is not affected by the transport queue issue, however, if invalid patterns has been applied, no newer update pattern with a lower version number (like 2112330001) will be applied.
We check if a folder with number 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
We show some general information about the Processor/Hardware of the Exchange server against which the script was executed.
Hardware Type:
VMWare
AmazonEC2
HyperV
Physical
Unknown
We additionally show the following information, if HardwareType is Physical or AmazonEC2: - Manufacturer - Model - Processor
Number of Processors:
We show an note if ServerType is VMWare [1]
We show an error if we have more than 2 Processors installed
Number of Physical/Logical Cores:
We show a warning if we have more than 24 Physical Cores and running Exchange 2013/2016 [2]
We show a warning if we have more than 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]
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
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.
This provides the application pools on the server with the following information:
State (Started or Stopped)
GCServerEnabled (Garbage Collection Server Enabled - Depends on the RAM on the server if this should be enabled or not on the server. If it should be, Health Checker should call it out.)
RestartConditionSet ( If there is an IIS setting that will automatically restart the App Pool. This is not recommended and will cause issues with client connectivity )
This provides the different locations that you use for different connection endpoints with the following information:
Extended Protection ( The current value )
Ssl Flags ( If enabled and/or Cert based )
IP Filtering Enabled ( If any IP filtering is enabled )
URL Rewrite ( Names of each rule applied at the location )
Authentication ( Provides each type of authentication that is enabled for the location. If anonymous 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
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.
"},{"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:
Go into the file 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
Open the file by using an elevated notepad.exe and change the gcServer Enabled value from false to true
Recycle the 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
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.
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).
This check is looking at the <ExchangeInstallPath>\\Bin\\Search\\Ceres\\Runtime\\1.0\\noderunner.exe.config to look at the memoryLimitMegabytes value. This value should be set to 0 for the best performance. By having it set to 0, we do not limit the noderunner.exe processes. However, in some scenarios you might want to recommend to limit the process memory consumption to prevent server impact. If you do this, it is only recommended as a temporary fix.
"},{"location":"Diagnostics/HealthChecker/NodeRunnerMemoryLimitCheck/#included-in-html-report","title":"Included in HTML Report?","text":"
Users can't receive email messages or connect to their mailbox
"},{"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
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.
Good: PacketsReceivedDiscarded is 0
Warning: PacketsReceivedDiscarded lower than 1000
Error: 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)
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).
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
"},{"location":"Diagnostics/HealthChecker/PagefileSizeCheck/#how-to-set-the-pagefile-to-a-static-value","title":"How to set the pagefile to a static value?","text":"
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]
"},{"location":"Diagnostics/HealthChecker/ProcessorCheck/#how-this-is-checked","title":"How This Is Checked","text":"
"},{"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.
We show a warning if we have more than 24 Logical Cores and running Exchange 2013/2016 [2]
We show a warning if we have more than 48 Logical Cores and running Exchange 2019 [2]
"},{"location":"Diagnostics/HealthChecker/ProcessorCheck/#how-this-is-checked_1","title":"How This Is Checked","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":"
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.
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.
We show a warning if we detect an outstanding pending reboot. We also display the type of pending reboot. We differentiate between:
PendingFileRenameOperations
SccmReboot
SccmRebootPending
ComponentBasedServicingRebootPending
AutoUpdatePendingReboot
UpdateExeVolatile\\Flags
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.
Open regedit to the desired location. Delete the key.
If unable to delete the key, follow these steps:
Right click on it
Open permissions
Click on Advanced
Change ownership to your account
Close Advanced window
Give your account Full Control in Permissions window
Delete the key
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.
The first thing to do is to create a service account which is used to run the script. It is recommended to use a strong password which will be changed regularly. It's also recommended to add the user to the 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).
Now it's time to create the Scheduled Task. This can be done by the help of PowerShell:
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:
Register-ScheduledTask -TaskName 'HealthChecker Daily Run' -InputObject $hcTask -User (Read-Host \"Please enter username in format (Domain\\Username)\") -Password (Read-Host \"Please enter password\")
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.
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":"
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 Disabled
"},{"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
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.
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:
Value Definition Enabled Client and Server Enabled values are set to 1 and DisabledByDefault is set to 0 on the TLS Version. Disabled Client and Server Enabled values are set to 0 and DisabledByDefault is set to 1 on the TLS Version. Half Disabled Client and Server Enabled values are set to either 0 or 1 and DisabledByDefault is set to the opposite where the value doesn't equal Enabled or Disabled.This is not a supported configuration as it doesn't follow the documentation that we have provided. Misconfigured When either the Enabled or the DisabledByDefault values do not match between the Client and Server of that TLS Version.Exchange can be a Client and a Server and this will cause problems and needs to be addressed ASAP.
The location where we are checking for the TLS values are here:
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:
Within Exchange Monitoring, we have a probe that will attempt to clear out the old temp data that is generated from EdgeTransport.exe process. However, this probe definition is defined in the %ExchangeInstallPath%\\Bin\\Monitoring\\Config\\AntiMalware.xml with a hardcoded path options to look. By default, we are only looking at \"D:\\ExchangeTemp\\TransportCts\\UnifiedContent;C:\\Windows\\Temp\\UnifiedContent;C:\\Program Files\\Microsoft\\Exchange Server\\V15\\TransportRoles\\data\\Temp\\UnifiedContent\". Therefore, if Exchange is not installed in at C:\\Program Files\\Microsoft\\Exchange Server\\V15\\ or if the TemporaryStoragePath of the EdgeTransport.exe.config value is anything other than C:\\Program Files\\Microsoft\\Exchange Server\\V15\\TransportRoles\\data\\Temp the probe will not work as intended to clean up the data files.
The only way to get the probe to automatically clean up the temp files is to add the correct location to the %ExchangeInstallPath%\\Bin\\Monitoring\\Config\\AntiMalware.xml file.
Included in HTML Report?
Yes
Additional resources:
Exchange UnifiedContent folder fills up the drive
"},{"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
The script performs different checks to detect vulnerabilities which may lead into a security issue for the Exchange server.
Vulnerability checks performed:
Check the Exchange server build number against known vulnerabilities that exists within a specific build
Check for CVE-2020-0796 SMBv3 vulnerability
Check for CVE-2020-1147 .NET Core & .NET Framework vulnerability
Check for CVE-2021-1730 Download Domains state
Included 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:
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:
Download the latest release: MDOThreatPolicyChecker.ps1
This script checks which Microsoft Defender for Office 365 and Exchange Online Protection threat policies cover a particular user, including anti-malware, anti-phishing, inbound and outbound anti-spam, as well as Safe Attachments and Safe Links policies in case these are licensed for your tenant. In addition, the script can check for threat policies that have inclusion and/or exclusion settings that may be redundant or confusing and lead to missed coverage of users or coverage by an unexpected threat policy.
It also includes an option to show all the actions and settings of the policies that apply to a user.
The script uses Exchange Online cmdlets from Exchange Online module and Microsoft.Graph cmdLets from Microsoft.Graph.Authentication, Microsoft.Graph.Groups and Microsoft.Graph.Users modules.
To run the PowerShell Graph cmdlets used in this script, you need only the following modules from the Microsoft.Graph PowerShell SDK: - Microsoft.Graph.Groups: Contains cmdlets for managing groups, including Get-MgGroup and Get-MgGroupMember. - Microsoft.Graph.Users: Includes cmdlets for managing users, such as Get-MgUser. - Microsoft.Graph.Authentication: Required for authentication purposes and to run any cmdlet that interacts with Microsoft Graph.
You can find the Microsoft Graph modules in the following link: \u00a0\u00a0\u00a0\u00a0https://www.powershellgallery.com/packages/Microsoft.Graph/ \u00a0\u00a0\u00a0\u00a0https://learn.microsoft.com/en-us/powershell/microsoftgraph/installation?view=graph-powershell-1.0#installation
Here's how you can install the required submodules for the PowerShell Graph SDK cmdlets:
Remember to run these commands in a PowerShell session with the appropriate permissions. The -Scope CurrentUser parameter installs the modules for the current user only, which doesn't require administrative privileges.
In the Graph connection you will need the following scopes 'Group.Read.All','User.Read.All'
You can find the Exchange module and information in the following links: \u00a0\u00a0\u00a0\u00a0https://learn.microsoft.com/en-us/powershell/exchange/exchange-online-powershell-v2?view=exchange-ps \u00a0\u00a0\u00a0\u00a0https://www.powershellgallery.com/packages/ExchangeOnlineManagement
"},{"location":"M365/MDO/MDOThreatPolicyChecker/#parameters","title":"Parameters","text":"Parameter Description CsvFilePath Allows you to specify a CSV file with a list of email addresses to check. Csv file must include a first line with header Email. EmailAddress Allows you to specify email address or multiple addresses separated by commas. IncludeMDOPolicies Checks both EOP and MDO (Safe Attachment and Safe Links) policies for user(s) specified in the CSV file or EmailAddress parameter. OnlyMDOPolicies Checks only MDO (Safe Attachment and Safe Links) policies for user(s) specified in the CSV file or EmailAddress parameter. ShowDetailedPolicies In addition to the policy applied, show any policy details that are set to True, On, or not blank. SkipConnectionCheck Skips connection check for Graph and Exchange Online. SkipVersionCheck Skips the version check of the script. ScriptUpdateOnly Just updates script version to latest one."},{"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.
Install Visual Studio Code. You'll need this to develop scripts for this project.
Assuming you're running Windows, install Git For Windows. When it asks for your default editor, choose Visual Studio Code. The rest of the defaults are fine. If you're on a different operating system, refer to the Git documentation for instructions.
Optional but recommended: Install Posh Git in your PowerShell 7+ shell. This adds some useful features such as branch name autocompletion in PowerShell.
"},{"location":"NewUserGuide/#forking-the-repository","title":"Forking the repository","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.
"},{"location":"NewUserGuide/#creating-a-new-branch","title":"Creating a new branch","text":"
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:
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.
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:
File has no newline at the end.
File is missing the required compliance header.
File has no BOM. We require a BOM on scripts.
The formatting of the code itself is not using the correct brace style. This is shown in a warning, followed by diff output illustrating the required change. In addition, a PSScriptAnalyzer check at the end highlights the same issue with the PSPlaceOpenBrace rule.
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.
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!
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.
"},{"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.
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.
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":"
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.
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.
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.
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.
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:
"},{"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:
This example starts a SimplePerf using the Exchange scenario, but then it includes every counter starting with either MSExchange or Microsoft Exchange.
This example starts a SimplePerf collecting all the matching Exchange counters without including any default counters at all, because the None scenario was specified.
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.
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:
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.
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.
Download the latest release: Update-PublicFolderPermissions.ps1
This script can be used to set specific permissions on public folders in bulk or to propagate the full set of permissions from a parent folder to its entire subtree.
Environment Support Exchange Online Supported Exchange 2019 Not Supported"},{"location":"PublicFolders/Update-PublicFolderPermissions/#syntax","title":"Syntax","text":"
This syntax propagates all permissions from \\FolderA to its entire subtree, including Default and Anonymous permissions. Note that this option simply ensures that all the permission entries that exist on \\FolderA also exist on all folders underneath it. It does not remove permissions from child folders when those permissions do not exist on \\FolderA.
"},{"location":"PublicFolders/Update-PublicFolderPermissions/#notes-about-rights-and-roles","title":"Notes about rights and roles","text":"
Historically, the FolderContact right and the FolderVisible right could be toggled on and off without affecting the role. This behavior can still be seen in classic Outlook. If a user is given the Owner role, FolderContact can be toggled on or off. Either way, the user still has the Owner role. Similarly, in classic Outlook, a user can be given the None role with or without FolderVisible.
By contrast, the current EXO cmdlets assume that Owner always includes FolderContact, and None never includes FolderVisible. Therefore, when propagating permissions with this script, None always means None without FolderVisible, and Owner always means Owner with FolderContact.
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
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.
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.
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:
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 via Get-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.
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.
"},{"location":"Security/CVE-2023-21709/#how-to-run","title":"How To Run","text":""},{"location":"Security/CVE-2023-21709/#examples","title":"Examples:","text":"
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.
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/ConfigureFipFsTextExtractionOverrides/","title":"ConfigureFipFsTextExtractionOverrides","text":"
Download the latest release: ConfigureFipFsTextExtractionOverrides.ps1
Note
Starting in the Exchange Server March 2024 security update we disable the use of the Oracle Outside In Technology (also known as OutsideInModule or OIT) in Microsoft Exchange Server due to multiple security vulnerabilities in the module. The OutsideInModule was used by the Microsoft Forefront Filtering Module to extract information from different file types, to perform content inspection as part of the Exchange Server Data Loss Prevention (DLP) or Exchange Transport Rules (ETR) features.
The ConfigureFipFsTextExtractionOverrides.ps1 script can be used to manipulate the usage of OutsideInModule that is disabled by default in the Exchange Server March 2024 security update.
There are two scenarios in which the script could be used:
It can be used to explicitly enable file types that should be processed by the help of the OutsideInModule.
It can be used to override the version of the OutsideInModule that should be used for processing file types, which were explicitly enabled to be processed by the OutsideInModule. After installing the March 2024 security update, Exchange Server uses the latest version of the OutsideInModule version 8.5.7 by default. By activating this override, OutsideInModule version 8.5.3 will be used.
Details about the change that was done as part of the March 2024 security update can be found in KB5037191.
Details about the security vulnerability can be found in the MSRC security advisory.
Warning
Microsoft strongly recommends not overriding the default behavior that was introduced with the March 2024 security update if there are no functional issues that affect your organization's mail flow.
This script must be run as Administrator in Exchange Management Shell (EMS). The user must be a member of the Organization Management role group.
"},{"location":"Security/ConfigureFipFsTextExtractionOverrides/#how-to-run","title":"How To Run","text":""},{"location":"Security/ConfigureFipFsTextExtractionOverrides/#examples","title":"Examples:","text":"
This syntax enables processing of Jpeg and AutoCad file types by the help of the OutsideInModule on the server where the command was executed.
This syntax causes Exchange Server to use the previous version of the OutsideInModule. The override will be enabled on the system on which the script was executed. Note that this can make your system vulnerable to known vulnerabilities in the previous version and should not be used unless explicitly advised by Microsoft.
This syntax restores the configuration.xml from the backup that was created by a previous run of the script on the Exchange server where the script was executed.
"},{"location":"Security/ConfigureFipFsTextExtractionOverrides/#parameters","title":"Parameters","text":"Parameter Description ExchangeServerNames A list of Exchange servers that you want to run the script against. SkipExchangeServerNames A list of Exchange servers that you don't want to execute the configuration action. ConfigureOverride A list of file types that should be allowed to be processed by the OutsideInModule. The following input can be used: XlsbOfficePackage, XlsmOfficePackage, XlsxOfficePackage, ExcelStorage, DocmOfficePackage, DocxOfficePackage, PptmOfficePackage, PptxOfficePackage, WordStorage, PowerPointStorage, VisioStorage, Rtf, Xml, OdfTextDocument, OdfSpreadsheet, OdfPresentation, OneNote, Pdf, Html, AutoCad, Jpeg, Tiff.If you want to enable the previous version of the OutsideInModule (8.5.3) to process file types, you must specify OutsideInModule as file type. Note that the OutsideInModule value cannot be used together with other file type values.The input is case-sensitive. Action String parameter to define the action that should be performed. Input can be Allow or Block. The default value is: Block Rollback Switch parameter to restore the configuration.xml that was backed-up during a previous run of the script. 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.
CVE-2021-26855
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:
+NEW Check for the latest version of EOMT and download it.
Mitigate against current known attacks using CVE-2021-26855 via a URL Rewrite configuration
Scan the Exchange Server using the Microsoft Safety Scanner
Attempt to remediate compromises detected by 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 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":"
External Internet Connection from your Exchange server (required to download the Microsoft Safety Scanner and the IIS URL Rewrite Module).
Windows Server 2008 R2, Server 2012, Server 2012 R2, Server 2016, Server 2019
+New If Operating System is older than Windows Server 2016, must have KB2999226 for IIS Rewrite Module 2.1 to work.
"},{"location":"Security/EOMT/#who-should-run-the-exchange-on-premises-mitigation-tool","title":"Who should run the Exchange On-premises Mitigation Tool","text":"Situation Guidance If you have done nothing to date to patch or mitigate this issue\u2026 Run EOMT.PS1 as soon as possible.This will both attempt to remediate as well as mitigate your servers against further attacks. Once complete, follow patching guidance to update your servers on http://aka.ms/exchangevulns If you have mitigated using any/all of the mitigation guidance Microsoft has given (ExchangeMitigations.Ps1, Blog post, etc..) Run EOMT.PS1 as soon as possible. This will both attempt to remediate as well as mitigate your servers against further attacks. Once complete, follow patching guidance to update your servers on http://aka.ms/exchangevulns If you have already patched your systems and are protected, but did NOT investigate for any adversary activity, indicators of compromise, etc\u2026. Run EOMT.PS1 as soon as possible. This will attempt to remediate any existing compromise that may not have been full remediated before patching. If you have already patched and investigated your systems for any indicators of compromise, etc\u2026. No action is required"},{"location":"Security/EOMT/#important-note-regarding-microsoft-safety-scanner","title":"Important note regarding Microsoft Safety Scanner","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.
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.
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:
Does mitigations for all 4 CVE's - CVE-2021-26855, CVE-2021-26857, CVE-2021-27065 & CVE-2021-26858.
Some of the mitigation methods impact Exchange functionality.
Does not do any scanning for existing compromise or exploitation.
Does not take response actions to existing active identified threats.
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.
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:
Check for the latest version of EOMTv2.ps1 and download it.
Mitigate against current known attacks using CVE-2022-41040 via a URL Rewrite configuration
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":"
PowerShell 3 or later
PowerShell script must be run as Administrator.
IIS 7.5 and later
Exchange 2013 Client Access Server role, Exchange 2016 Mailbox role, or Exchange 2019 Mailbox role
Windows Server 2008 R2, Server 2012, Server 2012 R2, Server 2016, Server 2019
If Operating System is older than Windows Server 2016, must have KB2999226 for IIS Rewrite Module 2.1 to work.
[Optional] External Internet Connection from your Exchange server (required to update the script and install IIS URL rewrite module).
NOTE: The script has to be executed individually for each server.
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.
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.
"},{"location":"Security/ExchangeExtendedProtectionManagement/#how-to-run","title":"How To Run","text":""},{"location":"Security/ExchangeExtendedProtectionManagement/#examples","title":"Examples:","text":"
This syntax will process the prerequisites check only against the servers that you provided. This will execute the same checks as if you were attempting to configure Extended Protection.
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.
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.
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.
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.
This syntax rolls back the Extended Protection configuration for all the Exchange Servers that are online where Extended Protection was previously configured.
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.
NOTE
This is a legacy version of the restore process and is no longer supported. You can still attempt to restore, if the configuration file is detected and is less than 30 days old if a configuration was done with a pervious version of the script. Moving forward, the applicationHost.config file is no longer being used as a backup to restore from. The RestoreConfiguration is the supported replacement.
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.
This syntax will disable Extended Protection configuration for all the Exchange Servers that are online by setting the value at all current configuring locations to None.
"},{"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. PrerequisitesCheckOnly Run the required prerequisites check for the passed server list to know if configuration can be attempted. ShowExtendedProtection Show the current configuration of Extended Protection for the passed server list. ExcludeVirtualDirectories Used to not enable Extended Protection on particular virtual directories. The following values are allowed: EWSFrontEnd. 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, RestoreConfiguration DisableExtendedProtection Using this parameter will disable extended protection for the servers you specify. This is done by setting all the configured locations back to None regardless of what the original value was set to prior to configuration or if it was enabled by default. 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:
CVE-2021-26855
CVE-2021-26857
CVE-2021-27065
CVE-2021-26858
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:
x86 & x64 -https://www.iis.net/downloads/microsoft/url-rewrite
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
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
"},{"location":"Security/Extended-Protection/","title":"Exchange Server Support for Windows Extended Protection","text":"
Documentation Moved
This documentation has been moved to Microsoft Learn. Please read Configure Windows Extended Protection in Exchange Server for more information.
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.
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.
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:
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.
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":"
Fulfill the requirements according to environment (i.e. On-Premises or Online)
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.
If step 2 generates CSV files, review the CSV file; if you find suspicious thing, then go to 5. If you only see blank things or paths to old .wav files, no need to go to step 5.
If you got suspected entries in CSV file, run the script in Cleanup mode
"},{"location":"Security/CVE-2023-23397/#requirements","title":"Requirements","text":""},{"location":"Security/CVE-2023-23397/#prerequisites-to-run-the-script-for-exchange-server-on-premises","title":"Prerequisites to run the script for Exchange Server (on-premises)","text":"
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.
"},{"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":"
Download the nuget package from NuGet Gallery | Microsoft.Exchange.WebServices.2.2.0
Change the extension of the file from .nupkg to .zip
Unzip the package.
Use the dll present at \"\\lib\\40\" location in the package
Provide the path to the DLL for the -DLLPath parameter when running the script.
"},{"location":"Security/CVE-2023-23397/#how-to-run","title":"How To Run","text":""},{"location":"Security/CVE-2023-23397/#script-parameters","title":"Script Parameters","text":"
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 the CertificateThumbprint 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:
AzureEnvironment Cloud Environment Name Global AzureCloud WW USGovernmentL4 AzureUSGovernment GCC USGovernmentL5 AzureUSGovernment DOD ChinaCloud AzureChinaCloud Office365 operated by 21Vianet"},{"location":"Security/CVE-2023-23397/#running-against-exchange-server-on-premises-mailboxes","title":"Running Against Exchange Server (On-Premises) Mailboxes","text":""},{"location":"Security/CVE-2023-23397/#audit-mode","title":"Audit Mode:","text":"
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.
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.
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/#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.
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
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:
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.
Download the correct NuGet Gallery | Microsoft.Exchange.WebServices.2.2.0
Close PowerShell (CRITICAL)
Launch new PowerShell session
Run cmdlet again with providing new dll path ( should be lib\\40\\Microsoft.Exchange.WebServices.dll)
"},{"location":"Security/CVE-2023-23397/#unable-to-connect-to-ews-endpoint-401-unauthorized-on-prem","title":"Unable to connect to EWS endpoint - 401 unauthorized - On Prem.","text":"
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
"},{"location":"Security/CVE-2023-23397/FAQ/","title":"CVE-2023-23397 Frequently Asked Questions","text":""},{"location":"Security/CVE-2023-23397/FAQ/#what-is-the-usesearchfolders-feature","title":"What is the -UseSearchFolders feature?","text":"
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
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:
"},{"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:
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:
"},{"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.
"},{"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:
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.
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.
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.
"},{"location":"Setup/Set-ExchAVExclusions/#how-to-run","title":"How To Run","text":"
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
"},{"location":"Setup/Set-ExchAVExclusions/#parameters","title":"Parameters","text":"Parameter Description ListRecommendedExclusions Get the full list of expected exclusions without set. FileName Export the Exclusion List. SkipVersionCheck Skip script version verification. ScriptUpdateOnly Just update script version to latest one."},{"location":"Setup/Set-ExchAVExclusions/#examples","title":"Examples:","text":"
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.
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.
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:
Current Logged on User and SID
Are you running as an Administrator
Member of Domain Admins
Member of Schema Admins
Member of Enterprise Admins
Member of Organization Management
Current PowerShell Execution Policy setting
Checks to see if you are missing files in the installer cache (only checks to see if they are there, not if they are valid)
More than 1 powershell.exe process up and running
If reboot pending. (Add -Verbose to see where)
The current AD level of readiness for CU upgrading. Displays warnings if a mismatch is detected.
Additional Parameters are used for when they are called out from the SetupLogReviewer.ps1
Parameter Type Description OtherWellKnownObjects switch Tests for deleted objects in the otherWellKnownObjects attribute"},{"location":"Setup/SetupAssist/ComputersContainer/","title":"Computers container renamed or missing","text":"
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.
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....
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.
Open regedit to the desired location. Delete the key.
If unable to delete the key, follow these steps:
Right click on it
Open permissions
Click on Advanced
Change ownership to your account
Close Advanced window
Give your account Full Control in Permissions window
Delete the key
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.
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.
$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
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.
-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
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:
Move all active Mailbox Databases to another DAG member
Run this command from Exchange Management Shell: Set-MailboxServer $env:ComputerName -DatabaseCopyAutoActivationPolicy Blocked
When the script is run, it takes the following actions.
Read the QueueDatabasePath and QueueDatabaseLoggingPath from the EdgeTransport.exe.config file. If these do not match, the script exits. That type of configuration is not yet supported by this script.
Search the QueueDatabasePath for any folders with names matching Message.old-*.
Parse the date string in the folder name to determine if this folder is under the MaxAgeInDays.
Any folders over the MaxAgeInDays are moved to the ReplaySkipped folder in the QueueDatabasePath.
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.
Check if the HubTransport component is in Draining state, and switch it to Draining if it is not.
Stop the Transport services (MSExchangeTransport and MSExchangeFrontEndTransport).
Move the current folder to be replayed to OldReplayQueue in the QueueDatabasePath.
Start the Transport services.
Check every 5 seconds if the queues clear. While waiting, run Remove-Message once a minute to remove any \"Delivery Delayed\" messages.
Once queues are cleared, stop the transport services.
Move OldQueueReplay to a folder inside of Replayed in the QueueDatabasePath, named Replayed-\\<original date on the folder>.
Continue to the next folder.
When finished with all the folders, stop the Transport services.
Overwrite EdgeTransport.exe.config with EdgeTransport.exe.config.before-replay.
Start the Transport services.
Notify the user that they must run the command to take the HubTransport component out of the Draining state when ready.
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.
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.
OldQueueReplay may have been left in place. If it is not clear whether this database was already replayed, Transport services should be started while QueueDatabasePath and QueueDatabaseLoggingPath in EdgeTransport.exe.config still point to OldQueueReplay. Once the queues have drained, Transport can be stopped, and OldQueueReplay can be moved to the Replayed folder.
The EdgeTransport.exe.config may be left pointing to OldQueueReplay. To fix it, replace EdgeTransport.exe.config with the EdgeTransport.exe.config.before-replay, which was the backup of the file prior to any changes.
MSExchangeTransport and MSExchangeFrontEndTransport may need to be started.
The HubTransport component must be set back to Active.
"}]}
\ No newline at end of file
+{"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"]},"docs":[{"location":"","title":"Microsoft Exchange Server Support Scripts","text":"
This project contains scripts for supporting and troubleshooting Microsoft Exchange Server.
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 8/23/2024 August 2024 update for Windows After installing the August 2024 update for Windows, MS Exchange Transport service may start crashing Please follow steps in this KB 4/23/2024 March 2024 Security Update for Exchange 2019,2016 After installing the March 2024 Security Update, Search in Outlook (cached mode) may show \"We're having trouble fetching results from the server...\". The search works fine in OWA or Outlook online mode. Please install April 2024 Hotfix Update 4/23/2024 March 2024 Security Update for Exchange 2019,2016 After installing the Security Update, add-ins may stop working with following error \"Add-in Error Something went wrong and we couldn't start this add-in. Please try again later or contact your system administrator Please install April 2024 Hotfix Update 4/23/2024 March 2024 Security Update for Exchange 2019,2016 After installing the March 2024 Security Update, Unread envelope icon is not getting updated after applying March 2024 SU Please install April 2024 Hotfix Update 4/23/2024 March 2024 Security Update for Exchange 2019,2016 After installing the March 2024 Security Update, preview of Office documents in OWA may fail with error \"Sorry, there was a problem and we can't open this document.\" Please install April 2024 Hotfix Update 2/20/2024 CU 14 for Exchange 2019 Environments that are using SSL offloading configuration may face issues with Outlook connectivity issues after upgrading to Exchange 2019 CU14. As announced in August 2023 , by default, starting with CU14, Setup enables the Windows Extended Protection (EP) feature on the Exchange server being installed. Extended Protection isn't supported in environments that use SSL Offloading. SSL termination during SSL Offloading causes Extended Protection to fail. To enable Extended Protection in your Exchange environment, you must not be using SSL offloading with your Load Balancers. Please check this link for more details 2/20/2024 CU 14 for Exchange 2019 Environments that are using SSL offloading configuration may face issues with Outlook connectivity issues after upgrading to Exchange 2019 CU14. As announced in August 2023 , by default, starting with CU14, Setup enables the Windows Extended Protection (EP) feature on the Exchange server being installed. Extended Protection isn't supported in environments that use SSL Offloading. SSL termination during SSL Offloading causes Extended Protection to fail. To enable Extended Protection in your Exchange environment, you must not be using SSL offloading with your Load Balancers. Please check this link for more details 2/19/2024 CU 14 for Exchange 2019 Exchange 2019 CU14 RecoverServer fails while creating \"New-PushNotificationsVirtualDirectory\" with following error: Exception setting \"ExtendedProtectionTokenChecking\": \"Cannot convert null to type \"Microsoft.Exchange.Data.Directory.SystemConfiguration.ExtendedProtectionTokenCheckingMode\" due to enumeration values that are not valid. Please follow the steps from this KB to resolve the issue 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 vulnerability
Updated 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 issue
Updated 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 event Watson 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.
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:
Making sure the source mailbox object is a member of the Mail-Enabled Security Group defined on the MailboxMovePublishedScopes of the source organization relationship
Making sure the source mailbox object ExchangeGuid attribute value matches the one from the target MailUser object, and give you the option to set it
Making sure the source mailbox object ArchiveGuid attribute (if there's an Archive enabled) value matches the one from the target MailUser object, and give you the option to set it
Making sure the source mailbox object has no more than 12 auxArchives
Making sure the source mailbox object has no hold applied
Making sure the source mailbox object TotalDeletedItemsSize is not bigger than Target MailUser recoverable items size
Making sure the source mailbox object LegacyExchangeDN attribute value is present on the target MailUser object as an X500 proxyAddress, and give you the option to set it, as long as the Target MailUser is not DirSynced
Making sure the source mailbox object X500 addresses are also present on the target MailUser object.
Checking if the source mailbox object has an Archive enabled, and if so, check if there's any content on the SubstrateHolds folder of the archive mailbox.
Making sure the target MailUser object PrimarySMTPAddress attribute value is part of the target tenant accepted domains and give you the option to set it to be like the UPN if not true, as long as the Target MailUser is not DirSynced
Making sure the target MailUser object EmailAddresses are all part of the target tenant accepted domains and give you the option to remove them if any doesn't belong to are found, as long as the Target MailUser is not DirSynced
Making sure the target MailUser object ExternalEmailAddress attribute value points to the source Mailbox object PrimarySMTPAddress and give you the option to set it if not true, as long as the Target MailUser is not DirSynced
Verifying if there's a T2T license assigned on either the source or target objects.
Checking if there's an AAD app as described on https://docs.microsoft.com/en-us/microsoft-365/enterprise/cross-tenant-mailbox-migration?view=o365-worldwide#prepare-the-target-destination-tenant-by-creating-the-migration-application-and-secret
Checking if the AAD app on Target has been consented in Source tenant as described on https://docs.microsoft.com/en-us/microsoft-365/enterprise/cross-tenant-mailbox-migration?view=o365-worldwide#prepare-the-source-current-mailbox-location-tenant-by-accepting-the-migration-application-and-configuring-the-organization-relationship
Checking if the target tenant has an Organization Relationship as described on https://docs.microsoft.com/en-us/microsoft-365/enterprise/cross-tenant-mailbox-migration?view=o365-worldwide#prepare-the-target-tenant-by-creating-the-exchange-online-migration-endpoint-and-organization-relationship
Checking if the target tenant has a Migration Endpoint as described on https://docs.microsoft.com/en-us/microsoft-365/enterprise/cross-tenant-mailbox-migration?view=o365-worldwide#prepare-the-target-tenant-by-creating-the-exchange-online-migration-endpoint-and-organization-relationship
Checking if the source tenant has an Organization Relationship as described on https://docs.microsoft.com/en-us/microsoft-365/enterprise/cross-tenant-mailbox-migration?view=o365-worldwide#prepare-the-source-current-mailbox-location-tenant-by-accepting-the-migration-application-and-configuring-the-organization-relationship including a Mail-Enabled security group defined on the MailboxMovePublishedScopes property.
Gather all the necessary information for troubleshooting and send it to Microsoft Support if needed
Because not all scenarios allow access to both tenants by the same person, this will also allow you to collect the source tenant and mailbox information and wrap it into a zip file so the target tenant admin can use it as a source to validate against.
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.
Please make sure you have at least the Exchange Online V2 Powershell module (https://docs.microsoft.com/en-us/powershell/exchange/exchange-online-powershell-v2?view=exchange-ps#install-and-maintain-the-exo-v2-module)
You would need the Microsoft Graph Module (https://learn.microsoft.com/en-us/powershell/microsoftgraph/installation?view=graph-powershell-1.0)
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.
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
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:
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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
"},{"location":"Admin/MonitorExchangeAuthCertificate/#how-to-run","title":"How To Run","text":""},{"location":"Admin/MonitorExchangeAuthCertificate/#examples","title":"Examples:","text":"
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:
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.
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.
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.
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.
NOTE: The ConfigureScriptToRunViaScheduledTask parameter can be combined with the IgnoreHybridConfig and IgnoreUnreachableServers parameter.
It creates a new Exchange Role Group, Auth Certificate Management, which has the following roles assigned: View-Only Configuration, View-Only Recipients, Exchange Server Certificates, Organization Client Access
It creates a new user account with the following User Principal Name (UPN): SystemMailbox{b963af59-3975-4f92-9d58-ad0b1fe3a1a3}@contoso.local
The user account is mail-enabled and hidden from address lists
The user account is added to the local Administrators group on the Exchange Server where the script is executed
The user account is added to the Auth Certificate Management Exchange Role Group
The script is copied to <ExchangeInstallPath>\\Scripts
A new scheduled task is registered to run the script in context of the SystemMailbox{b963af59-3975-4f92-9d58-ad0b1fe3a1a3}@contoso.local user
The 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.
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\".
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
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.
"},{"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.
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:
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.
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.
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:
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.
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/#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
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.
Test-ExchangePropertyPermissions is designed to detect certain schema issues which can manifest as permissions problems and can be challenging to identify manually, including:
Scenarios where a property set does not include all the expected properties.
Scenarios where an objectClass definition is missing expected properties.
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:
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.
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.
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.
"},{"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. 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/#general-overview-of-looking-at-sharing-issues","title":"General Overview of looking at Sharing Issues:","text":"
The first thing to determine is what kind of sharing relationship the users have.
Modern Sharing (New Model Sharing / REST) - Recipient gets a replicated copy of the Owners Calendar in their Mailbox.
Old Model Sharing \u2013 Recipient is granted rights but has to 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 (ICS) \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 output from 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.
Download the latest release: Get-CalendarDiagnosticObjectsSummary.ps1
This script runs the Get-CalendarDiagnosticObjects cmdlet and returns a summarized timeline of actions into clear English. It will also output an easier to read version of the CalLogs (enhanced) as well as a Raw copy of the logs for Developers.
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 in csv format in the current directory. New -ExportToExcel highly recommended for ease of use (all logs in one file, color coding, etc.). First time use will request installing the ImportExcel module. See https://github.com/dfinke/ImportExcel for more information on the ImportExcel module.
Parameters: Explanation: -Identity One (or more) SMTP Address of EXO User Mailbox to query. -Subject Subject of the meeting to query, only valid if Identity is a single user. -MeetingID MeetingID of the meeting to query. - Preferred way to get CalLogs. -TrackingLogs Populate attendee tracking columns in the output. - Only useable with the MeetingID parameter. -Exceptions Include Exception objects in the output. - Only useable with the MeetingID parameter. -ExportToExcel - [NEW Feature] Export the output to an Excel file with formatting. - Running the script for multiple users will create three tabs in the Excel file for each user. If you want to add more users to the Excel file, close the file and rerun with new user. - one tab for Enhanced CalLog - one tab for the TimeLine - Tab one for Raw CalLog -CaseNumber Case Number to include in the Filename of the output. - PrePend <CaseNumber>_ to filename. -ShortLogs Limit Logs to 500 instead of the default 2000, in case the server has trouble responding with the full logs. ---"},{"location":"Calendar/Get-CalendarDiagnosticObjectsSummary/#syntax","title":"Syntax:","text":"
Example to return timeline for a user with MeetingID:
Will create file like .\\123456_CalLogSummary_<MeetingID>.xlsx in current directory."},{"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).
"},{"location":"Calendar/Get-RBASummary/#high-level-steps-for-rba-processing","title":"High-level steps for RBA processing:","text":"
Determine if the Meeting Request is in policy or out of policy.
If the meeting request is Out of Policy, see if the user has rights to create an Out of Policy request and if so, forward it to the Delegates.
If it is In Policy, then either book it or forward it to the delegate based on the settings.
Lastly the RBA does the configured Post Processing steps to format the meeting (delete attachments, rename meeting, etc.)
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.
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.
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:
"},{"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":"
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.
"},{"location":"Databases/VSSTester/#trace-in-circular-mode-until-the-microsoft-exchange-writer-fails","title":"Trace in circular mode until the Microsoft Exchange Writer fails","text":"
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.
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.
Run \"dcomCnFg\" from the run box or command prompt on the problem machine
Expand Component Services then Computers
Right Click on My Computer and select Properties
Select the COM Security tab and select Edit Default... under Access Permissions
If the local Administrators group is not here for Allow for Local and Remote Access, click Add... to add the local Administrators group to the Default Security permissions
Change the locations to the computer name
Type in \"Administrators\" and select Check Names. Making sure the computer account comes up
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.
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.
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:
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.
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\"
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\"
"},{"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 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. 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 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 MailboxDeliveryThrottlingLogs Enable to collect the mailbox delivery throttling logs on the server. Location: (Get-MailboxTransportService $server).MailboxDeliveryThrottlingLogPath 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 TransportConnectivityLogs Aliases ConnectivityLogs, FrontEndConnectivityLogs, HubConnectivityLogs, and MailboxConnectivityLogs. Enable to collect the logs that was set at the following locations: (Get-FrontendTransportService $server).ConnectivityLogPath, (Get-TransportService $server).ConnectivityLogPath, and (Get-MailboxTransportService $server).ConnectivityLogPath TransportLogging Enables the following switches and their logs to be collected. AcceptedRemoteDomain, TransportConnectivityLogs, TransportProtocolLogs, MailboxDeliveryThrottlingLogs, MessageTrackingLogs, PipelineTracingLogs, QueueInformation, ReceiveConnectors, SendConnectors, TransportConfig, TransportRoutingTableLogs, and TransportRules TransportProtocolLogs Aliases ProtocolLogs, FrontEndProtocolLogs, HubProtocolLogs, and MailboxProtocolLogs. Enable to collect the logs that was set at the following locations: (Get-FrontendTransportService $server).ReceiveProtocolLogPath, (Get-FrontendTransportService $server).SendProtocolLogPath, (Get-TransportService $server).ReceiveProtocolLogPath, (Get-TransportService $server).SendProtocolLogPath, (Get-MailboxTransportService $server).ReceiveProtocolLogPath, and (Get-MailboxTransportService $server).SendProtocolLogPath 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 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 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
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:
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.
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. SkipVersionCheck Skip script version verification. ScriptUpdateOnly Just update script version to latest one."},{"location":"Diagnostics/Test-ExchAVExclusions/#outputs","title":"Outputs","text":"
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
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
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":"
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":"
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 2016 - Exchange Server 2019
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:
Organization Management
Domain Admins (only necessary for the DCCoreRatio parameter)
"},{"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.
This cmdlet will run the Health Checker Load Balancing Report for all the Exchange CAS (Front End connections only) and MBX servers (BackEnd connections) in the Organization.
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)
"},{"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-yyyyMMddHHmmss.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.
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:
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
"},{"location":"Diagnostics/HealthChecker/AuthCertificateCheck/#what-does-the-check-do","title":"What does the check do?","text":"
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":"
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!
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:
CloudServicesMailEnabled
If a Receive Connector has the following setting set, it means that the connector is eligible for cloud mail usage:
TlsDomainCapabilities
We only perform testings for the Receive Connectors if:
TransportRole is set to FrontendTransport
We run the following checks:
Connector enabled check:
We show a yellow warning, if the connector is not enabled
Send Connector configured to relay emails via M365 check:
If TlsAuthLevel is set to CertificateValidation
If RequireTLS is set to true
If TlsDomain is set (only performed if TlsAuthLevel is set to DomainValidation)
TlsCertificateName configuration check:
We check if TlsCertificateName has been set
We check if the certificate which is configured in TlsCertificateName exists on the server
If a certificate was configured and detected on the system, we then check if it expires within the next 60 days
If a certificate was configured, we compare it with the TlsCertificateName returned by Get-HybridConfiguration
If a certificate was configured, we check if the syntax is correct and not corrupt. Expected syntax: <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
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.
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
Shows if the EEMS is enabled or not on Organizational level
Shows if the EEMS is enabled or not on Server level
Windows Service Check
MSExchangeMitigation Windows service startup type should be: Automatic
MSExchangeMitigation Windows service status should be: Running
Pattern Service Check
We validate if we can reach the OCS which is used to serve the latest mitigations
OCS Mitigation Service url: https://officeclient.microsoft.com/GetExchangeMitigations
Mitigations Check
Shows which mitigations are currently being applied
Shows which mitigations are currently being blocked
Diagnostic Data Check
Shows if the service is configured to provide diagnostic data to Microsoft or not
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/ExchangeComputerMembership/","title":"Exchange Server Computer Membership","text":""},{"location":"Diagnostics/HealthChecker/ExchangeComputerMembership/#description","title":"Description:","text":"
Checks for the computer object to be members of the Exchange Trusted Subsystem and Exchange Servers security groups by default. It will also make sure the default local system account has the Exchange Trusted Subsystem a member of it as well in order to have the correct access to local system files.
This check is done by using the ADModule with using the cmdlets Get-LocalGroupMember -SID \"S-1-5-32-544\" and running Get-ADPrincipalGroupMembership (Get-ADComputer $env:COMPUTERNAME).DistinguishedName
If an issue is detected, the group will display with where the problem is located. Either Local System Membership if the group isn't part of the local system account or AD Group Membership if the computer object isn't a member of the group provided.
Included in HTML Report?
Yes
"},{"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:
We query the server component state by running Get-ServerComponentState
We query cluster node information by running Get-ClusterNode
We then check for each component if Component.State is not Active
If this is the case, we query the Component.LocalStates and Component.RemoteStates
We validate if both states LocalStates & RemoteStates are the same
We add the information, if LocalStates & RemoteStates are different
We 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
This is a simple check that can be performed from the Exchange On Prem side to quickly determine if the EXO connector is misconfigured. This does not completely determine if the connector is misconfigured, as Health Checker script is not designed to connect to Exchange Online to properly determine if everything is correctly configured for the way you want your mail flow to work.
A Send Connector is determined to be destined for Exchange Online if one of the following is true:
SmartHost endpoint has a *.mail.protection.outlook.com
AddressSpaces address has a *.mail.onmicrosoft.com
For those connectors, we then determine a misconfiguration if one of the following is true:
TLSCertificateName is not set
CloudServicesMailEnabled is not set to true
These are now being flagged as an issue due to some recent changes within Exchange Online.
Some additional configuration concerns are also warned about if one of the following is true:
TLSAuthLevel is not set to CertificateValidation or DomainValidation
TLSDomain is not set to mail.protection.outlook.com if TLSAuthLevel is set to DomainValidation
"},{"location":"Diagnostics/HealthChecker/ExoConnectorCheck/#included-in-html-report","title":"Included in HTML Report?","text":"
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.
Exchange 2013 is not affected by the transport queue issue, however, if invalid patterns has been applied, no newer update pattern with a lower version number (like 2112330001) will be applied.
We check if a folder with number 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
We show some general information about the Processor/Hardware of the Exchange server against which the script was executed.
Hardware Type:
VMWare
AmazonEC2
HyperV
Physical
Unknown
We additionally show the following information, if HardwareType is Physical or AmazonEC2: - Manufacturer - Model - Processor
Number of Processors:
We show an note if ServerType is VMWare [1]
We show an error if we have more than 2 Processors installed
Number of Physical/Logical Cores:
We show a warning if we have more than 24 Physical Cores and running Exchange 2013/2016 [2]
We show a warning if we have more than 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]
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
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.
This provides the application pools on the server with the following information:
State (Started or Stopped)
GCServerEnabled (Garbage Collection Server Enabled - Depends on the RAM on the server if this should be enabled or not on the server. If it should be, Health Checker should call it out.)
RestartConditionSet ( If there is an IIS setting that will automatically restart the App Pool. This is not recommended and will cause issues with client connectivity )
This provides the different locations that you use for different connection endpoints with the following information:
Extended Protection ( The current value )
Ssl Flags ( If enabled and/or Cert based )
IP Filtering Enabled ( If any IP filtering is enabled )
URL Rewrite ( Names of each rule applied at the location )
Authentication ( Provides each type of authentication that is enabled for the location. If anonymous 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
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.
"},{"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:
Go into the file 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
Open the file by using an elevated notepad.exe and change the gcServer Enabled value from false to true
Recycle the 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
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.
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).
This check is looking at the <ExchangeInstallPath>\\Bin\\Search\\Ceres\\Runtime\\1.0\\noderunner.exe.config to look at the memoryLimitMegabytes value. This value should be set to 0 for the best performance. By having it set to 0, we do not limit the noderunner.exe processes. However, in some scenarios you might want to recommend to limit the process memory consumption to prevent server impact. If you do this, it is only recommended as a temporary fix.
"},{"location":"Diagnostics/HealthChecker/NodeRunnerMemoryLimitCheck/#included-in-html-report","title":"Included in HTML Report?","text":"
Users can't receive email messages or connect to their mailbox
"},{"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
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.
Good: PacketsReceivedDiscarded is 0
Warning: PacketsReceivedDiscarded lower than 1000
Error: 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)
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).
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
"},{"location":"Diagnostics/HealthChecker/PagefileSizeCheck/#how-to-set-the-pagefile-to-a-static-value","title":"How to set the pagefile to a static value?","text":"
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]
"},{"location":"Diagnostics/HealthChecker/ProcessorCheck/#how-this-is-checked","title":"How This Is Checked","text":"
"},{"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.
We show a warning if we have more than 24 Logical Cores and running Exchange 2013/2016 [2]
We show a warning if we have more than 48 Logical Cores and running Exchange 2019 [2]
"},{"location":"Diagnostics/HealthChecker/ProcessorCheck/#how-this-is-checked_1","title":"How This Is Checked","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":"
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.
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.
We show a warning if we detect an outstanding pending reboot. We also display the type of pending reboot. We differentiate between:
PendingFileRenameOperations
SccmReboot
SccmRebootPending
ComponentBasedServicingRebootPending
AutoUpdatePendingReboot
UpdateExeVolatile\\Flags
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.
Open regedit to the desired location. Delete the key.
If unable to delete the key, follow these steps:
Right click on it
Open permissions
Click on Advanced
Change ownership to your account
Close Advanced window
Give your account Full Control in Permissions window
Delete the key
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.
The first thing to do is to create a service account which is used to run the script. It is recommended to use a strong password which will be changed regularly. It's also recommended to add the user to the 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).
Now it's time to create the Scheduled Task. This can be done by the help of PowerShell:
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:
Register-ScheduledTask -TaskName 'HealthChecker Daily Run' -InputObject $hcTask -User (Read-Host \"Please enter username in format (Domain\\Username)\") -Password (Read-Host \"Please enter password\")
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.
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":"
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 Disabled
"},{"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
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.
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:
Value Definition Enabled Client and Server Enabled values are set to 1 and DisabledByDefault is set to 0 on the TLS Version. Disabled Client and Server Enabled values are set to 0 and DisabledByDefault is set to 1 on the TLS Version. Half Disabled Client and Server Enabled values are set to either 0 or 1 and DisabledByDefault is set to the opposite where the value doesn't equal Enabled or Disabled.This is not a supported configuration as it doesn't follow the documentation that we have provided. Misconfigured When either the Enabled or the DisabledByDefault values do not match between the Client and Server of that TLS Version.Exchange can be a Client and a Server and this will cause problems and needs to be addressed ASAP.
The location where we are checking for the TLS values are here:
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:
Within Exchange Monitoring, we have a probe that will attempt to clear out the old temp data that is generated from EdgeTransport.exe process. However, this probe definition is defined in the %ExchangeInstallPath%\\Bin\\Monitoring\\Config\\AntiMalware.xml with a hardcoded path options to look. By default, we are only looking at \"D:\\ExchangeTemp\\TransportCts\\UnifiedContent;C:\\Windows\\Temp\\UnifiedContent;C:\\Program Files\\Microsoft\\Exchange Server\\V15\\TransportRoles\\data\\Temp\\UnifiedContent\". Therefore, if Exchange is not installed in at C:\\Program Files\\Microsoft\\Exchange Server\\V15\\ or if the TemporaryStoragePath of the EdgeTransport.exe.config value is anything other than C:\\Program Files\\Microsoft\\Exchange Server\\V15\\TransportRoles\\data\\Temp the probe will not work as intended to clean up the data files.
The only way to get the probe to automatically clean up the temp files is to add the correct location to the %ExchangeInstallPath%\\Bin\\Monitoring\\Config\\AntiMalware.xml file.
Included in HTML Report?
Yes
Additional resources:
Exchange UnifiedContent folder fills up the drive
"},{"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
The script performs different checks to detect vulnerabilities which may lead into a security issue for the Exchange server.
Vulnerability checks performed:
Check the Exchange server build number against known vulnerabilities that exists within a specific build
Check for CVE-2020-0796 SMBv3 vulnerability
Check for CVE-2020-1147 .NET Core & .NET Framework vulnerability
Check for CVE-2021-1730 Download Domains state
Included 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:
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:
Download the latest release: MDOThreatPolicyChecker.ps1
This script checks which Microsoft Defender for Office 365 and Exchange Online Protection threat policies cover a particular user, including anti-malware, anti-phishing, inbound and outbound anti-spam, as well as Safe Attachments and Safe Links policies in case these are licensed for your tenant. In addition, the script can check for threat policies that have inclusion and/or exclusion settings that may be redundant or confusing and lead to missed coverage of users or coverage by an unexpected threat policy.
It also includes an option to show all the actions and settings of the policies that apply to a user.
The script uses Exchange Online cmdlets from Exchange Online module and Microsoft.Graph cmdLets from Microsoft.Graph.Authentication, Microsoft.Graph.Groups and Microsoft.Graph.Users modules.
To run the PowerShell Graph cmdlets used in this script, you need only the following modules from the Microsoft.Graph PowerShell SDK: - Microsoft.Graph.Groups: Contains cmdlets for managing groups, including Get-MgGroup and Get-MgGroupMember. - Microsoft.Graph.Users: Includes cmdlets for managing users, such as Get-MgUser. - Microsoft.Graph.Authentication: Required for authentication purposes and to run any cmdlet that interacts with Microsoft Graph.
You can find the Microsoft Graph modules in the following link: \u00a0\u00a0\u00a0\u00a0https://www.powershellgallery.com/packages/Microsoft.Graph/ \u00a0\u00a0\u00a0\u00a0https://learn.microsoft.com/en-us/powershell/microsoftgraph/installation?view=graph-powershell-1.0#installation
Here's how you can install the required submodules for the PowerShell Graph SDK cmdlets:
Remember to run these commands in a PowerShell session with the appropriate permissions. The -Scope CurrentUser parameter installs the modules for the current user only, which doesn't require administrative privileges.
In the Graph connection you will need the following scopes 'Group.Read.All','User.Read.All'
You can find the Exchange module and information in the following links: \u00a0\u00a0\u00a0\u00a0https://learn.microsoft.com/en-us/powershell/exchange/exchange-online-powershell-v2?view=exchange-ps \u00a0\u00a0\u00a0\u00a0https://www.powershellgallery.com/packages/ExchangeOnlineManagement
"},{"location":"M365/MDO/MDOThreatPolicyChecker/#parameters","title":"Parameters","text":"Parameter Description CsvFilePath Allows you to specify a CSV file with a list of email addresses to check. Csv file must include a first line with header Email. EmailAddress Allows you to specify email address or multiple addresses separated by commas. IncludeMDOPolicies Checks both EOP and MDO (Safe Attachment and Safe Links) policies for user(s) specified in the CSV file or EmailAddress parameter. OnlyMDOPolicies Checks only MDO (Safe Attachment and Safe Links) policies for user(s) specified in the CSV file or EmailAddress parameter. ShowDetailedPolicies In addition to the policy applied, show any policy details that are set to True, On, or not blank. SkipConnectionCheck Skips connection check for Graph and Exchange Online. SkipVersionCheck Skips the version check of the script. ScriptUpdateOnly Just updates script version to latest one."},{"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.
Install Visual Studio Code. You'll need this to develop scripts for this project.
Assuming you're running Windows, install Git For Windows. When it asks for your default editor, choose Visual Studio Code. The rest of the defaults are fine. If you're on a different operating system, refer to the Git documentation for instructions.
Optional but recommended: Install Posh Git in your PowerShell 7+ shell. This adds some useful features such as branch name autocompletion in PowerShell.
"},{"location":"NewUserGuide/#forking-the-repository","title":"Forking the repository","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.
"},{"location":"NewUserGuide/#creating-a-new-branch","title":"Creating a new branch","text":"
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:
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.
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:
File has no newline at the end.
File is missing the required compliance header.
File has no BOM. We require a BOM on scripts.
The formatting of the code itself is not using the correct brace style. This is shown in a warning, followed by diff output illustrating the required change. In addition, a PSScriptAnalyzer check at the end highlights the same issue with the PSPlaceOpenBrace rule.
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.
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!
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.
"},{"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.
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.
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":"
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.
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.
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.
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.
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:
"},{"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:
This example starts a SimplePerf using the Exchange scenario, but then it includes every counter starting with either MSExchange or Microsoft Exchange.
This example starts a SimplePerf collecting all the matching Exchange counters without including any default counters at all, because the None scenario was specified.
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.
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:
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.
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.
Download the latest release: Update-PublicFolderPermissions.ps1
This script can be used to set specific permissions on public folders in bulk or to propagate the full set of permissions from a parent folder to its entire subtree.
Environment Support Exchange Online Supported Exchange 2019 Not Supported"},{"location":"PublicFolders/Update-PublicFolderPermissions/#syntax","title":"Syntax","text":"
This syntax propagates all permissions from \\FolderA to its entire subtree, including Default and Anonymous permissions. Note that this option simply ensures that all the permission entries that exist on \\FolderA also exist on all folders underneath it. It does not remove permissions from child folders when those permissions do not exist on \\FolderA.
"},{"location":"PublicFolders/Update-PublicFolderPermissions/#notes-about-rights-and-roles","title":"Notes about rights and roles","text":"
Historically, the FolderContact right and the FolderVisible right could be toggled on and off without affecting the role. This behavior can still be seen in classic Outlook. If a user is given the Owner role, FolderContact can be toggled on or off. Either way, the user still has the Owner role. Similarly, in classic Outlook, a user can be given the None role with or without FolderVisible.
By contrast, the current EXO cmdlets assume that Owner always includes FolderContact, and None never includes FolderVisible. Therefore, when propagating permissions with this script, None always means None without FolderVisible, and Owner always means Owner with FolderContact.
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
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.
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.
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:
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 via Get-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.
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.
"},{"location":"Security/CVE-2023-21709/#how-to-run","title":"How To Run","text":""},{"location":"Security/CVE-2023-21709/#examples","title":"Examples:","text":"
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.
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/ConfigureFipFsTextExtractionOverrides/","title":"ConfigureFipFsTextExtractionOverrides","text":"
Download the latest release: ConfigureFipFsTextExtractionOverrides.ps1
Note
Starting in the Exchange Server March 2024 security update we disable the use of the Oracle Outside In Technology (also known as OutsideInModule or OIT) in Microsoft Exchange Server due to multiple security vulnerabilities in the module. The OutsideInModule was used by the Microsoft Forefront Filtering Module to extract information from different file types, to perform content inspection as part of the Exchange Server Data Loss Prevention (DLP) or Exchange Transport Rules (ETR) features.
The ConfigureFipFsTextExtractionOverrides.ps1 script can be used to manipulate the usage of OutsideInModule that is disabled by default in the Exchange Server March 2024 security update.
There are two scenarios in which the script could be used:
It can be used to explicitly enable file types that should be processed by the help of the OutsideInModule.
It can be used to override the version of the OutsideInModule that should be used for processing file types, which were explicitly enabled to be processed by the OutsideInModule. After installing the March 2024 security update, Exchange Server uses the latest version of the OutsideInModule version 8.5.7 by default. By activating this override, OutsideInModule version 8.5.3 will be used.
Details about the change that was done as part of the March 2024 security update can be found in KB5037191.
Details about the security vulnerability can be found in the MSRC security advisory.
Warning
Microsoft strongly recommends not overriding the default behavior that was introduced with the March 2024 security update if there are no functional issues that affect your organization's mail flow.
This script must be run as Administrator in Exchange Management Shell (EMS). The user must be a member of the Organization Management role group.
"},{"location":"Security/ConfigureFipFsTextExtractionOverrides/#how-to-run","title":"How To Run","text":""},{"location":"Security/ConfigureFipFsTextExtractionOverrides/#examples","title":"Examples:","text":"
This syntax enables processing of Jpeg and AutoCad file types by the help of the OutsideInModule on the server where the command was executed.
This syntax causes Exchange Server to use the previous version of the OutsideInModule. The override will be enabled on the system on which the script was executed. Note that this can make your system vulnerable to known vulnerabilities in the previous version and should not be used unless explicitly advised by Microsoft.
This syntax restores the configuration.xml from the backup that was created by a previous run of the script on the Exchange server where the script was executed.
"},{"location":"Security/ConfigureFipFsTextExtractionOverrides/#parameters","title":"Parameters","text":"Parameter Description ExchangeServerNames A list of Exchange servers that you want to run the script against. SkipExchangeServerNames A list of Exchange servers that you don't want to execute the configuration action. ConfigureOverride A list of file types that should be allowed to be processed by the OutsideInModule. The following input can be used: XlsbOfficePackage, XlsmOfficePackage, XlsxOfficePackage, ExcelStorage, DocmOfficePackage, DocxOfficePackage, PptmOfficePackage, PptxOfficePackage, WordStorage, PowerPointStorage, VisioStorage, Rtf, Xml, OdfTextDocument, OdfSpreadsheet, OdfPresentation, OneNote, Pdf, Html, AutoCad, Jpeg, Tiff.If you want to enable the previous version of the OutsideInModule (8.5.3) to process file types, you must specify OutsideInModule as file type. Note that the OutsideInModule value cannot be used together with other file type values.The input is case-sensitive. Action String parameter to define the action that should be performed. Input can be Allow or Block. The default value is: Block Rollback Switch parameter to restore the configuration.xml that was backed-up during a previous run of the script. 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.
CVE-2021-26855
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:
+NEW Check for the latest version of EOMT and download it.
Mitigate against current known attacks using CVE-2021-26855 via a URL Rewrite configuration
Scan the Exchange Server using the Microsoft Safety Scanner
Attempt to remediate compromises detected by 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 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":"
External Internet Connection from your Exchange server (required to download the Microsoft Safety Scanner and the IIS URL Rewrite Module).
Windows Server 2008 R2, Server 2012, Server 2012 R2, Server 2016, Server 2019
+New If Operating System is older than Windows Server 2016, must have KB2999226 for IIS Rewrite Module 2.1 to work.
"},{"location":"Security/EOMT/#who-should-run-the-exchange-on-premises-mitigation-tool","title":"Who should run the Exchange On-premises Mitigation Tool","text":"Situation Guidance If you have done nothing to date to patch or mitigate this issue\u2026 Run EOMT.PS1 as soon as possible.This will both attempt to remediate as well as mitigate your servers against further attacks. Once complete, follow patching guidance to update your servers on http://aka.ms/exchangevulns If you have mitigated using any/all of the mitigation guidance Microsoft has given (ExchangeMitigations.Ps1, Blog post, etc..) Run EOMT.PS1 as soon as possible. This will both attempt to remediate as well as mitigate your servers against further attacks. Once complete, follow patching guidance to update your servers on http://aka.ms/exchangevulns If you have already patched your systems and are protected, but did NOT investigate for any adversary activity, indicators of compromise, etc\u2026. Run EOMT.PS1 as soon as possible. This will attempt to remediate any existing compromise that may not have been full remediated before patching. If you have already patched and investigated your systems for any indicators of compromise, etc\u2026. No action is required"},{"location":"Security/EOMT/#important-note-regarding-microsoft-safety-scanner","title":"Important note regarding Microsoft Safety Scanner","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.
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.
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:
Does mitigations for all 4 CVE's - CVE-2021-26855, CVE-2021-26857, CVE-2021-27065 & CVE-2021-26858.
Some of the mitigation methods impact Exchange functionality.
Does not do any scanning for existing compromise or exploitation.
Does not take response actions to existing active identified threats.
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.
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:
Check for the latest version of EOMTv2.ps1 and download it.
Mitigate against current known attacks using CVE-2022-41040 via a URL Rewrite configuration
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":"
PowerShell 3 or later
PowerShell script must be run as Administrator.
IIS 7.5 and later
Exchange 2013 Client Access Server role, Exchange 2016 Mailbox role, or Exchange 2019 Mailbox role
Windows Server 2008 R2, Server 2012, Server 2012 R2, Server 2016, Server 2019
If Operating System is older than Windows Server 2016, must have KB2999226 for IIS Rewrite Module 2.1 to work.
[Optional] External Internet Connection from your Exchange server (required to update the script and install IIS URL rewrite module).
NOTE: The script has to be executed individually for each server.
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.
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.
"},{"location":"Security/ExchangeExtendedProtectionManagement/#how-to-run","title":"How To Run","text":""},{"location":"Security/ExchangeExtendedProtectionManagement/#examples","title":"Examples:","text":"
This syntax will process the prerequisites check only against the servers that you provided. This will execute the same checks as if you were attempting to configure Extended Protection.
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.
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.
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.
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.
This syntax rolls back the Extended Protection configuration for all the Exchange Servers that are online where Extended Protection was previously configured.
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.
NOTE
This is a legacy version of the restore process and is no longer supported. You can still attempt to restore, if the configuration file is detected and is less than 30 days old if a configuration was done with a pervious version of the script. Moving forward, the applicationHost.config file is no longer being used as a backup to restore from. The RestoreConfiguration is the supported replacement.
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.
This syntax will disable Extended Protection configuration for all the Exchange Servers that are online by setting the value at all current configuring locations to None.
"},{"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. PrerequisitesCheckOnly Run the required prerequisites check for the passed server list to know if configuration can be attempted. ShowExtendedProtection Show the current configuration of Extended Protection for the passed server list. ExcludeVirtualDirectories Used to not enable Extended Protection on particular virtual directories. The following values are allowed: EWSFrontEnd. 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, RestoreConfiguration DisableExtendedProtection Using this parameter will disable extended protection for the servers you specify. This is done by setting all the configured locations back to None regardless of what the original value was set to prior to configuration or if it was enabled by default. 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:
CVE-2021-26855
CVE-2021-26857
CVE-2021-27065
CVE-2021-26858
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:
x86 & x64 -https://www.iis.net/downloads/microsoft/url-rewrite
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
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
"},{"location":"Security/Extended-Protection/","title":"Exchange Server Support for Windows Extended Protection","text":"
Documentation Moved
This documentation has been moved to Microsoft Learn. Please read Configure Windows Extended Protection in Exchange Server for more information.
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.
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.
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:
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.
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":"
Fulfill the requirements according to environment (i.e. On-Premises or Online)
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.
If step 2 generates CSV files, review the CSV file; if you find suspicious thing, then go to 5. If you only see blank things or paths to old .wav files, no need to go to step 5.
If you got suspected entries in CSV file, run the script in Cleanup mode
"},{"location":"Security/CVE-2023-23397/#requirements","title":"Requirements","text":""},{"location":"Security/CVE-2023-23397/#prerequisites-to-run-the-script-for-exchange-server-on-premises","title":"Prerequisites to run the script for Exchange Server (on-premises)","text":"
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.
"},{"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":"
Download the nuget package from NuGet Gallery | Microsoft.Exchange.WebServices.2.2.0
Change the extension of the file from .nupkg to .zip
Unzip the package.
Use the dll present at \"\\lib\\40\" location in the package
Provide the path to the DLL for the -DLLPath parameter when running the script.
"},{"location":"Security/CVE-2023-23397/#how-to-run","title":"How To Run","text":""},{"location":"Security/CVE-2023-23397/#script-parameters","title":"Script Parameters","text":"
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 the CertificateThumbprint 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:
AzureEnvironment Cloud Environment Name Global AzureCloud WW USGovernmentL4 AzureUSGovernment GCC USGovernmentL5 AzureUSGovernment DOD ChinaCloud AzureChinaCloud Office365 operated by 21Vianet"},{"location":"Security/CVE-2023-23397/#running-against-exchange-server-on-premises-mailboxes","title":"Running Against Exchange Server (On-Premises) Mailboxes","text":""},{"location":"Security/CVE-2023-23397/#audit-mode","title":"Audit Mode:","text":"
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.
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.
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/#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.
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
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:
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.
Download the correct NuGet Gallery | Microsoft.Exchange.WebServices.2.2.0
Close PowerShell (CRITICAL)
Launch new PowerShell session
Run cmdlet again with providing new dll path ( should be lib\\40\\Microsoft.Exchange.WebServices.dll)
"},{"location":"Security/CVE-2023-23397/#unable-to-connect-to-ews-endpoint-401-unauthorized-on-prem","title":"Unable to connect to EWS endpoint - 401 unauthorized - On Prem.","text":"
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
"},{"location":"Security/CVE-2023-23397/FAQ/","title":"CVE-2023-23397 Frequently Asked Questions","text":""},{"location":"Security/CVE-2023-23397/FAQ/#what-is-the-usesearchfolders-feature","title":"What is the -UseSearchFolders feature?","text":"
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
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:
"},{"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:
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:
"},{"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.
"},{"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:
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.
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.
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.
"},{"location":"Setup/Set-ExchAVExclusions/#how-to-run","title":"How To Run","text":"
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
"},{"location":"Setup/Set-ExchAVExclusions/#parameters","title":"Parameters","text":"Parameter Description ListRecommendedExclusions Get the full list of expected exclusions without set. FileName Export the Exclusion List. SkipVersionCheck Skip script version verification. ScriptUpdateOnly Just update script version to latest one."},{"location":"Setup/Set-ExchAVExclusions/#examples","title":"Examples:","text":"
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.
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.
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:
Current Logged on User and SID
Are you running as an Administrator
Member of Domain Admins
Member of Schema Admins
Member of Enterprise Admins
Member of Organization Management
Current PowerShell Execution Policy setting
Checks to see if you are missing files in the installer cache (only checks to see if they are there, not if they are valid)
More than 1 powershell.exe process up and running
If reboot pending. (Add -Verbose to see where)
The current AD level of readiness for CU upgrading. Displays warnings if a mismatch is detected.
Additional Parameters are used for when they are called out from the SetupLogReviewer.ps1
Parameter Type Description OtherWellKnownObjects switch Tests for deleted objects in the otherWellKnownObjects attribute"},{"location":"Setup/SetupAssist/ComputersContainer/","title":"Computers container renamed or missing","text":"
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.
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....
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.
Open regedit to the desired location. Delete the key.
If unable to delete the key, follow these steps:
Right click on it
Open permissions
Click on Advanced
Change ownership to your account
Close Advanced window
Give your account Full Control in Permissions window
Delete the key
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.
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.
$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
Gather message tracking log details of all message to / from a given recipient for a given time range. Useful for determining if a \"slow\" message was a one off or a pattern.
Note: If you provide a raw message tracking log to the script it WILL generate significant errors since many RECEIVE events and DELIVERY events occur on different servers.
"},{"location":"Transport/Measure-EmailDelayInMTL/#outputs","title":"Outputs","text":""},{"location":"Transport/Measure-EmailDelayInMTL/#csv-file","title":"CSV File","text":"Header Description MessageID ID of the Message TimeSent First time we see the message in the MTL TimeReceived Last delivery time in the MTL MessageDelay How long before the message was delivered"},{"location":"Transport/Measure-EmailDelayInMTL/#statistical-summary","title":"Statistical Summary","text":"Statistic Description EmailCount Number of email found in the MTL MaximumDelay Longest delivery delay found in the MTL MinimumDelay Shortest delivery delay found in the MTL AverageDelay Average of all delivery delays across all email in the MTL"},{"location":"Transport/Measure-EmailDelayInMTL/#default-output-file","title":"Default Output File:","text":"
Generates a report to the c:\\output directory from the file C:\\Temp\\LargeMTL.csv."},{"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.
-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
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:
Move all active Mailbox Databases to another DAG member
Run this command from Exchange Management Shell: Set-MailboxServer $env:ComputerName -DatabaseCopyAutoActivationPolicy Blocked
When the script is run, it takes the following actions.
Read the QueueDatabasePath and QueueDatabaseLoggingPath from the EdgeTransport.exe.config file. If these do not match, the script exits. That type of configuration is not yet supported by this script.
Search the QueueDatabasePath for any folders with names matching Message.old-*.
Parse the date string in the folder name to determine if this folder is under the MaxAgeInDays.
Any folders over the MaxAgeInDays are moved to the ReplaySkipped folder in the QueueDatabasePath.
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.
Check if the HubTransport component is in Draining state, and switch it to Draining if it is not.
Stop the Transport services (MSExchangeTransport and MSExchangeFrontEndTransport).
Move the current folder to be replayed to OldReplayQueue in the QueueDatabasePath.
Start the Transport services.
Check every 5 seconds if the queues clear. While waiting, run Remove-Message once a minute to remove any \"Delivery Delayed\" messages.
Once queues are cleared, stop the transport services.
Move OldQueueReplay to a folder inside of Replayed in the QueueDatabasePath, named Replayed-\\<original date on the folder>.
Continue to the next folder.
When finished with all the folders, stop the Transport services.
Overwrite EdgeTransport.exe.config with EdgeTransport.exe.config.before-replay.
Start the Transport services.
Notify the user that they must run the command to take the HubTransport component out of the Draining state when ready.
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.
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.
OldQueueReplay may have been left in place. If it is not clear whether this database was already replayed, Transport services should be started while QueueDatabasePath and QueueDatabaseLoggingPath in EdgeTransport.exe.config still point to OldQueueReplay. Once the queues have drained, Transport can be stopped, and OldQueueReplay can be moved to the Replayed folder.
The EdgeTransport.exe.config may be left pointing to OldQueueReplay. To fix it, replace EdgeTransport.exe.config with the EdgeTransport.exe.config.before-replay, which was the backup of the file prior to any changes.
MSExchangeTransport and MSExchangeFrontEndTransport may need to be started.
The HubTransport component must be set back to Active.