Exchange: разрешить любого получателя для коннектора отправки

Для отправки оповещений в виде email устройствами, системами мониторинга и прочими админскими штуками зачастую в Exchange создаётся специальный коннектор для отправки таких сообщений без аутентификации.
Конечно же, область действия такого коннектора административно ограничивается определёнными подсетями и адресами доверенных хостов.
Однако отправка почты на домены, не входящие в число доверенных в организации Exchange, в коннекторе по-умолчанию запрещена. Если нужно отправить оповещалку внешнему получателю – проблема.
В логе можно увидеть такое сообщение:

550 5.7.54 SMTP; Unable to relay recipient in non-accepted domain

Для того, чтобы разрешить отправку любому получателю через наш коннектор, необходимо выполнить команду, дающую соответствующие права анонимному юзеру:

Get-ReceiveConnector "MSK-MAIL2-01\Without Auth" | Add-ADPermission -User "NT AUTHORITY\ANONYMOUS LOGON" -ExtendedRights "Ms-Exch-SMTP-Accept-Any-Recipient"
Get-ReceiveConnector "MSK-MAIL2-01\Without Auth" | Get-ADPermission | sort user | where {$_.extendedrights -like "Ms-Exch-SMTP-Accept-Any-Recipient"} | ft User,ExtendedRights -auto

https://docs.microsoft.com/en-us/Exchange/mail-flow/connectors/receive-connectors?view=exchserver-2019#receive-connector-permission-groups

Чтение логов SMTP

Чтение логов протокола SMTP может доставлять немало головной боли, если не уметь его читать. Здесь я продублирую кусок документации с сайта Микрософт, в котором рассказано, какие поля содержатся в логах SMTP, которые ведут посылающие и принимающие коннекторы Exchange.

The protocol log stores each SMTP protocol event on a single line in the log. The information stored on each line is organized by fields, and these fields are separated by commas. The fields that are used in the protocol log are described in the following table.

Field nameDescription
date-timeUTC date-time of the protocol event. The UTC date-time is represented in the ISO 8601 date-time format: yyyy-mm-ddThh:mm:ss.fffZ, where yyyy = year, mm = month, dd = day, T indicates the beginning of the time component, hh = hour, mm = minute, ss = second, fff = fractions of a second, and Z signifies Zulu, which is another way to denote UTC.
connector-idDistinguished name (DN) of the connector that’s associated with the SMTP event.
session-idGUID value that’s unique for each SMTP session, but is the same for every event that’s associated with that SMTP session.
sequence-numberCounter that starts at 0 and is incremented for each event in the same SMTP session.
local-endpointLocal endpoint of an SMTP session. This consists of an IP address and TCP port number formatted as <IP address><port>.
remote-endpointRemote endpoint of an SMTP session. This consists of an IP address and TCP port number formatted as <IP address><port>.
eventSingle character that represents the protocol event. Valid values are:
+: Connect
-: Disconnect
>: Send
<: Receive
*: Information
dataText information associated with the SMTP event.
contextAdditional contextual information that may be associated with the SMTP event.

One SMTP conversation that represents sending or receiving a single email message generates multiple SMTP events. Each event is recorded on a separate line in the protocol log. An Exchange server has many SMTP conversations going on at any given time. This creates protocol log entries from different SMTP conversations that are mixed together. You can use the session-id and sequence-number fields to sort the protocol log entries by each individual SMTP conversation.

Случай 1:
Сервер не может доставить сообщение, ошибка 421 4.4.2 Connection dropped due to SocketError
Решение:
Смотрим лог. Фильтруем записи по session-id, последняя строка содержит с записи
>,DATA,
<,"354 Enter mail, end with ""."" on a line by itself.",
-,,Remote
Какой вывод можно сделать из этих строк? Сразу несколько.
1. Передача данных началась. Серверы успешно договорились о параметрах соединения, о получателях, все проверки антиспам пройдены и т.д.
2. Передача данных не завершилась. В случае успешного и корректного завершения приёма письма мы должны увидеть сообщение вида
<,"250 Mail OK queued as mx12,duCowABnt9OspNlfOs+tAA--.3497S2 1608098992",
которое говорит нам о том, что удалённый сервер принял к себе письмо.
3. Сессия была разорвана удалённым хостом. Об этом нам говорит символ “-” (минус), и подпись Remote. В штатном случае мы обычно видим -,,Local .
Причины? Обрыв связи из-за нестабильного канала связи (вполне может быть воспринят как разрыв удалённым сервером), таймаут из-за слишком медленной передачи письма (большой объём, медленный канал). Необходимо уменьшить размер письма.

Список всех ящиков и групп рассылки в csv

Скрипт для выгрузки всех ящиков и групп рассылки в csv:

$FileExport = "c:\ab_company.csv"
$dgs = Get-DistributionGroup
$mbx = Get-Mailbox
$CSVrows = @()
foreach ($m in $mbx) {
	$CSVrows += $m | Select DisplayName, PrimarySmtpAddress, HiddenFromAddressListsEnabled
}
foreach ($dg in $dgs) {
	$CSVrows += $dg | Select DisplayName, PrimarySmtpAddress, HiddenFromAddressListsEnabled
}
$CSVrows | Export-CSV -Path $FileExport -force -NoTypeInformation -Encoding "UTF8" -Delimiter ";"

Скрипт для выгрузки состава групп рассылки:

