Who doesn’t love Exchange Online dynamic distribution groups? It’s like cattle that sort themselves. Or maybe you don’t love them, but who loves maintaining super large distribution groups? (Not this guy) It’s like feeling good about who you are as a person when comparing yourself to Hitler. You may not be the best, but compared to a dictator you’re fantastic regardless of what HR says about you! Dynamically assigning membership as opposed to keeping up with a regular distribution group is very similar to eating a nice steak dinner (or a delicious grass filet if you’re in to that) versus stepping on a LEGO in the dark. It makes groups great again.

Office 365 with Exchange Online lets you create dynamic distribution groups in the Exchange Admin Center (EAC) but we don’t have a lot of control over the rules for determining membership. In fact, unless our Exchange Online dynamic distribution group has a requirement that we can achieve by using one of the few built in rules like company, department, state, or one of the custom attributes, it looks like we’re out of luck.

But have no fear! Like most things in Microsoft Land, we’re able to do a bit more customization behind the curtain, which inevitably leads us to PowerShell. As the famous adage goes: all roads lead to Ro—PowerShell.

\\\PowerShell Solves Everything

First, we need to connect to Exchange Online. I’ve written mine into a script that I call, but basically here’s what you need to connect to it first:

#Connect to Exchange Online
$Cred = Get-Credential
$Session = New-PSSession -ConfigurationName microsoft.exchange -ConnectionUri https://ps.outlook.com/powershell -Credential $Cred -Authentication Basic -AllowRedirection
Import-PSSession $Session

Once you’re connected, the aptly named Get-DynamicDistributionGroup will do the trick. If we haven’t created the group yet, we can use New- or we can use a Get-/Set- if we’ve already created it.

In my world, I have a need for an “All Users” mailbox that is limited to only user mailboxes. One would assume that by checking the “Users with Exchange mailboxes” that we would be selecting, oh, you know…users with exchange mailboxes:

But that’s a lie. It grabs shared mailboxes too. Well, it’s not really a fib because Shared Mailboxes are kind of special and technically they’re classified as a “UserMailbox,” but the betrayal still stings.

\\\Let’s Demonstrate

To determine the membership of a dynamic distribution group and see who’s hot and who’s not, we first have to get the “Recipient Filter” of the group. We can get the distro with Get-DynamicDistributionGroup, assign it to a variable, and then reference the filter in the Get-Recipient cmdlet. We’re going to pipe our output to the select alias for Select-Object and choose the Name, RecipientType, and RecipientTypeDetails to show that user and shared mailboxes are both classified as “User Mailboxes.”

$Distro = Get-DynamicDistributionGroup DistroInferno
Get-Recipient -RecipientPreviewFilter $Distro.RecipientFilter | select name, recipienttype, recipienttypedetails

Great. That’s just great. Don’t cancel your O365 subscription just yet, we can fix it Felix!

\\\The Filter Mothership

Let’s start by looking at the filter that’s created behind the scenes whenever we only check the “Users with Exchange mailboxes” box in the EAC. We can use the $Distro variable we’ve already defined and use dot notation to view the “RecipientFilter”:


Yeah, that looks like fun. If your filter could use a filter, it might be too long. In plain[er] English, what we’re trying to say is:

  • RecipientType IS UserMailbox
  • Name DOES NOT start with SystemMailbox or CAS
  • RecipientTypeDetailsValue IS NOT MailboxPlan, DiscoveryMailbox, PublicFolderMailbox, ArbitrationMailbox, AuditLogMailbox, AuxAuditLogMailbox, SupervisoryReviewPolicyMailbox, or GuestMailUser

\\\Need More Filter

Believe it or not, we actually want to add something to this…specifically we don’t want to have mailboxes with the RecipientTypeDetails value of “SharedMailbox.” But, instead of adding to it, we can also accomplish this by ONLY allowing mailboxes with the RecipientTypeDetails of “UserMailbox,” which will filter out Shared Mailboxes and anything else we don’t know about. We want to add something like this:

"{(RecipientTypeDetailsValue -eq 'UserMailbox')}"

So, me and my big brain has idea. (Dear Grammar Nazi, I’m well aware of the grammatical atrocities just committed. Don’t get your ones and zeroes in a bunch.)

My idea is to grab the filter, add our additional filter, and then set it back.

Wait…don’t do this.

Long story short, Exchange Online is doing some magic behind the scenes and converting our filter when we add it. If we take the existing filter, add our line to it, and add it all back, it will end up duplicating what was there already in the filter. We can avoid this by only adding our one line instead of adding our line and the existing filter. My great idea ended up not working. First time that’s ever happened. Very surprising.

Even though (at least to me) this looks like we’re going to replace the filter instead of adding to it, this actually adds to the existing filter:

$Filter = "{(RecipientTypeDetailsValue -eq 'UserMailbox')}"
Set-DynamicDistributionGroup -Identity DistroInferno -RecipientFilter $Filter

\\\Discount Double Check

After we run this, let’s get our distro again, assign it to $Distro variable, and use the Recipient Filter to see what the members of our dynamic distribution group would be:

$Distro = Get-DynamicDistributionGroup DistroInferno
Get-Recipient -RecipientPreviewFilter $Distro.RecipientFilter | select name, recipienttype, recipienttypedetails

Makes me happier than a Tusken Raider in a sandbox. As you can see, our new filter doesn’t include shared mailboxes. Our evil plan worked.

And now you know how to use recipient filters for Exchange Online dynamic distribution groups. What other filters have you used on your dynamic distribution groups? Hit me up in the comments below!


Index Scripts for Windows Search

So you just finished writing some code and you go to save your file. You summarize all of the important aspects this section of code contains into a nice, easy-to-read file name that your future self will immediately recognize. Fast forward to the future where you...

Array vs ArrayList (PowerShell)

For some tasks in life, being precise is a necessity. But most of us get away with rounding, paraphrasing, and hitting in the general vicinity most of the time. Depending on your personality, you may be one who strives for perfection and strains on every miniscule...

Spice Up HTML Emails with PowerShell – Part III

So far in this series we've fumbled our way around the kitchen and tried to wing it when sending HTML emails with PowerShell. It was clunky to say the least. We then went through our spice rack and built an HTML template, highlighting the nuances of each spicy element...

Spice up HTML Emails with PowerShell – Part II

In Part I of our scrumptious concoction we put our script into the oven to let it bake. But we forgot to add our secret sauce that's sure to leave our recipients drooling, which is clearly our goal. In this post we'll continue to spice up HTML emails with PowerShell...

Spice Up HTML Emails with PowerShell – Part I

I live in the South, specifically in God's country AKA TEXAS BABAY! There's plenty of amazing things about Texas and definitely some reasons to loathe being from Houston, but it's hard to knock our food. I mean, is there really even a debate between Whataburger vs...