[TR] On-Prem Exchange Server Ortamında Distribution Group Üyelerini CSV Olarak Listelemek

[TR] On-Prem Exchange Server Ortamında Distribution Group Üyelerini CSV Olarak Listelemek

Exchange Server yöneten sistem yöneticilerinin en sık ihtiyaç duyduğu raporlardan biri, ortamda bulunan Distribution Group yapılarını ve bu grupların üyelerini detaylı şekilde listelemektir. Özellikle denetim, yetki kontrolü, migration hazırlığı, mail akış analizi veya kullanıcı/grup temizliği gibi çalışmalarda hangi dağıtım grubunun hangi üyelerden oluştuğunu bilmek oldukça önemlidir.

On-Prem Exchange Server ortamında bu bilgiye Exchange Admin Center üzerinden tek tek bakmak mümkün olsa da, çok sayıda grup bulunan yapılarda bu yöntem pratik değildir. Bu nedenle en sağlıklı ve hızlı yöntem, Exchange Management Shell üzerinden PowerShell script çalıştırarak tüm grupları ve üyelerini CSV formatında dışa aktarmaktır.

Aşağıdaki script test edilmiş olup Distribution Group üyelerini doğru şekilde listeleyerek Excel ile açılabilir bir CSV dosyası üretmektedir.

Script Ne İşe Yarar?

Bu PowerShell scripti, Exchange Server ortamındaki tüm Distribution Group nesnelerini alır ve her grubun üyelerini tek tek kontrol eder.

Script sonucunda aşağıdaki bilgiler CSV dosyasına aktarılır:

AlanAçıklama
GroupNameDistribution Group görünen adı
GroupAliasGrubun alias bilgisi
GroupPrimarySMTPGrubun ana SMTP adresi
GroupTypeGrubun tipi
MemberNameGrup üyesinin görünen adı
MemberAliasGrup üyesinin alias bilgisi
MemberSMTPGrup üyesinin SMTP adresi
MemberTypeÜyenin alıcı tipi

Bu sayede hem grup bilgileri hem de grup üyeleri aynı dosya üzerinde kolayca analiz edilebilir.

Kullanılacak PowerShell Scripti

Aşağıdaki scripti Exchange Management Shell üzerinde çalıştırmanız yeterlidir:

$Out = "C:\Temp\Exchange_Distribution_Groups_Members.csv"

$Groups = Get-DistributionGroup -ResultSize Unlimited

$Result = foreach ($Group in $Groups) {
$Members = Get-DistributionGroupMember -Identity $Group.Identity -ResultSize Unlimited -ErrorAction SilentlyContinue

if ($Members) {
foreach ($Member in $Members) {
[PSCustomObject]@{
GroupName = $Group.DisplayName
GroupAlias = $Group.Alias
GroupPrimarySMTP = $Group.PrimarySmtpAddress
GroupType = $Group.GroupType
MemberName = $Member.DisplayName
MemberAlias = $Member.Alias
MemberSMTP = $Member.PrimarySmtpAddress
MemberType = $Member.RecipientType
}
}
}
else {
[PSCustomObject]@{
GroupName = $Group.DisplayName
GroupAlias = $Group.Alias
GroupPrimarySMTP = $Group.PrimarySmtpAddress
GroupType = $Group.GroupType
MemberName = ""
MemberAlias = ""
MemberSMTP = ""
MemberType = ""
}
}
}

$Result | Export-Csv $Out -NoTypeInformation -Encoding UTF8

Write-Host "Export tamamlandı: $Out"

Script Nasıl Çalışır?

Scriptin ilk satırında çıktı dosyasının nereye kaydedileceği belirlenir:

$Out = "C:\Temp\Exchange_Distribution_Groups_Members.csv"

Bu örnekte CSV dosyası C:\Temp dizini altına oluşturulur. Bu nedenle scripti çalıştırmadan önce ilgili klasörün var olduğundan emin olunmalıdır. Eğer C:\Temp klasörü yoksa export işlemi hata verebilir.