$FileExport = "c:\dgs.csv"
$dgs = Get-DistributionGroup
$mbx = Get-Mailbox
$CSVrows = @()
foreach ($dg in $dgs) {
	Write-Host $dg.Name -fore Green
	Get-DistributionGroupMember -Identity $dg.Identity | % {
		#Write-Host "`t"$_.DisplayName"`t"$_.PrimarySmtpAddress"`t"$_.RecipientType
		$CSVrow = "" | Select DistributionGroup,DG_email,Member_DisplayName,Member_PrimarySmtpAddress,Member_RecipientType
		$CSVrow.DistributionGroup = $dg.Name
		$CSVrow.DG_email = $dg.PrimarySmtpAddress
		$CSVrow.Member_DisplayName = $_.DisplayName
		$CSVrow.Member_PrimarySmtpAddress = $_.PrimarySmtpAddress
		$CSVrow.Member_RecipientType = $_.RecipientType
		$CSVrows += $CSVrow
	}
}
$CSVrows | Export-CSV -Path $FileExport -force -NoTypeInformation -Encoding "UTF8" -Delimiter ";"

Восстановление Exchange

Если полностью умер сервер и надо восстановить с чистой установки ОС:
https://docs.microsoft.com/ru-ru/Exchange/high-availability/disaster-recovery/recover-exchange-servers?view=exchserver-2019

Основная идея такая: не убивать учётку компьютера в домене, запускать установку Exchange со специальным ключом.

How to downgrade or change Exchange Server Edition

1. Run ADSI Edit tool: adsi.msc
2. Connect to
3. In connection settings Select a well known Naming Context – Configuration
4. Expand Configuration – Services – Microsoft Exchange – <Name of your Organization> – Administrative Groups – Exchange Administrative Group (FYDIBOHF23SPDLT) – Servers
5. Click Exchange server Properties
6. Clear msExchProductID attribute
7. Restart Microsoft Exchange Information Store service if server holds mailbox role
8. Enter New Product Key using Exchange Management Console or PowerShell

Set-ExchangeServer -Identity Server1 -ProductKey xxxxx-xxxxx-xxxxx-xxxxx-xxxxx

9. Restart Microsoft Exchange Information Store service

Здесь описано, как понизить лицензию на сервере с ролью Edge Transport:
https://okrylov.wordpress.com/2016/11/07/downgrade-exchange-server-edition/

Exchange: экспорт/иморт ящиков

Экспорт ящиков

$user="Vasya.Pupkin";New-MailboxExportRequest -Mailbox "$user@company.com" -FilePath "\\DUB-MAIL2-K\R$\MB_Export\$user.pst"
Get-MailboxExportRequest | Get-MailboxExportRequestStatistics | ft Name, Status, PercentComplete, OverallDuration, EstimatedTransferSize,BytesTransferred,BytesTransferredPerMinute,EstimatedTransferItemCount,ItemsTransferred
Get-MailboxExportRequest | where {$_.status -eq "Completed"} | Remove-MailboxExportRequest

Импорт ящиков:

$user="Vasya.Pupkin";New-MailboxImportRequest -Name "$user Import" -FilePath "\\DUB-MAIL2-01\T$\MB_Import\$user.pst" -Mailbox "$user@company.com"
Get-MailboxImportRequest | Get-MailboxImportRequestStatistics| ft Name, StatusDetail, PercentComplete, OverallDuration, EstimatedTransferSize, BytesTransferred, EstimatedTransferItemCount, ItemsTransferred
Get-MailboxImportRequest -Status Completed | Remove-MailboxImportRequest

Exchange: Создание почтовых ящиков

Создание пользователя в Active Directory

$OU='OU=Company1,OU=USERS,OU=ACCOUNTS,DC=DOMAIN,DC=LOCAL'
$u='Vasya.Pupkin'; $pwd='Xcee3Dj*i'; New-ADUser -GivenName $u.split(".")[0] -Surname $u.split(".")[1] -DisplayName ($u.split(".")[1] + " " + $u.split(".")[0]).trim() -Name ($u.split(".")[1] + " " + $u.split(".")[0] + " (Company1)").trim() -SamAccountName (($u[0..15] -join "")+'.cmp1') -UserPrincipalName ($u+"@company1.com") -Path $OU -AccountPassword(ConvertTo-SecureString $pwd -AsPlainText -force) -Enabled $true -ChangePasswordAtLogon $true

Активировать ящик:

$Database="Mail_DB_01"
$user="Vasya.Pupkin";
	$identity=$($user+"@company1.com")
	Enable-Mailbox -Identity $identity -Alias (($user[0..15] -join "")+'.cmp1') -Database $Database
	Get-Mailbox –Identity $identity | Set-Mailbox `
	-EmailAddressPolicyEnabled $false `
	-EmailAddresses "SMTP:$($user+"@company1.com")", `
	 "X500:/o=DOMAIN/ou=Exchange Administrative Group (FYDIBOHF23SPDLT)/cn=Recipients/cn=Pupkin Vasya (company1)f40";

Создать контакт в AD и Exchange:

New-MailContact -Name "Pupkin Vasya (GR)" -DisplayName "Pupkin Vasya" -FirstName "Vasya" -LastName "Pupkin" -ExternalEmailAddress "Vasya.Pupkin@domain.com" -Alias "Vasya.Pupkin.gr.contact" -OrganizationalUnit "OU=Contacts,OU=MAIL,OU=ACCOUNTS,DC=DOMAIN,DC=LOCAL"
$u = "Vasya.Pupkin"; New-MailContact -Name ($u.split(".")[1] + " " + $u.split(".")[0] + " (GR)").trim() -DisplayName ($u.split(".")[1] + " " + $u.split(".")[0]).trim() -FirstName $u.split(".")[0] -LastName $u.split(".")[1] -ExternalEmailAddress ($u+"@domain.com") -Alias ($u+".gr.contact") -OrganizationalUnit "OU=GR,OU=Mail_Contacts,OU=USERS,OU=ACCOUNTS,DC=DOMAIN,DC=LOCAL"; Set-MailContact -Identity ($u+".gr.contact") -HiddenFromAddressListsEnabled $true;