Dynamische Verteiler und Exchange Hybrid

Diese Seite beschreibt die Besonderheiten von dynamischen Verteilergruppen in Exchange OnPremise und Exchange Online in Verbindung mit dem Verzeichnisabgleich. Diese Seite ist für sie nur relevant, wenn Sie in Exchange Online oder OnPremises mit dynamischen Verteilerlisten arbeiten und Hybrid sind.

Kurzfassen: Dynamischen Verteilerlisten ignorieren "Remote Mailbox"-Empfänger, d.h. eine Mail an so eine Verteilerliste kommt nicht auf der anderen Seite an

Thematisch gehört diese Seite auch zum Bereich Exchange Online - Migration und Exchange Online - Hybrid.

Dynamische Gruppen und ADSync

Exchange OnPremises nutzt schon seit der Version Exchange 2000 das Active Directory als Verzeichnisdienst. Alle Exchange Empfänger sind dort als AD-Objekt vorhanden, Postfächer sind an AD-Benutzern hinterlegt und Mailverteiler als Verteiler- oder Sicherheitsgruppen mit den Mitgliedern gespeichert. Exchange ist dabei so smart und löst Gruppen auch Rekursiv auf. Details hierzu gibt es auch auf Abfragebasierte Verteiler - Querybased distribution Groups. Diese Gruppen haben aber durchaus Einschränkungen, denn es sind aus Sicht des Active Directory keine Gruppen, sondern besondere Objekte die nur von Exchange beim Mailrouting aufgelöst wird. Sie haben keine SID und keine Mitglieder und kann daher auch nicht für Berechtigungen verwendet werden.

Damit hat aber auch ADSync ein Problem, denn er kann die Gruppe gar nicht erst finden. Selbst wenn ADSync das Objekt lesen und in Entra ID anlegen würde, könnte er keine Mitglieder synchronisieren. Der LDAP-Query im lokalen AD kann auch nicht einfach so ins Entra ID übernommen werden. Das bedeutet letztlich:

Exchange OnPremises Dynamische Verteiler sind in Exchange Online nicht sichtbar.
Exchange Online Dynamische Verteiler sind in Exchange OnPremises nicht sichtbar

Das ist aber nicht die einzige Einschränkung, denn Exchange OnPremises findet sich eine weitere Fußangel, die nicht sofort auffällt. Wenn Sie eine solche Gruppen anlegen, müssen Sie den Filter mit hinterlegen und dazu gehört auch die Information, welche Empfänger enthalten sein sollen:


Quelle: https://learn.microsoft.com/en-us/powershell/module/exchange/set-dynamicdistributiongroup?view=exchange-ps#-includedrecipients

Oft fällt es erst auf den zweiten Blick auf, dass der Empfängertyp "RemoteMailbox" hier gar nicht sichtbar ist. Aber bekommt Sie dann auch keine Mails?

Remote-Mailbox und Dynamische DL

In meinem Testlabor habe ich jede Menge unterschiedliche Empfänger, wie eine kurze Abfrage ergibt:

[PS] C:\>Get-Recipient | group recipienttypedetails

