Build Filters Against Multiple Azure AD Properties
A post in the Microsoft Technical Community looked for help building a dynamic distribution list based on multiple Azure AD properties. Our esteemed technical editor, Vasil Michev, stepped in to help and involved me. I pointed out that this topic is covered in Chapter 6 of the Office 365 for IT Pros eBook (easy to miss in 1,250 pages) but admitted that the question was interesting.
Dynamic distribution lists are an undervalued part of Exchange Online. The concept has existed since Exchange 2003 introduced the query-based distribution group, or QDG. The current implementation arrived in Exchange 2007. In both cases, a query is resolved against the directory to identify the set of recipients for a message. The list is dynamic because the set of recipients will change based on the contents of the directory.
Precanned and Custom Recipient Filters
The Exchange admin center (EAC) GUI is designed to make it easy for administrators to create the queries for dynamic distribution lists. It does this by limiting the set of properties available for queries, like department and city. The queries generated by the EAC are called precanned queries. after generation, Exchange stores the recipient filter as a property of the dynamic distribution list.
Custom queries can use a much wider set of properties. The downside is that you must build the queries by hand and update dynamic distribution lists with PowerShell. That might seem hard, but it’s really not.
Excluding Some Mailboxes
In this instance, the need is to have a dynamic distribution list to address mailboxes owned by people with a specific job title but exclude any whose Azure AD accounts are blocked for sign-in. Figure 1 shows the account of architect Ben James. The account is blocked.
Figure 1: Details of a blocked Azure AD account
When an Azure AD account is blocked, Exchange synchronizes the status and updates the ExchangeUserAccountControl mailbox property. To find the set of recipients who have architect in their job title and can still sign in, we can build a recipient filter which checks the Title and ExchangeUserAccountControl properties. Because people might have prefixes to indicate the seniority of their architect status, we need to include some variants of the job title. Exchange only supports wildcards for filters at the end of a string (“architect*”) instead of the start (“*architect”), which would be more useful in this case.
Building and Testing a Recipient Filter with PowerShell
Here’s what a custom filter to check for a job title and account blocked status looks like:
To know if the filter works, we can use the Get-Recipient cmdlet. Get-Recipient accepts the filter defined in the $Filter variable and returns what it finds in the directory. This is exactly what will be returned as the set of recipients when the Exchange transport service resolves the query stored in the dynamic distribution list.
Get-Recipient -RecipientPreviewFilter $Filter | ft displayname, title
DisplayName Title
----------- -----
Ben James Architect
Eoin Redmond (Ireland) Architect
James Joyce Principal Architect
Tony Redmond Principal Architect
Vasil Michev (Technical Guru) Senior Architect
It’s important to test any filter before using it with a dynamic distribution list. If the query generated by the filter fails to resolve and return any recipients, any message sent to the list goes into a black hole. Exchange won’t generate a non-delivery notification because the address used for the message is valid (the list); the problem lies with what happens when the query is run against the directory.
Creating a Dynamic Distribution List with PowerShell
After you’re sure that the filter returns the correct set of recipients, you can create a dynamic distribution list using the filter. For example:
New-DynamicDistributionGroup -Name "Architects" -DisplayName "System and Engineering Architects" -Alias AllArchitects -PrimarySmtpAddress Architects@Office365itpros.com -RecipientFilter $Filter
Set-DynamicDistributionGroup -Identity AllArchitects -ManagedBy Tony.Redmond -MailTip "Distribution List for anyone with Architect in the job title"
The second command is to add an owner for the dynamic distribution list and to assign a mail tip for clients like Outlook to display when people address email to the list.
EAC Blocks Edits of Custom Recipient Filters
Any further adjustments to the recipient filter can only be made with PowerShell. If you look at a custom recipient filter with the Exchange admin center, it’s blocked for edit (Figure 2).
Figure 2: EAC stops any attempt to update a custom recipient filter for a dynamic distribution list
As for Ben James, when his Azure AD account is reenabled for sign-in, he’ll start to receive messages sent to the dynamic distribution list again, which is exactly what we want.
Insight like this doesn’t come easily. You’ve got to know the technology and understand how to look behind the scenes. Benefit from the knowledge and experience of the Office 365 for IT Pros team by subscribing to the best eBook covering Office 365 and the wider Microsoft 365 ecosystem.
44 Replies to “How to Create Exchange Dynamic Distribution Lists with Custom Recipient Filters”
Be aware a bug exists in the New EAC where any Custom recipient filter set on a DDG is wiped and replaced by a Precanned recipient filter when the DDG properties are opened and saved. The default Precanned filter that is applied will include all reciepient types. Resulting in emails sent to the DDG going to all mailboxes in the organisation as well as external recipients. When the DDG properties are opened in the New EAC, the save button is available even if the user does not change anything.
Due to this bug. It is recommended not to use the New EAC to manage DDGs with custom reciepient filters. Only use PowerShell.
Microsoft has been made aware of this bug. While they have recognised the bug they have not provided a timeline for resolution.
I am trying to build DDL based on StreetAddress but getting some weird syntax error. Can you please help? Basically, need to have DDL of mailbox users whose streetAddress is “Sterling”
But when i sending mail in Everyone@husola.de nobody getting mail with smtp @husola.de. Where and what am I doing wrong?
I want to note that we have had filters like this one for many years and work perfectly, but this is what does not work.
Text string properties that accept wildcard characters require the -like operator (for example, “Property -like ‘abc*'”). In Exchange Online PowerShell, you can’t use the wildcard as a prefix (for example, “Property -like ‘*abc'”) is not allowed).
Strangely, When I try to review the member using the legacy way, that is, storing the recipient filter after a variable and the calling that using get-recipient, I see the correct number:
I’d give your information to Microsoft in the form of a support incident to ask them to check out what’s going on. They can check the data against your tenant. I can’t!
Agreed, this needs to be shared with MS, however my intent to post here to understand if this is reproduced by others too.
Thanks for looking into it anyway!
Loading...
The problem is that we don’t have the same data to test against… so it’s hard to know if something in the data is causing the problem. But Microsoft can gain access (with your permission) to the data to check things out. Hence the recommendation.
Loading...
Hi
I am trying to create a Dynamic DL based on these filter Like EmailAddresses Like ‘@abc.com” Sample is -RecipientFilter {(RecipientType -eq ‘UserMailbox’ -and -not (UserAccountControl -eq “AccountDisabled, NormalAccount”) -and (EmailAddresses -Like ‘@abc.com’) -and (Title -like ‘General Manager*’))}.
The DL group did get created but no memebers. Can you please advise me what am I missing here.
Thank you in advanced.
HI Amardeep
I am using Get-Recipient -RecipientPreviewFilter $FTE.RecipientFilter -OrganizationalUnit $FTE.RecipientContainer to get the memership results
Loading...
I don’t think this is possible. You can only position the wildcard character at the end of strings in a recipient filter and I think you’d want to have it at the start. A quick search revealed that many people have had similar issues, so I will raise this with Microsoft.
Thank you for a good guide, it makes it a bit easier to understand. I did have a few questions and hopefully you can help with some answers. Do you know why after it is done, Exchange puts like so many parenthesis in front for example, here is the result I have:
To note, I have not created this, but I am simply looking to modifiy the (((-not(MemberOfGroup -eq ‘DC=ExcludeFromAllStaff’)) line since we have some issues with that group it looks like. I feel like all the parenthesis aren’t intentionally created by the end user and from your example, it doesn’t look like it.
This looks like it’s a custom filter created using PowerShell. Do you know how it was created?
The parenthesis are inserted by Exchange to make sure that all of its exclusions (no system mailboxes, no audit mailboxes, no disposition review mailboxes, no discovery mailboxes, and so on) do not show up in the returned set. You can’t do anything about the exclusions or how Exchange formats the command. All you can control is the recipient filter built with PowerShell. If that filter works with Get-Recipient, then it should work with the dynamic distribution list.
WRT the question about groups, I think any group supported by Exchange will work. The acid test is if it passes the recipient filter.
Unfortunately I don’t know how it was created. The client was onboarded to us with this already in place and we typically would not set up a dynamic distribution list (not a common practice for us).
I think maybe the option that you are hinting at, and correct me if I am wrong, but if I have a group named ExcludeFromGroupName, a test would be:
Get-Recipient -RecipientPreviewFilter $Filter | ft displayname, title
Do you know if the MemberOfGroup attributing is pulling the DisplayName option?
Thanks,
Brice H
Loading...
This works:
$DN = (Get-UnifiedGroup ExchangeGoms).DistinguishedName
$Filter = “((memberOfgroup -eq ‘$DN’) -and (RecipientType -eq ‘UserMailbox’))”
Get-Recipient -RecipientPreviewFilter $Filter | Ft DisplayName, Title
DisplayName Title
———– —–
Tony Redmond Principal Architect
Jeff Guillet Chief ExPTA
Global Tenant Administrator Office 365 Global Administrator
Vasil Michev (Technical Guru) Senior Architect
The important points here are that:
1. Use the distinguished name property to identify the group for use with MemberOfGroup.
2. The group can be a Microsoft 365 group (used in my example), a distribution list, or a dynamic distribution list. In other words, its membership has to be under the control of Exchange.
Loading...
Hi Tony,
Can I include On premise AD attribute which is syncing with Azure AD.
e,g Employee type Contractor or Employee
Hi Tony,
I have a question of how can we ADD a External Contact or another DL to the DDG that is trying to filter out other Contacts and DL’s
I’ve worked this script except to the point I need to add 4 Contacts either by DL or individuals. Please Take a look: Primary @SET-DDG where I try to add a DL that has the contacts.
I have replaced identifying information with simple 3 digit or letter combo’s
## Used with MFA to connect to ExchangeOnline
Connect-ExchangeOnline
## Enter the name of the Dynamic Distrobution Group here ##
$DistroIdentity = “123 ALL Emails”
## The Separation below is when you customize it per client to remove additional UserMailboxes that you do not want a part of the DDG ##
## If Alias doesn’t work, try DisplayName
I think you are over-complicating things. In situations like this, I use one of the Exchange custom attributes to identify the recipients to be in the DDG. Then you can simply filter on the CustomAttribute which works for all mail-enabled recipient types.
The documentation says that the values for ExchangeUserAccountControl:
For valid values, see ADS_USER_FLAG_ENUM enumeration. The integer values will work as described. Most of the text values won’t work as described (even if you remove ADS_UF and all underscores).
I don’t see a value there for AccountDisabled. Where did you get it?
I created a few DDLs withe intention of populating them with users who have the country or region attribute set according our office countries.
As an example I have used New-DynamicDistributionGroup -Name “Gibraltar Employees New” -RecipientFilter “(RecipientTypeDetails -eq ‘UserMailbox’) -and (CountryOrRegion -eq ‘Gibraltar’)”
I mass update all required users CountryOrRegion Attribute via PoSH and a CSV so I know they have this set. But for some reason the list is not fully populating when I check with PoSH using Get-Recipient -RecipientPreviewFilter (Get-DynamicDistributionGroup “Malta Employees New”).RecipientFilter.
Perhaps I have something wrong but I can’t see what.
Hey Tony, just wanted to say thanks for the help – in the end I went with City as I was trying to match this with a dynamic security group for group licensing which I know have all of these working.
One follow up question, if I wanted to create a DDL using multiple cities using the below filters would that work?
It did create the DDL when I ran the script and I can see it in Exchange but I am wondering if this is like the security group filter where you can have and or? I would think and (City -eq ‘Gibraltar, Malta, IOM, Budapest’)” means any of these cities not that they need all of them.
I want to make this as a global DL – with all office locations staff being dynamically added in.
Thanks
Loading...
I think you will need -or clauses to match against multiple city names. AFAIK, the -eq clause doesn’t take multiple values to match against. This is easily validated by using the Get-Recipient cmdlet to test the recipient filter.
Loading...
Tony, Do you know “When MS will allow using wildcard as first character to create the Dynamic groups” We are unable to create Dynamic groups based on Primary smtp domain since it does not accept asterisk in the beginning. I know and we can use WindowsLiveDomain field which accept asterisk in beginning but this is not helping us since WindowsLiveDomain field is same for all users in our firm. Any ideas??
I wouldn’t hold my breath waiting for Microsoft to support wildcards for domain names. Which is why I used the technique explained in https://practical365.com/adaptive-scope-domain-name/ to create an adaptive scope based on a domain name. The same principal applies.
Hi all. I have a few DDL’s based on the users Office location which all work well. Recently we have started using group based licencing where the O365 licence is applied to a group and the user is a member of the group. The new users who have had their licences applied this way are missing from the DDL where all other users on there.
Is there an issue with the DDL not detecting the user licence ?
Is there a way to include unlicenced users in the DDL ?
Or am I totally on the wrong track ???
{"id":null,"mode":"button","open_style":"in_modal","currency_code":"EUR","currency_symbol":"\u20ac","currency_type":"decimal","blank_flag_url":"https:\/\/office365itpros.com\/wp-content\/plugins\/tip-jar-wp\/\/assets\/images\/flags\/blank.gif","flag_sprite_url":"https:\/\/office365itpros.com\/wp-content\/plugins\/tip-jar-wp\/\/assets\/images\/flags\/flags.png","default_amount":100,"top_media_type":"featured_image","featured_image_url":"https:\/\/office365itpros.com\/wp-content\/uploads\/2022\/11\/cover-141x200.jpg","featured_embed":"","header_media":null,"file_download_attachment_data":null,"recurring_options_enabled":true,"recurring_options":{"never":{"selected":true,"after_output":"One time only"},"weekly":{"selected":false,"after_output":"Every week"},"monthly":{"selected":false,"after_output":"Every month"},"yearly":{"selected":false,"after_output":"Every year"}},"strings":{"current_user_email":"","current_user_name":"","link_text":"Virtual Tip Jar","complete_payment_button_error_text":"Check info and try again","payment_verb":"Pay","payment_request_label":"Office 365 for IT Pros","form_has_an_error":"Please check and fix the errors above","general_server_error":"Something isn't working right at the moment. Please try again.","form_title":"Office 365 for IT Pros","form_subtitle":null,"currency_search_text":"Country or Currency here","other_payment_option":"Other payment option","manage_payments_button_text":"Manage your payments","thank_you_message":"Thank you for supporting the work of Office 365 for IT Pros!","payment_confirmation_title":"Office 365 for IT Pros","receipt_title":"Your Receipt","print_receipt":"Print Receipt","email_receipt":"Email Receipt","email_receipt_sending":"Sending receipt...","email_receipt_success":"Email receipt successfully sent","email_receipt_failed":"Email receipt failed to send. Please try again.","receipt_payee":"Paid to","receipt_statement_descriptor":"This will show up on your statement as","receipt_date":"Date","receipt_transaction_id":"Transaction ID","receipt_transaction_amount":"Amount","refund_payer":"Refund from","login":"Log in to manage your payments","manage_payments":"Manage Payments","transactions_title":"Your Transactions","transaction_title":"Transaction Receipt","transaction_period":"Plan Period","arrangements_title":"Your Plans","arrangement_title":"Manage Plan","arrangement_details":"Plan Details","arrangement_id_title":"Plan ID","arrangement_payment_method_title":"Payment Method","arrangement_amount_title":"Plan Amount","arrangement_renewal_title":"Next renewal date","arrangement_action_cancel":"Cancel Plan","arrangement_action_cant_cancel":"Cancelling is currently not available.","arrangement_action_cancel_double":"Are you sure you'd like to cancel?","arrangement_cancelling":"Cancelling Plan...","arrangement_cancelled":"Plan Cancelled","arrangement_failed_to_cancel":"Failed to cancel plan","back_to_plans":"\u2190 Back to Plans","update_payment_method_verb":"Update","sca_auth_description":"Your have a pending renewal payment which requires authorization.","sca_auth_verb":"Authorize renewal payment","sca_authing_verb":"Authorizing payment","sca_authed_verb":"Payment successfully authorized!","sca_auth_failed":"Unable to authorize! Please try again.","login_button_text":"Log in","login_form_has_an_error":"Please check and fix the errors above","uppercase_search":"Search","lowercase_search":"search","uppercase_page":"Page","lowercase_page":"page","uppercase_items":"Items","lowercase_items":"items","uppercase_per":"Per","lowercase_per":"per","uppercase_of":"Of","lowercase_of":"of","back":"Back to plans","zip_code_placeholder":"Zip\/Postal Code","download_file_button_text":"Download File","input_field_instructions":{"tip_amount":{"placeholder_text":"How much would you like to tip?","initial":{"instruction_type":"normal","instruction_message":"How much would you like to tip? Choose any currency."},"empty":{"instruction_type":"error","instruction_message":"How much would you like to tip? Choose any currency."},"invalid_curency":{"instruction_type":"error","instruction_message":"Please choose a valid currency."}},"recurring":{"placeholder_text":"Recurring","initial":{"instruction_type":"normal","instruction_message":"How often would you like to give this?"},"success":{"instruction_type":"success","instruction_message":"How often would you like to give this?"},"empty":{"instruction_type":"error","instruction_message":"How often would you like to give this?"}},"name":{"placeholder_text":"Name on Credit Card","initial":{"instruction_type":"normal","instruction_message":"Enter the name on your card."},"success":{"instruction_type":"success","instruction_message":"Enter the name on your card."},"empty":{"instruction_type":"error","instruction_message":"Please enter the name on your card."}},"privacy_policy":{"terms_title":"Terms and conditions","terms_body":null,"terms_show_text":"View Terms","terms_hide_text":"Hide Terms","initial":{"instruction_type":"normal","instruction_message":"I agree to the terms."},"unchecked":{"instruction_type":"error","instruction_message":"Please agree to the terms."},"checked":{"instruction_type":"success","instruction_message":"I agree to the terms."}},"email":{"placeholder_text":"Your email address","initial":{"instruction_type":"normal","instruction_message":"Enter your email address"},"success":{"instruction_type":"success","instruction_message":"Enter your email address"},"blank":{"instruction_type":"error","instruction_message":"Enter your email address"},"not_an_email_address":{"instruction_type":"error","instruction_message":"Make sure you have entered a valid email address"}},"note_with_tip":{"placeholder_text":"Your note here...","initial":{"instruction_type":"normal","instruction_message":"Attach a note to your tip (optional)"},"empty":{"instruction_type":"normal","instruction_message":"Attach a note to your tip (optional)"},"not_empty_initial":{"instruction_type":"normal","instruction_message":"Attach a note to your tip (optional)"},"saving":{"instruction_type":"normal","instruction_message":"Saving note..."},"success":{"instruction_type":"success","instruction_message":"Note successfully saved!"},"error":{"instruction_type":"error","instruction_message":"Unable to save note note at this time. Please try again."}},"email_for_login_code":{"placeholder_text":"Your email address","initial":{"instruction_type":"normal","instruction_message":"Enter your email to log in."},"success":{"instruction_type":"success","instruction_message":"Enter your email to log in."},"blank":{"instruction_type":"error","instruction_message":"Enter your email to log in."},"empty":{"instruction_type":"error","instruction_message":"Enter your email to log in."}},"login_code":{"initial":{"instruction_type":"normal","instruction_message":"Check your email and enter the login code."},"success":{"instruction_type":"success","instruction_message":"Check your email and enter the login code."},"blank":{"instruction_type":"error","instruction_message":"Check your email and enter the login code."},"empty":{"instruction_type":"error","instruction_message":"Check your email and enter the login code."}},"stripe_all_in_one":{"initial":{"instruction_type":"normal","instruction_message":"Enter your credit card details here."},"empty":{"instruction_type":"error","instruction_message":"Enter your credit card details here."},"success":{"instruction_type":"normal","instruction_message":"Enter your credit card details here."},"invalid_number":{"instruction_type":"error","instruction_message":"The card number is not a valid credit card number."},"invalid_expiry_month":{"instruction_type":"error","instruction_message":"The card's expiration month is invalid."},"invalid_expiry_year":{"instruction_type":"error","instruction_message":"The card's expiration year is invalid."},"invalid_cvc":{"instruction_type":"error","instruction_message":"The card's security code is invalid."},"incorrect_number":{"instruction_type":"error","instruction_message":"The card number is incorrect."},"incomplete_number":{"instruction_type":"error","instruction_message":"The card number is incomplete."},"incomplete_cvc":{"instruction_type":"error","instruction_message":"The card's security code is incomplete."},"incomplete_expiry":{"instruction_type":"error","instruction_message":"The card's expiration date is incomplete."},"incomplete_zip":{"instruction_type":"error","instruction_message":"The card's zip code is incomplete."},"expired_card":{"instruction_type":"error","instruction_message":"The card has expired."},"incorrect_cvc":{"instruction_type":"error","instruction_message":"The card's security code is incorrect."},"incorrect_zip":{"instruction_type":"error","instruction_message":"The card's zip code failed validation."},"invalid_expiry_year_past":{"instruction_type":"error","instruction_message":"The card's expiration year is in the past"},"card_declined":{"instruction_type":"error","instruction_message":"The card was declined."},"missing":{"instruction_type":"error","instruction_message":"There is no card on a customer that is being charged."},"processing_error":{"instruction_type":"error","instruction_message":"An error occurred while processing the card."},"invalid_request_error":{"instruction_type":"error","instruction_message":"Unable to process this payment, please try again or use alternative method."},"invalid_sofort_country":{"instruction_type":"error","instruction_message":"The billing country is not accepted by SOFORT. Please try another country."}}}},"fetched_oembed_html":false}
Be aware a bug exists in the New EAC where any Custom recipient filter set on a DDG is wiped and replaced by a Precanned recipient filter when the DDG properties are opened and saved. The default Precanned filter that is applied will include all reciepient types. Resulting in emails sent to the DDG going to all mailboxes in the organisation as well as external recipients. When the DDG properties are opened in the New EAC, the save button is available even if the user does not change anything.
Due to this bug. It is recommended not to use the New EAC to manage DDGs with custom reciepient filters. Only use PowerShell.
Microsoft has been made aware of this bug. While they have recognised the bug they have not provided a timeline for resolution.
Personally speaking, I would never go near the EAC when dealing with DDGs with custom filters. The record of dealing with these filters is not good.
I am trying to build DDL based on StreetAddress but getting some weird syntax error. Can you please help? Basically, need to have DDL of mailbox users whose streetAddress is “Sterling”
$filter = “((((((RecipientType -eq ‘UserMailbox’))) -and (-not(UserAccountControl -eq ‘AccountDisabled, NormalAccount’)))) -and (-not(Name -like ‘SystemMailbox{*’)) -and (-not(Name -like ‘CAS_{*’)) -and (-not(RecipientTypeDetailsValue -eq ‘MailboxPlan’)) -and (-not(RecipientTypeDetailsValue -eq ‘DiscoveryMailbox’)) -and (-not(RecipientTypeDetailsValue -eq ‘PublicFolderMailbox’)) -and (-not(RecipientTypeDetailsValue -eq ‘ArbitrationMailbox’)) -and (-not(RecipientTypeDetails -eq ‘SharedMailbox’) -and (-not(RecipientTypeDetailsValue -eq ‘AuditLogMailbox’)) -and (-not(RecipientTypeDetailsValue -eq ‘AuxAuditLogMailbox’)) -and (-not(RecipientTypeDetailsValue -eq ‘SupervisoryReviewPolicyMailbox’)) -and (StreetAddress -eq ‘sterling’)”
$Filter = “(StreetAddress -eq ‘Sterling’)”
And then create the DDL using the filter defined in $Filter as explained in the article…
Hello. I’m try create ddg filter based emails with script below:
New-DynamicDistributionGroup -Alias “Everyone” -Name Husola Everyone” -RecipientFilter {(RecipientType -eq ‘UserMailbox’) -and (EmailAddresses -like ‘*husola.de*’)} -PrimarySmtpAddress “Everyone@husola.de”
And the output is:
((((RecipientType -eq ‘UserMailbox’) -and (EmailAddresses -like ‘*husola.de*’))) -and (-not(Name -like ‘SystemMailbox{*’)) -and (-not(Name -like ‘CAS_{*’)) -and (-not(RecipientTypeDetailsValue -eq ‘MailboxPlan’)) -and (-not(RecipientTypeDetailsValue -eq ‘DiscoveryMailbox’)) -and (-not(RecipientTypeDetailsValue -eq ‘PublicFolderMailbox’)) -and (-not(RecipientTypeDetailsValue -eq ‘ArbitrationMailbox’)) -and (-not(RecipientTypeDetailsValue -eq ‘AuditLogMailbox’)))
But when i sending mail in Everyone@husola.de nobody getting mail with smtp @husola.de. Where and what am I doing wrong?
I want to note that we have had filters like this one for many years and work perfectly, but this is what does not work.
What do you get when you try the recipient filter from the DDG with Get-Recipient?
This works for me:
$Filter = “((EmailAddresses -like ‘*Office365itpros*’) -and (RecipientTypeDetails -eq ‘UserMailbox’))”
get-recipient -RecipientPreviewFilter $Filter
But the filter doesn’t work with the DDG because Exchange Online doesn’t support a wildcard character as the start of a term – only at the end (I know that https://docs.microsoft.com/en-us/powershell/exchange/recipientfilter-properties?view=exchange-ps specifies that wildcards can be used withg EmailAddresses, but only at the end):
Text string properties that accept wildcard characters require the -like operator (for example, “Property -like ‘abc*'”). In Exchange Online PowerShell, you can’t use the wildcard as a prefix (for example, “Property -like ‘*abc'”) is not allowed).
Firstly, I want to say that I am doing this on On-premise (local) Exchange 2013.
What do you get when you try the recipient filter from the DDG with Get-Recipient?
I get a list of users who have this smtp address.
My this command for on-premise exchange 2013 wrong?:
New-DynamicDistributionGroup -Alias “Everyone” -Name Husola Everyone” -RecipientFilter {(RecipientType -eq ‘UserMailbox’) -and (EmailAddresses -like ‘*husola.de*’)} -PrimarySmtpAddress “Everyone@husola.de”
Hi Tony,
Please let me know how to pass wildcard as a prefix, I have few property where I want to pass it like *abc*.
Please let me know if there is any way.
You can’t. Exchange Online doesn’t support wildcards in recipient filters except as a suffix.
Hello,
i’m try to create a DDL based on a active directory group:
set-DynamicDistributionGroup “AllUserInGroup” -recipientFilter “(sAMAccountName -eq ‘TEST_DYNAMIC_GROUP_0365’)”
but don’t working
That looks as if you’re trying to create a dynamic group membership from the membership of another dynamic group… I don’t believe you can do that.
so it is impossible to add unique members of a specific group to a DDL?
Use the MemberOfGroup Property as per https://docs.microsoft.com/en-us/powershell/exchange/recipientfilter-properties?view=exchange-ps
$Filter = “MemberOfGroup -eq ‘$DN'”
$Dn = (Get-DistributionGroup -Identity ‘Tiger Team’).DistinguishedName
Get-Recipient -RecipientPreviewFilter $Filter
These few filters are very fun to work with, However found something strange, hence wanted to clarify with the experts:)
Here is an easiest filter I have applied,
$Filter = ((UsageLocation -eq ‘US’) -and (CustomAttribute15 -eq ’employee’))
Now, when preview the filter, I’m returned with 360 entries:
(Get-Recipient -RecipientPreviewFilter $filter).count
360
However, When this filter is set in the DDG, it doesn’t give me 360 members instead it give me a higher number.
Here are the recipient filters after updating:
RecipientFilter: ((((((RecipientType -eq ‘UserMailbox’) -and (UsageLocation -eq ‘United States’))) -and (CustomAttribute15 -eq ’employee’))) -and (-not(Name -like ‘SystemMailbox{*’)) -and (-not(Name -like ‘CAS_{*’)) -and (-not(RecipientTypeDetailsValue -eq ‘MailboxPlan’)) -and (-not(RecipientTypeDetailsValue -eq ‘DiscoveryMailbox’)) -and (-not(RecipientTypeDetailsValue -eq ‘PublicFolderMailbox’)) -and (-not(RecipientTypeDetailsValue -eq ‘ArbitrationMailbox’)) -and (-not(RecipientTypeDetailsValue -eq ‘AuditLogMailbox’)) -and (-not(RecipientTypeDetailsValue -eq ‘AuxAuditLogMailbox’)) -and (-not(RecipientTypeDetailsValue -eq ‘SupervisoryReviewPolicyMailbox’)))
Here is the count I get, when I do Get-DynamicDistributionGroupMembers (I don’t think this command existed before)
(Get-DynamicDistributionGroupMember It.test).count
553
Strangely, When I try to review the member using the legacy way, that is, storing the recipient filter after a variable and the calling that using get-recipient, I see the correct number:
$ITDdg = Get-DynamicDistributionGroup it.test
(Get-Recipient -RecipientPreviewFilter $ITDdg.RecipientFilter).count
360
Now, either the new cmdlet Get-DynamicDistributionGroupMember is not showing the correct number or my filter has a syntax error.
Please suggest.
I’d give your information to Microsoft in the form of a support incident to ask them to check out what’s going on. They can check the data against your tenant. I can’t!
Thanks for your response, Tony!
Agreed, this needs to be shared with MS, however my intent to post here to understand if this is reproduced by others too.
Thanks for looking into it anyway!
The problem is that we don’t have the same data to test against… so it’s hard to know if something in the data is causing the problem. But Microsoft can gain access (with your permission) to the data to check things out. Hence the recommendation.
Hi
I am trying to create a Dynamic DL based on these filter Like EmailAddresses Like ‘@abc.com” Sample is -RecipientFilter {(RecipientType -eq ‘UserMailbox’ -and -not (UserAccountControl -eq “AccountDisabled, NormalAccount”) -and (EmailAddresses -Like ‘@abc.com’) -and (Title -like ‘General Manager*’))}.
The DL group did get created but no memebers. Can you please advise me what am I missing here.
Thank you in advanced.
How are you validating the group membership?
HI Amardeep
I am using Get-Recipient -RecipientPreviewFilter $FTE.RecipientFilter -OrganizationalUnit $FTE.RecipientContainer to get the memership results
I don’t think this is possible. You can only position the wildcard character at the end of strings in a recipient filter and I think you’d want to have it at the start. A quick search revealed that many people have had similar issues, so I will raise this with Microsoft.
Hi Tony,
Thank you for a good guide, it makes it a bit easier to understand. I did have a few questions and hopefully you can help with some answers. Do you know why after it is done, Exchange puts like so many parenthesis in front for example, here is the result I have:
((((((((((((((((((((((RecipientType -eq ‘UserMailbox’) -and (((-not(Name -like ‘REDACTED’)) -and (((-not(MemberOfGroup -eq ‘DC=ExcludeFromAllStaff’)) -and (((-not(Name -like ‘REDACTED’)) -and (-not(RecipientTypeDetailsValue -eq ‘RoomMailbox’)))))))))) -and (-not(Name -like ‘SystemMailbox{*’)))) -and (-not(Name -like ‘CAS_{*’)))) -and (-not(RecipientTypeDetailsValue -eq ‘MailboxPlan’)))) -and (-not(RecipientTypeDetailsValue -eq ‘DiscoveryMailbox’)))) -and (-not(RecipientTypeDetailsValue -eq ‘PublicFolderMailbox’)))) -and (-not(RecipientTypeDetailsValue -eq ‘ArbitrationMailbox’)))) -and (-not(RecipientTypeDetailsValue -eq ‘AuditLogMailbox’)))) -and (-not(RecipientTypeDetailsValue -eq ‘AuxAuditLogMailbox’)))) -and (-not(RecipientTypeDetailsValue -eq ‘SupervisoryReviewPolicyMailbox’)))) -and (-not(Name -like ‘SystemMailbox{*’)) -and (-not(Name -like ‘CAS_{*’)) -and (-not(RecipientTypeDetailsValue -eq ‘MailboxPlan’)) -and (-not(RecipientTypeDetailsValue -eq ‘DiscoveryMailbox’)) -and (-not(RecipientTypeDetailsValue -eq ‘PublicFolderMailbox’)) -and (-not(RecipientTypeDetailsValue -eq ‘ArbitrationMailbox’)) -and (-not(RecipientTypeDetailsValue -eq ‘AuditLogMailbox’)) -and (-not(RecipientTypeDetailsValue -eq ‘AuxAuditLogMailbox’)) -and (-not(RecipientTypeDetailsValue -eq ‘SupervisoryReviewPolicyMailbox’)))
To note, I have not created this, but I am simply looking to modifiy the (((-not(MemberOfGroup -eq ‘DC=ExcludeFromAllStaff’)) line since we have some issues with that group it looks like. I feel like all the parenthesis aren’t intentionally created by the end user and from your example, it doesn’t look like it.
Also, reading the specific recipient filter properties here: https://docs.microsoft.com/en-us/powershell/exchange/recipientfilter-properties?view=exchange-ps
Do you know if it supports Cloud only Security Groups or would I need to convert it to a Mail-enabled security group to get the MemberofGroup functionality working again?
I appreciate your time and response.
Thank you,
Brice H
This looks like it’s a custom filter created using PowerShell. Do you know how it was created?
The parenthesis are inserted by Exchange to make sure that all of its exclusions (no system mailboxes, no audit mailboxes, no disposition review mailboxes, no discovery mailboxes, and so on) do not show up in the returned set. You can’t do anything about the exclusions or how Exchange formats the command. All you can control is the recipient filter built with PowerShell. If that filter works with Get-Recipient, then it should work with the dynamic distribution list.
WRT the question about groups, I think any group supported by Exchange will work. The acid test is if it passes the recipient filter.
Unfortunately I don’t know how it was created. The client was onboarded to us with this already in place and we typically would not set up a dynamic distribution list (not a common practice for us).
I think maybe the option that you are hinting at, and correct me if I am wrong, but if I have a group named ExcludeFromGroupName, a test would be:
$Filter = “((MemberOfGroup -eq ‘ExcludeFromGroupName’))”
Get-Recipient -RecipientPreviewFilter $Filter | ft displayname, title
Do you know if the MemberOfGroup attributing is pulling the DisplayName option?
Thanks,
Brice H
This works:
$DN = (Get-UnifiedGroup ExchangeGoms).DistinguishedName
$Filter = “((memberOfgroup -eq ‘$DN’) -and (RecipientType -eq ‘UserMailbox’))”
Get-Recipient -RecipientPreviewFilter $Filter | Ft DisplayName, Title
DisplayName Title
———– —–
Tony Redmond Principal Architect
Jeff Guillet Chief ExPTA
Global Tenant Administrator Office 365 Global Administrator
Vasil Michev (Technical Guru) Senior Architect
The important points here are that:
1. Use the distinguished name property to identify the group for use with MemberOfGroup.
2. The group can be a Microsoft 365 group (used in my example), a distribution list, or a dynamic distribution list. In other words, its membership has to be under the control of Exchange.
Hi Tony,
Can I include On premise AD attribute which is syncing with Azure AD.
e,g Employee type Contractor or Employee
You can only include properties from the supported set (see link in article).
Hi Tony,
I have a question of how can we ADD a External Contact or another DL to the DDG that is trying to filter out other Contacts and DL’s
I’ve worked this script except to the point I need to add 4 Contacts either by DL or individuals. Please Take a look: Primary @SET-DDG where I try to add a DL that has the contacts.
I have replaced identifying information with simple 3 digit or letter combo’s
## Used with MFA to connect to ExchangeOnline
Connect-ExchangeOnline
## Enter the name of the Dynamic Distrobution Group here ##
$DistroIdentity = “123 ALL Emails”
$List=Get-DynamicDistributionGroup $DistroIdentity
## The Separation below is when you customize it per client to remove additional UserMailboxes that you do not want a part of the DDG ##
## If Alias doesn’t work, try DisplayName
Set-DynamicDistributionGroup -identity $DistroIdentity -RecipientFilter {(EmailAddresses -eq “team4@123.com”)
-and (-not(RecipientTypeDetailsValue -eq ‘SharedMailbox’))
-and (-not(RecipientTypeDetailsValue -eq ‘RoomMailbox’))
-and (-not(RecipientType -eq ‘MailContact’))
-and (-not(RecipientType -eq ‘MailUniversalDistributionGroup’))
-and (-not(RecipientType -eq ‘MailUniversalSecurityGroup’))
-and (-not(RecipientTypeDetailsValue -eq ‘EquipmentMailbox’))
-and (-not(RecipientType -eq ‘MailUser’))
-and (-not(RecipientType -eq ‘DynamicDistributionGroup’))
-and (-not(DisplayName -eq “Scanner”))
-and (-not(Alias -eq “123”))
-and (-not(Alias -eq “234”))
-and (-not(Alias -eq “spadmin”))
-and (-not(Alias -eq “ConferenceRoom”))
-and (-not(Alias -eq “crestronmanagementaccount”))
-and (-not(Alias -eq “zoomroomadmin”))
-and (-not(Alias -eq “345”))
-and (-not(Displayname -eq “456”))
-and (-not(Alias -eq “567”))
-and (-not(Displayname -eq “678”))
-and (-not(Displayname -eq “789”))
-and (-not(Displayname -eq “890”))
-and (-not(Displayname -eq “abc”))
-and (-not(Alias -eq “bcd”))
-and (-not(Alias -eq “cde”))
-and (-not(Displayname -eq “def”))
-and (-not(Displayname -eq “efg”))
-and (-not(Displayname -eq “fgh”))
-and (-not(Displayname -eq “ghi”))
-and (-not(Alias -eq “hij”))
-and (-not(Displayname -eq “ijk”))
}
Get-Recipient -RecipientPreviewFilter $List.RecipientFilter
I think you are over-complicating things. In situations like this, I use one of the Exchange custom attributes to identify the recipients to be in the DDG. Then you can simply filter on the CustomAttribute which works for all mail-enabled recipient types.
I am attempting to remove disabled accounts from a DDL, however it is not working. We are syncing with on-prem AD to Azure for 365.
Here is the validation I am doing, but disabled users are still included:
$Filter = “((Department -like ‘IT*’) -or (Department -eq ‘Data Analytics and Reporting’) -or (Title -eq ‘Chief Information Officer’) -and (RecipientType -eq ‘UserMailbox’) -and (ExchangeUserAccountControl -ne ‘AccountDisabled’))”
get-recipient -RecipientPreviewFilter $Filter
The documentation says that the values for ExchangeUserAccountControl:
For valid values, see ADS_USER_FLAG_ENUM enumeration. The integer values will work as described. Most of the text values won’t work as described (even if you remove ADS_UF and all underscores).
I don’t see a value there for AccountDisabled. Where did you get it?
I did see a suggested answer on https://social.technet.microsoft.com/Forums/windowsserver/en-US/00aeef18-6528-42a0-9760-118479bf9a7c/dynamic-distribution-list-exclude-disabled-accounts that you could check out.
Hi Tony,
I created a few DDLs withe intention of populating them with users who have the country or region attribute set according our office countries.
As an example I have used New-DynamicDistributionGroup -Name “Gibraltar Employees New” -RecipientFilter “(RecipientTypeDetails -eq ‘UserMailbox’) -and (CountryOrRegion -eq ‘Gibraltar’)”
I mass update all required users CountryOrRegion Attribute via PoSH and a CSV so I know they have this set. But for some reason the list is not fully populating when I check with PoSH using Get-Recipient -RecipientPreviewFilter (Get-DynamicDistributionGroup “Malta Employees New”).RecipientFilter.
Perhaps I have something wrong but I can’t see what.
As per https://docs.microsoft.com/en-us/powershell/exchange/recipientfilter-properties?view=exchange-ps&WT.mc_id=M365-MVP-9501, the country property is passed as Co.
I did this:
$Filter = “(RecipientTypeDetails -eq ‘UserMailbox’) -and (Co -eq ‘Ireland’)”
New-DynamicDistributionGroup -Name “Ireland Employees (New)” -RecipientFilter $Filter -Alias Ireland.Employees.New
Everything worked.. Maybe try Co?
Hey Tony, just wanted to say thanks for the help – in the end I went with City as I was trying to match this with a dynamic security group for group licensing which I know have all of these working.
One follow up question, if I wanted to create a DDL using multiple cities using the below filters would that work?
New-DynamicDistributionGroup -Name “All Employees New” -RecipientFilter “(RecipientTypeDetails -eq ‘UserMailbox’) -and (City -eq ‘Gibraltar, Malta, IOM, Budapest’)”
It did create the DDL when I ran the script and I can see it in Exchange but I am wondering if this is like the security group filter where you can have and or? I would think and (City -eq ‘Gibraltar, Malta, IOM, Budapest’)” means any of these cities not that they need all of them.
I want to make this as a global DL – with all office locations staff being dynamically added in.
Thanks
I think you will need -or clauses to match against multiple city names. AFAIK, the -eq clause doesn’t take multiple values to match against. This is easily validated by using the Get-Recipient cmdlet to test the recipient filter.
Tony, Do you know “When MS will allow using wildcard as first character to create the Dynamic groups” We are unable to create Dynamic groups based on Primary smtp domain since it does not accept asterisk in the beginning. I know and we can use WindowsLiveDomain field which accept asterisk in beginning but this is not helping us since WindowsLiveDomain field is same for all users in our firm. Any ideas??
I wouldn’t hold my breath waiting for Microsoft to support wildcards for domain names. Which is why I used the technique explained in https://practical365.com/adaptive-scope-domain-name/ to create an adaptive scope based on a domain name. The same principal applies.
I would like to create DDL based on country.
I bet you would. And you’ve investigated the list of filterable properties?
Hi all. I have a few DDL’s based on the users Office location which all work well. Recently we have started using group based licencing where the O365 licence is applied to a group and the user is a member of the group. The new users who have had their licences applied this way are missing from the DDL where all other users on there.
Is there an issue with the DDL not detecting the user licence ?
Is there a way to include unlicenced users in the DDL ?
Or am I totally on the wrong track ???
Are DDLs supported for group-based licensing? The last time I looked, a security group was needed and that seems to be the same now as per https://learn.microsoft.com/en-us/azure/active-directory/fundamentals/active-directory-licensing-whatis-azure-portal