Daha sonra Exchange ortamındaki tüm Distribution Group nesneleri alınır:

$Groups = Get-DistributionGroup -ResultSize Unlimited

Burada kullanılan -ResultSize Unlimited parametresi oldukça önemlidir. Exchange bazı komutlarda varsayılan olarak sınırlı sayıda sonuç döndürebilir. Bu parametre sayesinde ortamda kaç adet Distribution Group varsa tamamı listelenir.

Sonraki bölümde script her bir grubu tek tek işler:

$Result = foreach ($Group in $Groups) {

Her grup için üyeler alınır:

$Members = Get-DistributionGroupMember -Identity $Group.Identity -ResultSize Unlimited -ErrorAction SilentlyContinue

Bu satırda ilgili grubun üyeleri sorgulanır. -ErrorAction SilentlyContinue parametresi ise bazı gruplarda erişim, çözümleme veya özel durum kaynaklı hata oluşması halinde scriptin tamamen durmasını engeller.

Üyesi Olan Grupların İşlenmesi

Eğer bir grubun üyesi varsa, script her üyeyi ayrı bir satır olarak CSV dosyasına yazar:

if ($Members) {
foreach ($Member in $Members) {

Örneğin bir Distribution Group içinde 20 kullanıcı varsa, CSV çıktısında bu grup için 20 ayrı satır oluşur. Her satırda grup bilgisi tekrar eder, fakat üye bilgisi değişir.

Bu yöntem raporlama açısından oldukça kullanışlıdır. Çünkü Excel üzerinde filtreleme yaparak belirli bir grubun tüm üyelerini veya belirli bir kullanıcının hangi gruplarda yer aldığını kolayca görebilirsiniz.

Üyesi Olmayan Grupların İşlenmesi

Scriptin güzel taraflarından biri de boş grupları atlamamasıdır.

Eğer bir Distribution Group içinde hiç üye yoksa, script yine de o grubu CSV dosyasına ekler:

else {
[PSCustomObject]@{
GroupName = $Group.DisplayName
GroupAlias = $Group.Alias
GroupPrimarySMTP = $Group.PrimarySmtpAddress
GroupType = $Group.GroupType
MemberName = ""
MemberAlias = ""
MemberSMTP = ""
MemberType = ""
}
}

Bu sayede ortamda kullanılmayan, boş kalmış veya temizlenmesi gereken Distribution Group nesneleri de kolayca tespit edilebilir.

CSV Dosyasının Oluşturulması

Script sonunda elde edilen sonuçlar CSV dosyasına aktarılır:

$Result | Export-Csv $Out -NoTypeInformation -Encoding UTF8

Burada kullanılan -NoTypeInformation parametresi CSV dosyasının başına PowerShell nesne tipi bilgisinin yazılmasını engeller. Böylece dosya Excel üzerinde daha temiz açılır.

-Encoding UTF8 parametresi ise Türkçe karakterlerin düzgün görüntülenmesi için önemlidir. Özellikle grup veya kullanıcı adlarında Türkçe karakterler bulunuyorsa bu parametre kullanılmalıdır.

Son satırda ise işlemin tamamlandığı kullanıcıya bildirilir:

Write-Host "Export tamamlandı: $Out"

Çıktı Dosyası Nasıl Görünür?

Script çalıştırıldıktan sonra aşağıdaki konumda CSV dosyası oluşur:

C:\Temp\Exchange_Distribution_Groups_Members.csv

Dosya Excel ile açıldığında aşağıdaki başlıkları içeren bir tablo görüntülenir:

GroupName, GroupAlias, GroupPrimarySMTP, GroupType, MemberName, MemberAlias, MemberSMTP, MemberType

Bu tablo üzerinden şu analizler kolayca yapılabilir:

  • Hangi Distribution Group içinde hangi kullanıcılar var?
  • Bir kullanıcının üye olduğu gruplar hangileri?
  • Boş Distribution Group var mı?
  • Gruplarda kullanıcı dışında başka grup üyeliği var mı?
  • Nested group kullanımı mevcut mu?
  • Mail-enabled security group veya farklı recipient tipleri bulunuyor mu?
  • Migration öncesi grup üyelikleri sağlıklı mı?

Scripti Çalıştırmadan Önce Dikkat Edilmesi Gerekenler

Scriptin doğru şekilde çalışması için bazı temel noktalara dikkat edilmelidir.

Öncelikle script mutlaka Exchange Management Shell üzerinde çalıştırılmalıdır. Normal PowerShell penceresinde Exchange modülleri yüklü değilse Get-DistributionGroup veya Get-DistributionGroupMember komutları tanınmayabilir.

Ayrıca scripti çalıştıran hesabın Exchange üzerinde gerekli okuma yetkilerine sahip olması gerekir. Genellikle aşağıdaki roller bu işlem için yeterlidir:

Recipient Management
View-Only Organization Management
Organization Management

Rapor alınacak ortam büyükse scriptin tamamlanması zaman alabilir. Özellikle binlerce Distribution Group veya çok fazla üyeye sahip gruplar varsa işlem süresi uzayabilir.

C:\Temp Klasörü Yoksa Ne Yapılmalı?

Scriptte çıktı dizini olarak C:\Temp kullanıldığı için bu klasörün önceden oluşturulmuş olması gerekir.

Aşağıdaki komutla klasörü oluşturabilirsiniz:

New-Item -Path "C:\Temp" -ItemType Directory -Force

Dilerseniz scriptin başına bu satırı ekleyerek klasörün otomatik oluşturulmasını sağlayabilirsiniz:

$OutFolder = "C:\Temp"
$Out = "$OutFolder\Exchange_Distribution_Groups_Members.csv"

if (!(Test-Path $OutFolder)) {
New-Item -Path $OutFolder -ItemType Directory -Force | Out-Null
}

Bu düzenleme sayesinde C:\Temp klasörü yoksa otomatik olarak oluşturulur.

Geliştirilmiş Script Örneği

Aşağıdaki sürümde çıktı klasörünün varlığı kontrol edilir ve yoksa otomatik oluşturulur:

$OutFolder = "C:\Temp"
$Out = "$OutFolder\Exchange_Distribution_Groups_Members.csv"

if (!(Test-Path $OutFolder)) {
New-Item -Path $OutFolder -ItemType Directory -Force | Out-Null
}

$Groups = Get-DistributionGroup -ResultSize Unlimited

$Result = foreach ($Group in $Groups) {
$Members = Get-DistributionGroupMember -Identity $Group.Identity -ResultSize Unlimited -ErrorAction SilentlyContinue

if ($Members) {
foreach ($Member in $Members) {
[PSCustomObject]@{
GroupName = $Group.DisplayName
GroupAlias = $Group.Alias
GroupPrimarySMTP = $Group.PrimarySmtpAddress
GroupType = $Group.GroupType
MemberName = $Member.DisplayName
MemberAlias = $Member.Alias
MemberSMTP = $Member.PrimarySmtpAddress
MemberType = $Member.RecipientType
}
}
}
else {
[PSCustomObject]@{
GroupName = $Group.DisplayName
GroupAlias = $Group.Alias
GroupPrimarySMTP = $Group.PrimarySmtpAddress
GroupType = $Group.GroupType
MemberName = ""
MemberAlias = ""
MemberSMTP = ""
MemberType = ""
}
}
}

$Result | Export-Csv $Out -NoTypeInformation -Encoding UTF8

Write-Host "Export tamamlandı: $Out" -ForegroundColor Green

Nested Group Durumu

Bazı Exchange ortamlarında bir Distribution Group içine başka bir Distribution Group veya Mail-Enabled Security Group eklenmiş olabilir. Bu yapıya genellikle nested group membership denir.

Bu script, varsayılan haliyle nested group içindeki kullanıcıları recursive olarak açmaz. Yani bir grubun içinde başka bir grup varsa, o iç grup üye olarak listelenir. İç grubun kendi üyeleri ayrıca açılıp ana grubun altında gösterilmez.

Bu davranış çoğu raporlama senaryosu için faydalıdır. Çünkü hangi grubun hangi gruba üye olduğu net şekilde görülebilir. Ancak tüm üyeleri recursive olarak görmek istenirse scriptin ayrıca genişletilmesi gerekir.

Dynamic Distribution Group İçin Durum Farklıdır

Bu script klasik Distribution Group üyeliklerini listelemek için uygundur. Ancak Dynamic Distribution Group yapıları farklı çalışır.

Dynamic Distribution Group üyeleri manuel olarak eklenmez. Üyelikler belirli filtrelere göre dinamik olarak hesaplanır. Bu nedenle Dynamic Distribution Group üyelerini listelemek için farklı komutlar ve recipient filter mantığı kullanılmalıdır.

Bu yüzden bu scripti kullanırken kapsamın klasik Distribution Group üyelikleri olduğunu bilmek önemlidir.

Hangi Senaryolarda Kullanılabilir?

Bu script aşağıdaki çalışmalar için oldukça faydalıdır:

  • Exchange migration öncesi grup üyeliklerinin çıkarılması
  • Active Directory ve Exchange temizlik çalışmaları
  • Denetim ve raporlama süreçleri
  • Yetki ve erişim kontrolü
  • Eski veya boş Distribution Group tespiti
  • Kullanıcı ayrılışlarında grup üyeliklerinin kontrolü
  • Mail akışında sorun yaşanan grupların analiz edilmesi
  • Disaster recovery öncesi yapı dokümantasyonu
  • Kurumsal envanter çalışmaları

Özellikle Exchange Server’dan Microsoft 365 ortamına geçiş yapılacaksa, Distribution Group üyeliklerinin önceden dışa aktarılması önemli bir hazırlık adımıdır.

Olası Hatalar ve Çözüm Önerileri

1. Get-DistributionGroup komutu tanınmıyor

Bu hata genellikle scriptin normal PowerShell üzerinde çalıştırıldığını gösterir.

Çözüm olarak scripti Exchange Management Shell üzerinden çalıştırın.

2. CSV dosyası oluşmuyor

Bunun en yaygın nedeni C:\Temp klasörünün mevcut olmamasıdır.

Aşağıdaki komutla klasörü oluşturabilirsiniz:

New-Item -Path "C:\Temp" -ItemType Directory -Force

3. Bazı grupların üyeleri boş geliyor

Bu durum birkaç farklı nedenden kaynaklanabilir:

  • Grup gerçekten boş olabilir.
  • Yetki yetersizliği olabilir.
  • Grup dynamic distribution group olabilir.
  • Grup üyeliği nested yapı üzerinden sağlanıyor olabilir.
  • İlgili nesne çözümlenemiyor olabilir.

4. Türkçe karakterler bozuk görünüyor

Scriptte -Encoding UTF8 parametresi kullanıldığı için çoğu durumda Türkçe karakterler düzgün görüntülenir. Ancak Excel bölgesel ayarları veya CSV açma yöntemi nedeniyle karakter problemi yaşanabilir.

Bu durumda CSV dosyasını Excel üzerinden Data > From Text/CSV yöntemiyle içeri aktararak UTF-8 formatında açmak daha sağlıklı olur.

On-Prem Exchange Server ortamlarında Distribution Group üyeliklerinin düzenli olarak raporlanması, hem operasyonel yönetim hem de denetim süreçleri açısından oldukça önemlidir.

Paylaşılan PowerShell scripti sayesinde tüm Distribution Group nesneleri ve üyeleri kısa sürede CSV formatında dışa aktarılabilir. Bu çıktı Excel üzerinde kolayca filtrelenebilir, analiz edilebilir ve gerektiğinde dokümantasyon amacıyla saklanabilir.

Özellikle büyük Exchange ortamlarında manuel kontrol yerine bu tip scriptlerle raporlama yapmak hem zaman kazandırır hem de hata riskini azaltır. Migration, temizlik, denetim veya güvenlik çalışmaları öncesinde bu raporun alınması oldukça faydalı olacaktır.