Count Name                      Group
----- ----                      -----
    8 UserMailbox               {UCLABOR.DE/Accounts
    1 RemoteSharedMailbox       {UCLABOR.DE/Accounts
    1 DiscoveryMailbox          {UCLABOR.DE/Users/Di
    1 MailNonUniversalGroup     {UCLABOR.DE/Grouptes
    1 DynamicDistributionGroup  {UCLABOR.DE/Users/Dy
    3 RemoteUserMailbox         {UCLABOR.DE/Accounts
    1 MailUniversalSecurityG... {UCLABOR.DE/Accounts
    1 MailUniversalDistribut... {UCLABOR.DE/Users/fc
    4 MailUser                  {UCLABOR.DE/Accounts
    1 LinkedMailbox             {UCLABOR.DE/Accounts
    3 RoomMailbox               {UCLABOR.DE/Users/Ra
    3 RemoteRoomMailbox         {UCLABOR.DE/Users/Ra
    1 SharedMailbox             {UCLABOR.DE/Accounts

Hier gibt es auch einige "Remote*"-Empfänger. Per PowerShell habe ich schnell eine einfache dynamische Verteilergruppe angelegt

New-DynamicDistributionGroup `
   -Name DynDL1 `
   -IncludedRecipients Allrecipients

Name   ManagedBy
----   ---------
DynDL1

Die Properties sind mit einem LDIFDE-Export schnell dokumentiert:

dn: CN=DynDL1,OU=Verteiler,OU=Accounts,DC=UCLABOR,DC=DE
changetype: add
objectClass: top
objectClass: msExchDynamicDistributionList
cn: DynDL1
distinguishedName: CN=DynDL1,OU=Verteiler,OU=Accounts,DC=UCLABOR,DC=DE
instanceType: 4
whenCreated: 20241203121846.0Z
whenChanged: 20241203123954.0Z
displayName: DynDL1
uSNCreated: 17116962
uSNChanged: 17117000
proxyAddresses: smtp:DynDL1@msxfaqlab.mail.onmicrosoft.com
proxyAddresses: SMTP:DynDL1@UCLABOR.DE
name: DynDL1
objectGUID:: Qj3YKhMFcUuBR/yFJbOPmQ==
showInAddressBook: 
 CN=All Recipients(VLV),CN=All System Address Lists,CN=Address Lists Container,
 CN=First Organization,CN=Microsoft Exchange,CN=Services,CN=Configuration,DC=UC
 LABOR,DC=DE
showInAddressBook: 
 CN=Default Global Address List,CN=All Global Address Lists,CN=Address Lists Co
 ntainer,CN=First Organization,CN=Microsoft Exchange,CN=Services,CN=Configurati
 on,DC=UCLABOR,DC=DE
legacyExchangeDN: 
 /o=First Organization/ou=Exchange Administrative Group (FYDIBOHF23SPDLT)/cn=Re
 cipients/cn=3938594afdd94e049ea34bdb51803397-DynDL
objectCategory: 
 CN=ms-Exch-Dynamic-Distribution-List,CN=Schema,CN=Configuration,DC=UCLABOR,DC=
 DE
mail: DynDL1@UCLABOR.DE
msExchTransportRecipientSettingsFlags: 0
mailNickname: DynDL1
reportToOriginator: TRUE
msExchRecipientDisplayType: 3
msExchRequireAuthToSendTo: TRUE
msExchBypassAudit: FALSE
msExchPoliciesIncluded: dcc1acf1-8090-4647-ba80-34bca7bab308
msExchPoliciesIncluded: {26491cfc-9e50-4857-861b-0cb8df22b5d7}
msExchVersion: 44220983382016
msExchModerationFlags: 6
msExchMailboxAuditLogAgeLimit: 7776000
msExchMailboxAuditEnable: FALSE
msExchDynamicDLFilter: 
 (&(mailNickname=*)(!(name=SystemMailbox{*))(!(name=CAS_{*))(!(msExchRecipientT
 ypeDetails=16777216))(!(msExchRecipientTypeDetails=536870912))(!(msExchRecipie
 ntTypeDetails=68719476736))(!(msExchRecipientTypeDetails=8388608))(!(msExchRec
 ipientTypeDetails=4398046511104))(!(msExchRecipientTypeDetails=70368744177664)
 )(!(msExchRecipientTypeDetails=140737488355328)))
msExchMailboxFolderSet: 0
msExchRecipientSoftDeletedStatus: 0
internetEncoding: 0
msExchUserAccountControl: 0
msExchQueryFilterMetadata: 
 Microsoft.Exchange12.8f91d340bc0c47e4b4058a479602f94c:RecipientFilterType=2
msExchQueryFilterMetadata: 
 Microsoft.Exchange12.8f91d340bc0c47e4b4058a479602f94c:IncludedRecipients=-1
msExchAddressBookFlags: 1
msExchGroupMemberCount: 9
msExchGroupExternalMemberCount: 1
msExchQueryFilter: 
 ((Alias -ne $null) -and (-not(Name -like 'SystemMailbox{*')) -and (-not(Name -
 like 'CAS_{*')) -and (-not(RecipientTypeDetailsValue -eq 'MailboxPlan')) -and 
 (-not(RecipientTypeDetailsValue -eq 'DiscoveryMailbox')) -and (-not(RecipientT
 ypeDetailsValue -eq 'PublicFolderMailbox')) -and (-not(RecipientTypeDetailsVal
 ue -eq 'ArbitrationMailbox')) -and (-not(RecipientTypeDetailsValue -eq 'AuditL
 ogMailbox')) -and (-not(RecipientTypeDetailsValue -eq 'AuxAuditLogMailbox')) -
 and (-not(RecipientTypeDetailsValue -eq 'SupervisoryReviewPolicyMailbox')))
msExchDynamicDLBaseDN: CN=Users,DC=UCLABOR,DC=DE
msExchProvisioningFlags: 0

Sie sehen hier einmal den LDAP-Query im Feld "msExchDynamicDLFilter" und passend dazu die Exchange Filtersyntax in "msExchQueryFilter". Exchange 2019 schließt einige Empfänger anhand des "msExchRecipientTypeDetails" aus. Die RemoteMailbox ist hier aber nicht explizit ausgeschlossen. Ich kann sie nur per PowerShell nicht einschließen.

Der nächste Schritt war dann eine Testmail an diesen Verteiler und das Messagetracking hat den Ablauf auf dem lokalen Exchange Server protokolliert:

[PS] C:\>Get-MessageTrackingLog -MessageSubject DynDL1C

Timestamp              EventId          Source        Sender   Recipien Message
                                                               ts       Subject
---------              -------          ------        ------   -------- -------
03.12.2024 14:17:03    RECEIVE          STOREDRIVER   Admin... {DynD... DynDL1C
03.12.2024 14:17:09    SUBMIT           STOREDRIVER   Admin... {DynD... DynDL1C
03.12.2024 14:17:09    HAREDIRECTFAIL   SMTP          Admin... {DynD... DynDL1C
03.12.2024 14:17:09    RECEIVE          SMTP          Admin... {DynD... DynDL1C
03.12.2024 14:17:09    EXPAND           ROUTING       Admin... {Admi... DynDL1C
03.12.2024 14:17:09    RESOLVE          ROUTING       Admin... {t2tu... DynDL1C
03.12.2024 14:17:09    AGENTINFO        AGENT         Admin... {DynD... DynDL1C
03.12.2024 14:17:09    TRANSFER         ROUTING       Admin... {t2tu... DynDL1C
03.12.2024 14:17:09    TRANSFER         ROUTING       Admin... {Admi... DynDL1C
03.12.2024 14:17:09    DROP             ROUTING       Admin... {DynD... DynDL1C
03.12.2024 14:17:09    TRANSFER         ROUTING       Admin... {t2tu... DynDL1C
03.12.2024 14:17:09    SEND             SMTP          Admin... {delt... DynDL1C
03.12.2024 14:17:09    SEND             SMTP          Admin... {Admi... DynDL1C
03.12.2024 14:17:09    DELIVER          STOREDRIVER   Admin... {delt... DynDL1C
03.12.2024 14:17:09    DELIVER          STOREDRIVER   Admin... {Admi... DynDL1C

Hier sind die Zeilen mit der EventID="EXPAND" interessant, die ich gezielt noch einmal abgefragt habe:

[PS] C:\>Get-MessageTrackingLog -MessageSubject DynDL1C -EventId expand

Timestamp              EventId          Source        Sender   Recipien Message
                                                               ts       Subject
---------              -------          ------        ------   -------- -------
03.12.2024 14:17:09    EXPAND           ROUTING       Admin... {Admi... DynDL1C

[PS] C:\>Get-MessageTrackingLog -MessageSubject DynDL1C -EventId expand |fl


RunspaceId              : 2419b4e9-b473-4374-9e3c-fae47c914ff0
Timestamp               : 03.12.2024 14:17:09
ClientIp                :
ClientHostname          :
ServerIp                :
ServerHostname          : EX01
SourceContext           : DC01.UCLABOR.DE
ConnectorId             :
Source                  : ROUTING
EventId                 : EXPAND
InternalMessageId       : 250246269501445
MessageId               : <7778d49670034df38f80a9087c32aee2@uclabor.de>
NetworkMessageId        : daf22218-bd61-4606-d44d-08dd139cc73a
Recipients              : {Administrator@uclabor.de, t2tuser1@uclabor.de, deltest@uclabor.de}
RecipientStatus         : {250 2.1.5 RESOLVER.GRP.Expanded; distribution list expanded}
TotalBytes              : 7089
RecipientCount          : 3
RelatedRecipientAddress : DynDL1@UCLABOR.DE
MessageSubject          : DynDL1C
Sender                  : Administrator@uclabor.de
ReturnPath              : Administrator@uclabor.de
Directionality          : Originating
EventData               : {[DeliveryPriority, Normal], [AccountForest, UCLABOR.DE]}
TransportTrafficType    : Email
SchemaVersion           : 15.01.2507.043

Die aufgeteilte Empfängerliste enthält keine RemoteMailbox. Allerdings habe ich in meinem Exchange Lab auch weitere andere lokale Empfänger, die diese Testmails auch nicht bekommen haben. Das macht mich schon etwas stutzig.

Den Fall muss ich später noch einmal nachstellen, warum Exchange 2019 hier nicht alle Empfänger eingebunden hat.

Microsoft beschreit auch noch den Fall, wenn ein Exchange OnlineUser so eine Mailadresse "blind" anschreibt und diese über den Hybrid-Connector auf dem OnPremises System ankommt. Normalerweise sind solche Verteiler nur für "Authentifizierte Mailboxen" als Absender erreichbar. Exchange Online User haben aber keine lokale Mailbox.

Dynamische DL in Exchange Online

Die am Anfang neu angelegte dynamische Verteilerliste wurde von ADSync wie erwartet ignoriert, da es jeder User, Gruppe noch Kontakt ist sondern eine "msExchDynamicDistributionList". Damit weiß auch Exchange Online nichts davon und damit ist das globale Adressbuch nicht mehr synchron. Es hindert sie aber auch niemand daran, in Exchange Online ebenfalls eine dynamische Gruppe anzulegen.

Der Prozess ist gut dokumentiert und kann einfach über das Exchange Online Admin Center ausgeführt werden.

Aber auch diese Empfänger sind dann nur in Exchange Online sichtbar. Eine Testmail an die Gruppe hat auch wieder nur die Online-Empfänger erreicht aber keine User, deren Postfach "OnPremises" liegt.

Problem und Lösungen

Fassen wir noch einmal zusammen.

  • Dynamische Verteiler erlauben eine automatische Auflösung der Mitglieder über eine LDAP-Abfrage
    Das macht sie ideal für Mailverteiler basierend auf AD-Feldern wie "Department", "Location" etc.
  • Dynamische Verteiler werden nicht durch ADSync abgeglichen
    Damit müssen Sie diese von Hand auf beiden Seiten pflegen
  • "All Recipients" enthält keine Postfächer der anderen Exchange Umgebung
    Damit sind die Gruppen eigentlich disqualifiziert.
  • Member sind nur bedingt nachvollziehbar
    Sie können weder als Administrator noch als Anwender einfach erkennen, wer nun tatsächlich zu der Gruppe gezählt wird und damit die Mails bekommt.

Ich rate mittlerweile von solchen von Exchange OnPremises oder EntraID gepflegten dynamischen Gruppen ab.

Stattdessen setze ich viel lieber reguläre Verteilergruppen oder Sicherheitsgruppen ein, die ich entweder im lokalen AD manuell oder automatisch pflege und durch Exchange Online replizieren lasse oder ich lege die Gruppen in Exchange Online an und bediene mich der Funktion Group Writeback CloudConnect, um die Cloud-Gruppen auch im lokalen AD anlegen und verwalten zu lassen.

Hinweis: Group Writeback von Cloud Sync verhindert nicht dass Sie lokal die Gruppen verändern. Mitgliedschaften werden aber immer wieder überschrieben.

Eine Sicherheitsgruppe ist im lokalen AD oder auch in Exchange Online schnell per Admin Center oder Powershell angelegt. Offen bleibt nun noch die Frage, wer denn die Mitglieder verwaltet. Eine manuelle Verwaltung von Hand ist möglich aber unbequem. Die Frage ist nun eher, wie Sie die sonstigen Empfänger von Exchange heute verwalten. Legen Sie Benutzer und Postfach jedes Mal manuell an oder haben Sie schon ein kleines Skript dafür oder sogar ein vollwertiges Provisioning-System. Wenn Sie die Stammdaten z.B. schon aus der Personalabteilung erhalten und automatisiert die Benutzer verwalten. dann ist eine Erweiterung dieser Logik zu Verwaltung der Mitglieder dieser Pseudo-dynamischen Gruppen der wahrscheinliche Weg. Bei dem Prozess wir ja erkannt, wann sich bei einem Benutzer z.B. die Abteilung, die OU o.ä., ändert und sie können quasi sofort die Gruppenmitgliedschaften aktualisieren. Es wird aber dann noch noch einige Minuten dauern, bis alle DCs die Daten repliziert, Exchange im Cache aktualisiert und ADSync die Änderungen in den Tenant übertragen hat

Eine andere Option wäre natürlich die manuelle Anlage eines Kontakte auf der jeweils anderen Seite, damit Exchange einen Empfänger sieht und eine Mail an diesen Empfänger einmal über den Hybrid-Connect an die Plattform geht, die die dynamische Verteilergruppe hat und dann die Mail wieder aufteilt. Ich habe sogar ein Skript dazu gefunden. Sinnvoll finde ich das aber nicht.

Echte Gruppen mit automatisierten Mitgliedern

Sie können aber auch immer ein PowerShell-Script automatisiert starten, welches ihre Gruppen aktualisiert. Der Aufwand dafür ist minimal und habe ich auf Querybased Security Groups schon lange beschrieben. Sie können dies natürlich auch über die AD-PowerShell oder Exchange PowerShell durchführen. Zuerst ein Code-Beispiel für die AD-PowerShell. Ich sammle mit die gewünschten Objekte per GET-ADObject. Natürlich können Sie auch Get-ADUser und andere Filter-Kriterien nehmen. In dem Beispiel nutze ich dann die SID als Identity, um eine Liste der Mitglieder aufzubauen und dann als Mitglied der Gruppe zu setzen.

# AD Gruppen per LDAP setzen	

# Liste der Mitglieder aufbauen
[string[]]$sids= @()
$sids+= Get-ADUser -LDAPfilter "(mail=*)" -Properties @('SID') | ForEach-Object { '<SID=' + $_.SID + '>'}

# Mitgliedschaften aktualisieren
Set-ADGroup -Identity AllMailUser -Replace @{Member=$sids}

Das Feld "Member" wird dabei ersetzt. Das Active Directory ist alleine smart genug, nur dann die Änderungen zu schreiben, wenn es auch etwas zu Ändern gab.

Das Beispiel funktioniert so nur mit Mitgliedern, die eine SID haben, also keine AD-Kontakte oder Verteilergruppen und ohne weitere Ergänzungen auch nur in einer Domain und nicht dem gesamten Forest.

Wenn es sich aber sowieso um Exchange Objekte handelt, dann ist vielleicht die Exchange PowerShell eine einfache alternative, da diese alle Exchange Empfänger, d.h. auch Kontakte und Verteiler berücksichtigt und auch den kompletten Forest bedienen kann

Sie holen sich über eine normale Abfrage mit "Get-Recipient" und entsprechenden Filtern die Liste der gewünschten Empfänger und schreiben diese mit "Update-Distributiongroup" einfach als Member.

Set-ADServerSettings - ViewEntireForest:$true
# Mitglieder aus Sales aktualisieren
Update-DistributionGroupMember `
   -Identity Vertrieb `
   -Members (Get-Recipient -Filter "Department -eq 'Vertrieb'").distinguishedname -Resultsize unlimited`
   -Confirm:$false
# Mitglieder aus der OU aus Vertrieb als Mitglieder aktualisieren
Update-DistributionGroupMember `
   -Identity Vertrieb `
   -Members (Get-Recipient -OrganizationalUnit "UCLABOR.DE/Accounts/Vertrieb").distinguishedname `
   -Confirm:$false

Das ist wirklich nicht schwer und kann per "geplanten Task" auf dem Exchange Server einfach regelmäßig ausgeführt werden. Es könnte sein, dass das ausführende Dienstkonto kein Manager ist und keine Exchange RBAC-Rollen hat. Wenn es aber die erforderlichen AD-Rechte hat, dann können sie mit dem Schalter "-BypassSecurityGroupManagerCheck" die Manager-Prüfung abschalten.

Das funktioniert so natürlich auch in Exchange Online mittels Exchange PowerShell oder Microsoft Graph. Hier wäre dann zu prüfen, ob sie vielleicht eine App-Registration für Exchange Online nutzen. Siehe dazu auch die Seite EXO PowerShell Automation. Das wären dann aber Gruppen in der Cloud, die Sie dann vielleicht mit Group Writeback erst wieder ins lokale AD überführen müssen.

Weitere Links