Update: We have now released the get-etrlimits PowerShell cmdlet. This new cmdlet incorporates many of the functionalities mentioned below, but with added ease and simplicity.
For additional related information you can also check our new blog post Finding Transport Rule Size Part 2 – Regex Limit.
EDIT 1/3/2023:
Recently we’ve enhanced “Get-TransportRule” cmdlet to return rule size and regex sizes. So, there is no need to create custom scripts anymore. To find the size of the Transport Rule and to determine the character limit for regular expressions (sometimes called regex) used in a Transport rule, you can use: Get-TransportRule cmdlet from Exchange Online Powershell.
Get-TransportRule “Name of the Rule” | FL Size,RegexSize
A question we sometimes hear from Exchange Online admins is “How can I determine the size of an Exchange Transport Rule (ETR)?” Sounds like a pretty easy question, but unfortunately there is no out of the box method to determine transport rule size. Until now, the answer has been elusive.
Why is knowing the size of an ETR important? Because the maximum size of an individual transport rule in Exchange Online is 8KB. Although it’s not easy to reach that limit, it might happen if the rule contains too many values. If it does, you get the following error:
For this reason, you might want to monitor the size of your rules and avoid being blocked unexpectedly if you add conditions. But before we start, let’s understand some basic concepts around Transport Rules.
Transport Rule Basic Concepts
When you create an ETR, Exchange Server or Exchange Online create an object in Active Directory (AD) under the CN=TransportVersioned container as an msExchTransportRule class. This object contains several attributes related to the rule, but the one that we’ll focus on is msExchTransportRuleXml. This is a string attribute in XML format that contains all the information about the rule (the name, conditions, actions, exceptions, etc.).
Understanding the msExchTransportRuleXml attribute is essential as the Exchange code relies on the length of this attribute to check the size of rule. A very simple mechanism, don’t you think? And indeed, it is if msExchTransportRuleXml is accessible. If you run Exchange Server, you can get the size of this attribute using the Get-ADObject cmdlet. As you probably can guess, the Get-ADObject cmdlet won’t work in Exchange Online. But there are other options; such as a script!
Although there is no way to manipulate msExchTransportRuleXml directly using Exchange Online PowerShell, there is a cmdlet that can help us: Export-TransportRuleCollection
Using a Script
To build your own script, start by assigning the ETR name you want to retrieve to a variable:
$ruleName = "Your ETR here"
Next, use Export-TransportRuleCollection with -Format InternalXML to export all ETRs found in AD to XML.
$file = Export-TransportRuleCollection -Format InternalXML
If you check the FileData property on the XML file containing the ETR export, you’ll see measurements in bytes, which means that you need to decode the FileData from byte array to string and cast it to XMLDocument:
[xml]$xml = [System.Text.Encoding]::UTF8.GetString($file.FileData)
Now you should be able to parse the XML. All rules were added, so you need to filter for the ETR you want:
$null = ($xml.SelectNodes("//rule")).Where({$_.name -notmatch "$ruleName"}) | % {$_.ParentNode.RemoveChild($_)}
Another thing to clean up in the XML is the “Id” attribute. The msExchTransportRuleXml string doesn’t have an Id attribute, so even though Export-TransportRuleCollection method adds it, you should remove it to align with msExchTransportRuleXml.
$xml.rules.rule.RemoveAttribute("id")
The last thing to do is the conversion from XML to string:
[string]$node = $xml.rules.rule.OuterXml
And now, you can check the length of the node variable to see the size of your rule:
$node.Length
The output is in bytes; the following example shows a rule at the limit of 8192 bytes.
Here is the full script:
$ruleName = "Your ETR here"
$file = Export-TransportRuleCollection -Format InternalXML
[xml]$xml = [System.Text.Encoding]::UTF8.GetString($file.FileData)
$null = ($xml.SelectNodes("//rule")).Where({$_.name -notmatch "$ruleName"}) | % {$_.ParentNode.RemoveChild($_)}
$xml.rules.rule.RemoveAttribute("id")
[string]$node = $xml.rules.rule.OuterXml
$node.Length
You can also use the following cmdlets to show all ETR size descending by the length in bytes:
($xml = ([xml][System.Text.Encoding]::UTF8.GetString((Export-TransportRuleCollection -Format InternalXML).FileData))).SelectNodes("//rule").RemoveAttribute("id")
$xml.rules.rule | %{ [pscustomobject]@{Name = $_.Name; LengthInBytes = $_.OuterXml.Length} } | Sort LengthInBytes -Descending
You can use following script in Exchange Server to retrieve the value directly from the msExchTransportRuleXml attribute:
$ruleName = "Your ETR here"
$rule = Get-TransportRule -Identity $ruleName
$obj = Get-ADObject -SearchBase $rule.DistinguishedName -lDAPFilter "(CN=$ruleName)" -Properties "msExchTransportRuleXml"
$obj.msExchTransportRuleXml.Length
Remember that the limit is not adjustable in Exchange Online. If you have large ETRs, we encourage you to check their size and reduce their length as much as possible, and to remove ETRs after they are no longer needed. These actions might help reduce your mail flow latency.
We hope that these details on how to retrieve the size of an ETR improve your Exchange Online and Exchange Server experience. Feel free to use the Comments section to ask questions or provide suggestions!
Thanks to Arindam Thokder, Alex Hudish, Keith Schottland and Nino Bilic for their review of this post.
Denis Vilaça Signorelli
Service Engineer