Bu makalemde Microsoft Exchange Server Transport Rules (ör. “disclaimer”, “external mail uyarısı”) uygulandıktan sonra bazı iletilerde Türkçe karakter bozulması (ğ, Ğ, ş, Ş, ç, Ç, ı, İ, ö, Ö, ü, Ü) yaşanması problemine kök nedeni, güvenli çözümü, doğrulaması, rollback ve otomasyon adımlarıyla değineceğiz

Senaryonuzla birebir uyumludur. kural eklendikten sonra içerik UTF-8 iken bazı durumlarda (özellikle multipart/mixed davetler, HTML içerikler) iletinin yeniden kodlanması sırasında ISO-8859-1’e düşüş olur ve karakterler bozulur.

Transport Rule iletinin gövdesini/başlıklarını değiştirir (ör. HTML disclaimer ekler). Bu değişiklik sırasında içerik dönüştürme (content conversion) motoru mesaj içindeki meta charset veya parça (part) bilgilerinden kodlamayı otomatik tespit etmeye çalışır. Bazı davet/duyuru/harici istemci üretimli iletilerde bu tespit yanlış/eksik yapılır veya varsayılan olarak ISO-8859-1’e düşer. Sonuç olarak mail yeniden kodlanırken Türkçe karakterler hatalı transliterate edilir ve bozulur. (Tipik işaretler: “ç”, “ÄŸ”, “ÅŸ” vb.)

Content-Type: multipart/mixed içinde farklı charset’ler yer alabilir kural uygulandıktan sonra gövde “sarmalanır (wrap)” ya da yeni bir bölüm oluşur ve charset çakışması yaşanır.

Exchange Server üzerinde Meta etiketinden kodlama algılamayı kapatıyoruz. Böylece Exchange’in içerik dönüştürme aşamasında meta charset’e göre otomatik karar vermesi yerine orijinal içerik kodlamasına sadık kalması sağlanıyor. Bu ayar Transport hizmetinin (MSExchangeTransport) kullandığı EdgeTransport.exe.config üzerinden yapılır.

Bu yaklaşım Transport Rules sonrası UTF-8 içeriğin ISO-8859-1’e düşmesini engelleyerek Türkçe karakterleri korur.

Not: Config dosyası bir XML’dir. Hatalı düzenleme Transport servisinin açılmamasına yol açabilir. Mümkünse bakım penceresinde uygulayın.

yedek almak için

$cfg = "C:\Program Files\Microsoft\Exchange Server\V15\Bin\EdgeTransport.exe.config"
Copy-Item $cfg "$cfg.bak-$(Get-Date -Format yyyyMMddHHmmss)"

Dosyayı yönetici olarak açınız ve kapanış etiketinin hemen üstüne şu satırı ekleyin:

<add key="DisableDetectEncodingFromMetaTag" value="true" />

Notlar

  • Çift tırnaklar düz olmalı: " (akıllı tırnak “ ” kullanmayın).
  • Anahtar appSettings bloğunun içinde olmalı. (Yanlış yere konursa etkisiz kalır ya da XML bozulur.)

işlem tamamlandıktan sonra transport servisini yeniden başlatınız.

Restart-Service MSExchangeTransport

Mailbox/Transport rolü olan tüm Exchange sunucularında (Edge varsa Edge’lerde de) aynı işlemi yapınız.

İşlemi Doğrulamak

  1. Test iletileri gönderin:
    • Salt metin, HTML, Teams/Calendar daveti (multipart), inline resimli e-postalar.
    • Gövdede bol Türkçe karakter bulundurun.
  2. İletiyi kuralın tetiklediğinden emin olun (disclaimer/uyarı görünsün).
  3. Alıcı tarafta ve “Message tracking/headers” içinde:
    • Content-Type satırında charset=utf-8 kalıyor mu?
    • Bozulma belirtileri (Ã, Å, Ä gibi) yok mu?
  4. Gerekirse “öncesi” ile “sonrası” örneklerini saklayın; MIME parçalarını (boundary, part charset’leri) kıyaslayın.

Rollback

Sorun/yan etki görürseniz:

İlgili satırı silin (veya value="false" yapın).

Transport Service’i yeniden başlatınız.

 Restart-Service MSExchangeTransport

Gerekirse config yedeğini geri yükleyiniz.

Copy-Item "$cfg.bak-<timestamp>" $cfg -Force Restart-Service MSExchangeTransport

Çok Sunuculu Ortamlar için;

Aşağıdaki powershell sciripti ile tüm Exchange sunucularında anahtar var mı/yok mu kontrol eder yoksa ekler XML’i güvenli şekilde kaydeder ve servisi kontrollü yeniden başlatır.

$servers = (Get-ExchangeServer | ? {$_.IsMailboxServer -or $_.IsEdgeServer}).Name
$relative = "\V15\Bin\EdgeTransport.exe.config"

foreach($s in $servers){
  $path = "\\$s\C$\Program Files\Microsoft\Exchange Server$relative"
  if(-not (Test-Path $path)){
    Write-Warning "Bulunamadı: $s -> $path"
    continue
  }

  Write-Host "Yedek alınıyor: $s"
  Copy-Item $path "$path.bak-$(Get-Date -Format yyyyMMddHHmmss)" -Force

  [xml]$xml = Get-Content $path
  $appSettings = $xml.configuration.appSettings
  if(-not $appSettings){ Write-Warning "$s: appSettings yok!"; continue }

  $keyNode = $appSettings.add | ? { $_.key -eq "DisableDetectEncodingFromMetaTag" }
  if($keyNode){
    $keyNode.value = "true"
    Write-Host "$s: mevcut anahtar güncellendi."
  } else {
    $newNode = $xml.CreateElement("add")
    $newNode.SetAttribute("key","DisableDetectEncodingFromMetaTag")
    $newNode.SetAttribute("value","true")
    $appSettings.AppendChild($newNode) | Out-Null
    Write-Host "$s: anahtar eklendi."
  }

  $xml.Save($path)

  Write-Host "$s: MSExchangeTransport yeniden başlatılıyor..."
  Invoke-Command -ComputerName $s -ScriptBlock { Restart-Service MSExchangeTransport -Force }
}