# Посмотреть, кто имеет доступ к ящику username
Get-MailboxPermission username | ft user,accessrights -AutoSize
# Посмотреть доступ для учётки к ящикам
get-mailbox | Get-MailboxPermission -User Username -ResultSize Unlimited | ft Identity,AccessRights -AutoSize
# Вывести список ящиков, в которые имеет доступ учетка
Get-Mailbox -ResultSize Unlimited | Get-MailboxPermission -User S-1-5-21-606747145-1343024091-1708537768-16143 | ft -wrap
# Удалить учетку с правами FullAccess изо всех ящиков
Get-Mailbox -ResultSize Unlimited | Remove-MailboxPermission -User S-1-5-21-606747145-1343024091-1708537768-16143 -AccessRights FullAccess -Confirm:$False
# Проверить ящик на ошибки (можно и базу), без исправления (-DetectOnly)
New-MailboxRepairRequest –Mailbox user7@domain28.lab –CorruptionType SearchFolder, AggregateCounts, ProvisionedFolder, FolderView -DetectOnly
# Проверить статус проверки ящика
Get-MailboxRepairRequest –Mailbox user7@domain28.lab
==== Фильтр csv-отчёта и выгрузка ящиков ====
$t = get-date -Format yyyy-MM
dir "$env:USERPROFILE\desktop\$t-*.csv" -OutVariable f
$f = import-csv $f -Delimiter ";" | where -Property "Рекомендован к отключению" -eq "рекомендован, аккаунт отключен" | select -ExpandProperty Команда
$fname = "$env:USERPROFILE\desktop\$t-filtered.txt"
# примерный результат работы фильтра
#New-MailboxExportRequest -Mailbox "userone@domain.ru" -FilePath "\\domain.ru\main\backups\filesarchive\PST\auto-export\userone20190521-1204.pst"
#New-MailboxExportRequest -Mailbox "usertwo@domain.ru" -FilePath "\\domain.ru\main\backups\filesarchive\PST\auto-export\usertwo20190521-1224.pst"
#New-MailboxExportRequest -Mailbox "userthree@domain.ru" -FilePath "\\domain.ru\main\backups\filesarchive\PST\auto-export\userthree20190521-1505.pst"
echo '
# Загрузить модуль Exchange
Import-Module "$env:ExchangeInstallPath\Bin\RemoteExchange.ps1"
Connect-ExchangeServer -auto'`n | Out-File $fname
$f | Out-File -Append $fname
echo '
# Вывести список экспортируемых ящиков
Get-MailboxExportRequest | select Mailbox,Status | fl
# Возобновить экспорт ящиков, закончившихся неудачей
Get-MailboxExportRequest -Status Failed | Resume-MailboxExportRequest
# Очистить очередь на экспорт, добавив информацию в файл
Get-MailboxExportRequest -Status Completed | %{$_| fl | out-file "\\minprom.gov.ru\main\backups\filesarchive\PST\auto-export\log.txt" -append; Disable-Mailbox $_.Mailbox -Confirm:$false; Remove-MailboxExportRequest -Identity $_ -Confirm:$false}' |
Out-File -Append $fname
Invoke-Item $fname
==== При сбое выгрузки ящика ====
# Отчёт по сбойному запросу выгрузки
Get-MailboxExportRequest -Status Failed |Get-MailboxExportRequestStatistics -IncludeReport |fl > c:\temp\usernameExport-report.txt
# Подкрутить параметры запроса
Get-MailboxExportRequest -Status Failed |Set-MailboxExportRequest -BadItemLimit 9999 -AcceptLargeDataLoss
# Продолжить запрос
Get-MailboxExportRequest -Status Failed |Resume-MailboxExportRequest
https://www.stellarinfo.com/article/new-mailboxexportrequest-failed.php
==== Запрет группы отправителей ====
# Сделать группу
New-DistributionGroup -Name senders.banned -OrganizationalUnit "domain.ru/Почта/Списки рассылок" -SamAccountName senders.banned -Type "Security"
# Скрыть из адресной книги
Set-DistributionGroup senders.banned -HiddenFromAddressListsEnabled $True
# Внести в список запрещённых отправителей ящика
Set-Mailbox i.petrov -RejectMessagesFromDLMembers (Get-DistributionGroup senders.banned)
Затем нужно добавить отправителей в группу.
В ящиках есть 3 параметра, касающихся запрета на получение:
* RejectMessagesFrom - только единичные пользователи
* RejectMessagesFromDLMembers - группы
* RejectMessagesFromSendersOrMembers - сюда автоматически копируется всё из предыдущих параметров
# Получить список всех запрещённых отправителей
(Get-Mailbox i.petrov).RejectMessagesFromSendersOrMembers |select name
==== Удаление адресов X400 ====
# Предварительный отчёт для ящиков
$allmailboxes = get-mailbox -ResultSize Unlimited
$report = @()
foreach ($mbx in $allmailboxes) {
$smtpaddr,$x400addr = ($mbx.emailaddresses).where({$_ -notmatch "x400:"}, 'split')
$str = [pscustomobject]@{
Name = $mbx.name
Alias = $mbx.alias
SMTP = $smtpaddr -join "`n"
X400 = ($x400addr -join "`n").ToString()
}
$report += $str
}
$report |sort name |Export-Csv "c:\temp\MailboxesX400report.csv" -Delimiter ';' -NoTypeInformation -Encoding UTF8
# Удалить адреса X400 из ящиков
foreach ($mbx in (get-mailbox -ResultSize Unlimited)) {
$smtpaddr = ($mbx.emailaddresses).where{$_ -notmatch "x400:"}
set-mailbox $mbx.Identity -emailaddresses $smtpaddr
}
# Удалить адреса X400 из групп рассылки
foreach ($dg in (Get-DistributionGroup -ResultSize Unlimited)) {
$smtpaddr = ($dg.emailaddresses).where{$_ -notmatch "x400:"}
set-DistributionGroup $dg.Identity -emailaddresses $smtpaddr
}
==== Управление адресами ====
# Добавить адрес к ящику
set-mailbox ivanov -EmailAddresses @{add="sidorov@example.com"}
# Удалить пользователя из прав на отправку в группе рассылки (пользователь не существует в AD)
Remove-ADPermission DG-marketing -User "S-1-5-21-1482476501-1004336348-839522115-5731" -Extendedrights "Send As" -Confirm:$false
==== PST ====
Подключить в Outlook
Add-type -assembly "Microsoft.Office.Interop.Outlook" > $null
$outlook = new-object -comobject outlook.application
$namespace = $outlook.GetNameSpace("MAPI")
dir "$env:userprofile\Documents\Файлы Outlook\*.pst" |% {$namespace.AddStore($_.FullName)}
===== Права =====
# Убрать права юзера на ящик
get-mailboxpermission -identity mailboxowner -user user | remove-mailboxpermission
# Выдать полные права на календарь (-AccessRights Reviewer - чтение)
Add-MailboxFolderPermission -Identity mailboxowner:\Календарь -User user -AccessRights Owner
# Дать права Full Access группе на ящик
Add-MailboxPermission "mailboxName" -User "groupName" -AccessRights "FullAccess"
# дать права группе на отправку от имени ящика
get-mailbox "mailboxName" |Add-ADPermission -User "groupName" -ExtendedRights "Send As"
===== Календари =====
# Посмотреть доступ для учётки Username к каким-либо календарям
ForEach ($mbx in Get-Mailbox -ResultSize Unlimited) {Get-MailboxFolderPermission ($mbx.Name + ":\Календарь") | Where-Object {$_.User -like "Username"} | Select @{Name="Calendar Of";expression={($mbx.name)}},User,AccessRights}
# Посмотреть, кто имеет к календарю учётки Username
Get-MailboxFolderPermission Username:\Календарь | ft user,accessrights -AutoSize
# Выгрузить список пользователей, имеющих права на календарь
# с нестандартным именем "Общий календарь"
Get-MailboxFolderPermission "Username:\Название учётки - Общий календарь" | select User,AccessRights | sort User | Out-File -Encoding UTF8 $env:userprofile\desktop\username-cal-users.txt
===== Письма =====
# Удалить из всех ящиков письмо с определённой темой за определённый день, от определённого адреса и где нет вложений .xlsx
Get-Mailbox -ResultSize unlimited |Search-Mailbox -SearchQuery `
'Subject:"Вниманию руководителей структурных подразделений" AND Received:"16.11.2022" AND from:"pr@example.com" NOT Attachment:"*.xlsx"' `
-DeleteContent -Force
# Найти письма в ящике и скопировать результаты в другой ящик
Search-Mailbox username -SearchQuery 'from:"someone@domain.ru" AND sent:"07.04.2020"' -TargetMailbox admin -TargetFolder "SearchQueries"
# Удалить письмо из ящика пользователя
search-mailbox username -SearchQuery 'from:"someone" AND subject:"Табель за апрель, 1-я половина" AND sent:"07.04.2020"' -DeleteContent -Force
# Поиск письма в транспортных журналах (RecipientStatus - причина отлупа)
Get-MessageTrackingLog -Sender "sender@domain.ru" |select RecipientStatus
$mbx = Get-Mailbox -ResultSize unlimited
# Найти, у кого есть письмо с определённой темой
$mbx | Search-Mailbox -SearchQuery 'subject:"Объяснительная Вселенная унитазов"' -EstimateResultOnly |? ResultItemsCount -ne 0
RunspaceId : 12345678-1234-1234-1234-123456789012
Identity : domain.ru/Kontora/1_Users/Горчакова Мариэтта Петровна
TargetMailbox :
Success : True
TargetFolder :
ResultItemsCount : 1
ResultItemsSize : 36.08 KB (36,948 bytes)
RunspaceId : 12345678-1234-1234-1234-123456789013
Identity : domain.ru/Kontora/1_Users/Саруманов Сергей Викторович
TargetMailbox :
Success : True
TargetFolder :
ResultItemsCount : 1
ResultItemsSize : 44.68 KB (45,749 bytes)
A space between two keywords or two //property:value// expressions is the same as using **AND.** For example, //%%from:"Sara Davis" subject:reorganization%%// returns all messages sent by Sara Davis that contain the word **reorganization** in the subject line.\\
[[https://learn.microsoft.com/en-us/powershell/module/exchange/search-mailbox?view=exchange-ps|Search-Mailbox]]\\
[[https://docs.microsoft.com/en-US/exchange/security-and-compliance/in-place-ediscovery/message-properties-and-search-operators|Свойства и операторы поиска]]
===== Переадресация =====
# Установить переадресацию
Set-Mailbox "Выскина Анна Алексеевна" -ForwardingAddress "Розова Виктория Викторовна"
# Переадресация с одновременным хранением в первоначальном ящике
Set-Mailbox "Выскина Анна Алексеевна" -DeliverToMailboxAndForward $true -ForwardingAddress "Розова Виктория Викторовна"
# Заполнить обоснование в AD (В поле "Почтовый ящик")
Set-ADUser (Get-ADUser -filter "name -eq 'Выскина Анна Алексеевна'" -Properties postOfficeBox) -replace @{postOfficeBox="СЗ №07/1 - 1234 от 13.05.2021"} -Confirm:$false
# Занести в переменную адреса ящика
$addr = (Get-ADUser -filter "name -eq 'Киренко Петр Александрович'" -Properties proxyaddresses).proxyaddresses -replace "^smtp:"
# Добавить эти адреса другому ящику (делать только после удаления исходного)
Set-Mailbox "Гончарова Маргарита Борисовна" -EmailAddresses @{add=$addr}
# Убрать ВСЕ переадресации с ящика и убрать обоснование в поле "Почтовый ящик" в AD
$user = "Копач Олег Сергеевич"
Set-Mailbox $user -DeliverToMailboxAndForward $false -ForwardingSMTPAddress $null -ForwardingAddress $null
Set-ADUser (Get-ADUser -filter "name -eq `'$user`'" -Properties postOfficeBox) -clear 'postOfficeBox' -Confirm:$false
Есть 2 типа переадресации:
- ForwardingAddress – Задаётся администратором, у пользователя нет доступа к этой настройке.
- ForwardingSMTPAddress – Пользователь может задать эту переадресацию в Outlook web access (OWA)
# Убрать все переадресации в ящике
Set-Mailbox paulie -ForwardingAddress $NULL -ForwardingSmtpAddress $NULL
https://learn.microsoft.com/en-us/exchange/recipients/user-mailboxes/email-addresses\\
https://learn.microsoft.com/en-us/exchange/recipients/user-mailboxes/email-forwarding\\
https://www.tachytelic.net/2019/06/remove-forwarding-office-365-powershell
===== Группы рассылки =====
Динамическая группа рассылки, получатели берутся из OU=Company,DC=domain,DC=ru, слать на неё разрешено только группе MailRights-DDG-allstaff-sendto. Из списка рассылки исключен генеральный директор и его заместители.
# Группа с правами на отправку
New-DistributionGroup -Name "MailRights-DDG-allstaff-sendto" -OrganizationalUnit "OU=Mail,DC=domain,DC=ru" -SamAccountName "MailRights-DDG-allstaff-sendto" -Type "Security"
Set-DistributionGroup MailRights-DDG-allstaff-sendto -HiddenFromAddressListsEnabled $true
# Сама группа рассылки
New-DynamicDistributionGroup -Name "DDG-allstaff" -Alias "allstaff" -DisplayName "Все сотрудники" -RecipientContainer "OU=Company,DC=domain,DC=ru" `
-OrganizationalUnit "OU=Mail,DC=domain,DC=ru" -RecipientFilter {title -notlike "*Заместитель Генерального директора*" -and title -ne "Генеральный директор"}
# Оставшиеся параметры
Set-DynamicDistributionGroup -Identity "DDG-allstaff" -AcceptMessagesOnlyFromDLMembers "MailRights-DDG-allstaff-sendto" -Notes "Все, кроме ГД и заместителей"
Фильтр получателей с исключением, например, когда нужно исключить всех замов, но одного включить.
Set-DistributionGroup DDG-allstaff -RecipientFilter {
(title -notlike "*Заместитель Генерального директора*" -and title -ne "Генеральный директор") -or `
(name -eq "Рассылкин Иван Иванович")
}
==== Список членов динамической группы рассылки ====
$ddg = Get-DynamicDistributionGroup -Identity "DDG-allstaff"
Get-Recipient -RecipientPreviewFilter $ddg.RecipientFilter -OrganizationalUnit $ddg.RecipientContainer
# Тестирование работы фильтра
Get-Recipient -RecipientPreviewFilter {title -ne 'Генеральный директор'} |? name -match "Иванов"
==== Добавить пользователя в статическую группу рассылки ====
Add-DistributionGroupMember -Identity group -Member ivanovii -BypassSecurityGroupManagerCheck
==== Включить возможность слать извне на группу рассылки ====
Set-DistributionGroup -Identity group -RequireSenderAuthenticationEnabled $false
===== Настройка сервера =====
$server = "srv-mbx01"
# Информация о лицензии
Get-ExchangeServer $server | fl Name,Edition,*Trial*
# Ввести ключ
Set-ExchangeServer $server -ProductKey 12345-12345-12345-12345-12345
# Просмотр настройки фильтров на Edge (сама настройка - Set-)
Get-ContentFilterConfig
Get-RecipientFilterConfig
Get-SenderFilterConfig
# Content filter приходится выключать, т. к. слишком часто отбрасывает нужные письма.
Get-ContentFilterConfig -SCLRejectEnabled $false -SCLDeleteEnabled $false -SCLQuarantineEnabled $false
# Либо настраивать какой-нибудь ящик как карантинный, но потом возиться с письмами, которые туда попадают.
# Письма от user@sender.ru и user@sender2.ru - ошибка "451 4.3.2 System not accepting network messages - Content Filter Agent"
# На Edge:
Set-ContentFilterConfig –BypassedSenderDomains @{Add="sender.ru", "sender2.ru"}
# Если нужно убрать адреса из списка
Set-ContentFilterConfig –BypassedSenderDomains @{Remove="sender.ru", "sender2.ru"}
===== Коннекторы =====
# Посмотреть FQDN и ограничения на размер сообщений
Get-SendConnector |select identity,fqdn,maxmessagesize
Get-ReceiveConnector |select identity,fqdn,maxmessagesize
# Задать ограничение в 30 МБ для сообщений
Get-SendConnector |% {Set-SendConnector $_ -MaxMessageSize 30MB}
Get-ReceiveConnector |% {Set-ReceiveConnector $_ -MaxMessageSize 30MB}
===== Пересоздание подписки на Edge =====
Проверка
Test-EdgeSynchronization |select name,syncstatus,FailureDetail,@{n="LastSync";e={($_.LastSynchronizedUtc).addhours(3)}}
Name SyncStatus FailureDetail LastSync
---- ---------- ------------- --------
srv-edge2 Normal 31.01.2023 15:55:13
# удалить подписку на Edge и на транспорте
get-edgesubscription | remove-edgesubscription
# сформировать файл на Edge
New-EdgeSubscription -FileName c:\temp\ES.xml
# скопировать файл с Edge на Транспорт
# на транспорте создаем подписку
New-EdgeSubscription -FileData ([byte[]]$(Get-Content -Path "c:\temp\ES.xml" -Encoding Byte -ReadCount 0)) -Site "Default-First-Site-Name"
# Установить максимальный размер отправляемых сообщений на 30Mb
Get-SendConnector |% {Set-SendConnector $_ -MaxMessageSize 30MB}
# Задать FQDN как edge.domain.ru
Get-SendConnector |? name -match '^EdgeSync' |Set-SendConnector -Fqdn 'edge.domain.ru'
# Синхронизировать изменения
Start-EdgeSynchronization
# Тест
Test-EdgeSynchronization
===== Замена SSL-сертификатов =====
# Import-Module "$env:ExchangeInstallPath\Bin\RemoteExchange.ps1"
# Connect-ExchangeServer -auto
$mailServers = (Get-ExchangeServer |? IsMailboxServer).name
$certFile = "\\domain.ru\fs\share\cert\2022\cert.pfx"
$certPass = Read-Host "Введите пароль сертификата"
# Импорт
$mailServers |% {
Import-ExchangeCertificate -Server $_ -FileName $certFile -Password (ConvertTo-SecureString -String "$certPass" -AsPlainText -Force)
}
# Включить новый сертификат для служб
Get-ExchangeCertificate # выяснить Thumbprint нового и старого сертификата для следующих команд
$thumbprintNew = "A9B662C98263911226A81EC5BA4AFCA958A237BC"
$thumbprintOld = "D1C6ED2B39A19BFEF0216B94E2D74E77B044F7B4"
$mailServers |% {
Enable-ExchangeCertificate -Thumbprint $thumbprintNew -Services IIS,SMTP -Server $_ -DoNotRequireSsl
}
# Удалить старый
$mailServers |% {
Remove-ExchangeCertificate -Thumbprint $thumbprintOld -Server $_
}
### На Edge - скопировать сертификат в c:\temp\cert.pfx ###
$certFile = "c:\temp\cert.pfx"
$certPass = Read-Host "Введите пароль сертификата"
Import-ExchangeCertificate -FileName $certFile -Password (ConvertTo-SecureString -String "$certPass" -AsPlainText -Force)
Get-ExchangeCertificate
$thumbprintNew = "A9B662C98263911226A81EC5BA4AFCA958A237BC"
$thumbprintOld = "D1C6ED2B39A19BFEF0216B94E2D74E77B044F7B4"
Enable-ExchangeCertificate -Thumbprint $thumbprintNew -Services SMTP
Remove-ExchangeCertificate -Thumbprint $thumbprintOld
https://docs.microsoft.com/en-us/powershell/module/exchange/import-exchangecertificate?view=exchange-ps\\
https://docs.microsoft.com/en-us/exchange/architecture/client-access/assign-certificates-to-services?view=exchserver-2019
==== ASSERT: HMACprovider.GetCertificates:ProtectionCertificates.Length<1 ====
После удаления сертификата, привязанного только к SMTP, перестала работать OWA и ECP. Ошибка после попытки логина:
(Get-AuthConfig).CurrentCertificateThumbprint | Get-ExchangeCertificate | Format-List
# A special Rpc error occurs on server WS-MS1: The certificate with thumbprint D7482B97190A5517B581A6A768AF356C13887918 w
# as not found.
# + CategoryInfo : NotSpecified: (:) [Get-ExchangeCertificate], InvalidOperationException
# + FullyQualifiedErrorId : [Server=WS-MS1,RequestId=15314839-d0a6-4b13-ab88-da483bbbc78c,TimeStamp=01.09.2023 5:41:
# 47] [FailureCategory=Cmdlet-InvalidOperationException] CFD7CD37,Microsoft.Exchange.Management.SystemConfigurationT
# asks.GetExchangeCertificate
# + PSComputerName : ws-ms1.example.com
При попытке создать новый сертификат говорится, что сертификат уже есть:
New-ExchangeCertificate -KeySize 2048 -PrivateKeyExportable $true `
-SubjectName "cn=Microsoft Exchange Server Auth Certificate" -FriendlyName "Microsoft Exchange Server Auth Certificate" -DomainName @()
# Confirm
# Overwrite the existing default SMTP certificate?
# Current certificate: 'F7630C1126AC09F9BB9152CFA5623D06D7089E7C' (expires 16.01.2028 8:54:05)
# Replace it with certificate: '11C2C4B244066744CA8CA65701D4A85D99693677' (expires 01.09.2028 8:42:11)
# [Y] Yes [A] Yes to All [N] No [L] No to All [?] Help (default is "Y"): n
Поэтому удаляем только что созданный сертификат и привязываем тот, который уже есть и публикуем его:
# Удаление
Remove-ExchangeCertificate 11C2C4B244066744CA8CA65701D4A85D99693677
# Привязка
Set-AuthConfig -NewCertificateThumbprint F7630C1126AC09F9BB9152CFA5623D06D7089E7C `
-NewCertificateEffectiveDate (Get-Date)
# Confirm
# The new certificate effective date is not at least "48" hours in the future and may not be deployed on all necessary
# servers. Do you wish to continue?
# [Y] Yes [A] Yes to All [N] No [L] No to All [?] Help (default is "Y"): y
# Публикация
Set-AuthConfig -PublishCertificate
Сертификат уже распространился на все почтовые сервера, теперь нужно перезапустить пулы __на каждом сервере__.
Restart-WebAppPool MSExchangeOWAAppPool
Restart-WebAppPool MSExchangeECPAppPool
[[https://learn.microsoft.com/en-us/exchange/troubleshoot/administration/cannot-access-owa-or-ecp-if-oauth-expired|Can't sign in to Outlook on the web or EAC if Exchange Server OAuth certificate is expired]]\\
===== Очередь =====
# Удалить письма от определённого адресата со всех серверов HubTransport (-withNDR - без отчёта о недоставке)
Get-ExchangeServer |? IsHubTransportServer |Get-Queue |get-message |? fromaddress -eq 'user@domain.ru' |Remove-Message -withNDR $false -Confirm:$false
# С Edge
Get-Queue |get-message |? fromaddress -eq 'user@domain.ru' |Remove-Message -withNDR $false -Confirm:$false
===== Информация =====
В Exchange management shell
# Версия Exchange (https://docs.microsoft.com/en-us/Exchange/new-features/build-numbers-and-release-dates)
(Get-Command Exsetup.exe).FileVersionInfo
ProductVersion FileVersion FileName
-------------- ----------- --------
15.00.1497.033 15.00.1497.033 c:\Program Files\Microsoft\Exchange Server\V15\bin\ExSetup.exe
===== Прочее =====
==== Чистка логов на серверах ====
$hosts = "ex1","ex2","ex3"
Invoke-Command -computername $hosts -command {
$t = get-date
# Чистка логов IIS - оставляем 7 дней
gci 'C:\inetpub\logs\LogFiles' -Include '*.log' -Recurse |? LastWriteTime -LT $t.AddDays(-7) |Remove-Item
# Чистка логов Exchange - оставляем 3 месяца
gci 'C:\Program Files\Microsoft\Exchange Server\V15\Logging' -Include '*.log', '*.blg' -Recurse |? LastWriteTime -LT $t.AddMonths(-3) |Remove-Item
}
==== Срок хранения транспортных журналов ====
# Просмотр настроек
Get-TransportService |select *tracking*
# Изменение
Set-TransportService srv-edge2 -MessageTrackingLogMaxAge 100 -MessageTrackingLogMaxDirectorySize 5GB -MessageTrackingLogMaxFileSize 30MB
==== Запустить Exchange shell в Powershell ====
Нужно, чтобы на компе админа были установлены компоненты управления.
Import-Module "$env:ExchangeInstallPath\Bin\RemoteExchange.ps1"
Connect-ExchangeServer -auto
Другой способ (для 2013):
Add-PSSnapin Microsoft.Exchange.Management.PowerShell.Support,Microsoft.Exchange.Management.PowerShell.E2010,Microsoft.Exchange.Management.PowerShell.SnapIn
[[http://hkeylocalmachine.com/?p=180|How do I add the Exchange PowerShell module into a standard PowerShell session]]
==== Connect to Exchange servers using remote PowerShell ====
В данном случае в конторе три сервера - exch1, exch2, exch3, перебор до первого, с кем удастся установить соединение.
$c = 1
do {$pssession = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri http://exch$($c).domain.ru/PowerShell/ -Authentication Kerberos -ErrorAction SilentlyContinue; $c++}
until ($? -or $c -gt 3)
if (!$?) {write-host -fore red "Не удалось подключиться ни к одному серверу Exchange"; sleep 2; exit}
Import-PSSession $pssession -DisableNameChecking -ErrorAction SilentlyContinue > $null
if (!$?) {write-host -fore red "Ошибка импорта удалённой сессии Powershell"; sleep 2; exit}
# do some work
Remove-PSSession $Session
https://docs.microsoft.com/en-us/powershell/exchange/exchange-server/connect-to-exchange-servers-using-remote-powershell?view=exchange-ps
==== Ссылка создания шаблонного письма ====
mailto:mail@domain.ru?subject=Привет%20всем&body=Здравствуйте!%20Как%20вы%20поживаете?%20%0A%0DУ%20меня%20всё%20нормально.%0A%0DПишите.
==== Предуведомление о спаме ====
Идея - добавлять предуведомление в тело письма после пограничного антиспама, добавляющего тэги в тему ([Spam], [Phishing] и т. п.). Реализуется правилом на сервере Exchange с действием Prepend the disclaimer.
Примерное содержание уведомления:
Внимание!
Антиспам-система предприятия распознала это письмо из внешней
почты как подозрительное.
Подобные письма могут содержать вредоносные вложения, ссылки на
сайты злоумышленников или заведомо ложную информацию.
Будьте осторожны:
- Не открывайте ссылки и приложенные файлы.
- Если письмо пришло от знакомого вам адресата, но содержит неожиданные сведения или запросы
(ссылки на документы или сайты, приложенные файлы), уточните у отправителя по телефону или другим способом,
действительно ли он отправлял вам это письмо. Помните, что злоумышленники могли завладеть
почтой вашего собеседника или подделать обратный адрес.
- Не вводите пароли, телефоны, номера карт и другую персональную информацию,
если по ссылкам из письма открываются сайты, которые их запрашивают,
даже если сайты выглядят похоже на привычные (корпоративная или личная веб-почта,
сайт предприятия, личный кабинет вашего банка и т. п.)
- Не доверяйте сведениям, содержащимся в письме. Злоумышленники могут сообщать вам,
что пароль истёк (и нужно его сообщить для замены), что на вашем компьютере работает троянская программа
(и вы должны заплатить выкуп), что ваш отчёт в контролирующий орган не принят (и вам необходимо срочно ознакомиться
с приложенной к письму претензией в формате PDF), и тому подобное.
Помните, что злоумышленники стараются напугать жертву или заставить её торопиться, чтобы снизить осторожность.
Для получения дополнительной информации обращайтесь в Управление безопасности.
https://batishchev.ru/blog/all/kenk-klms-disclaimer/
==== Поиск ящика, которому принадлежит адрес ====
Get-Recipient |? emailaddresses -match 'pass' |select name,emailaddresses
===== Отчёты =====
Кол-во отправленных и полученных писем за прошлый месяц на Exchange Edge
Add-PSSnapin Microsoft.Exchange.Management.PowerShell.E2010
$reportpath = "C:\scripts\Send-Receive-statistics"
#за весь прошлый месяц
$startdate = ((get-date -day 1).AddMonths(-1)).Date
$enddate = ((get-date -day 1).date).AddSeconds(-1)
$mailboxes = ((get-messagetrackinglog -Start $startdate -End $enddate -ResultSize unlimited |
? EventId -match "SEND|RECEIVE" |select -expand Recipients) -split ', ') -match '@domain.ru' |sort -Unique
$report = @()
foreach ($mbx in $mailboxes) {
$mbxstat = '' |select 'Адрес','Кол-во полученных сообщений','Кол-во отправленных сообщений'
$mbxstat.'Адрес' = $mbx.tolower()
$mbxstat.'Кол-во полученных сообщений' = (Get-MessageTrackingLog -Start $startdate -End $enddate -EventId "RECEIVE" -Recipients $mbx -ResultSize Unlimited).count
$mbxstat.'Кол-во отправленных сообщений' = (Get-MessageTrackingLog -Start $startdate -End $enddate -EventId "SEND" -Sender $mbx -ResultSize Unlimited).count
$report += $mbxstat
}
$mark = (get-date).ToString("yyyy-MM-dd")
$report |Export-Csv -Path "$reportpath\$mark-mailboxes-send-receive-stat-$($startdate.ToString("MMMM-yyyy")).csv" -Delimiter ';' -Encoding UTF8 -NoTypeInformation
#$report |sort 'Имя' |Export-Excel -Path "$reportpath\$mark-mailboxes-send-receive-stat-$($startdate.ToString("MMMM-yyyy")).xlsx" -AutoSize -FreezeTopRow -AutoFilter -BoldTopRow
sleep 30
$attach = (gci "$reportpath\*.csv" |sort creationtime |select -last 1).fullname
$mailbody = "Отчёт по отправленным и полученным письмам за период с $($startdate.ToString()) по $($enddate.ToString())
"
$mailbody += "Общее количество адресов в отчёте - $($expomailboxes.Count)`.
"
$mailbody += "Отчёт сформирован скриптом $($PSScriptRoot + '\' + $MyInvocation.MyCommand) на компьютере $($env:COMPUTERNAME).
"
Send-MailMessage -SmtpServer mail.domain.ru -From "support@domain.ru" -To 'admin@domain.ru' -Subject "Exchange Edge - статистика по отправленным и полученным письмам" -Body "$mailbody" -Attachments "$attach" -Encoding UTF8 -bodyashtml
===== Статьи =====
[[http://www.michev.info/Blog/Post/1516/quickly-list-all-mailboxes-to-which-a-particular-user-has-access|Quickly list all mailboxes to which a particular user has access]]
[[http://www.powertheshell.com/displaying-complete-results/|Displaying Complete Results]]
[[https://www.codetwo.com/admins-blog/new-mailboxrepairrequest-the-successor-of-the-isinteg-tool/|New-MailboxRepairRequest – the successor of the Isinteg tool]]
===== Autodiscover =====
Порядок поиска автонастройки клиентами, каждый следующий способ используется после неудачного использования предыдущего:
- SCP (Service Connection Point), для доменных клиентов. Путь (MMC Sites and Services): //CN=CAS01,CN=Autodiscover,CN=Protocols,CN=CAS01,CN=Servers,CN=Exchange Administrative Group (ABCDE123456),CN=Administrative Groups,CN=Domain,CN=Microsoft Exchange,CN=Services,CN=Configuration,DC=domain,DC=ru//\\ Клиенты читают 3 атрибута:\\ **serviceBindingInformation** – FQDN CAS-сервера (%%https://
# Получить список серверов
Get-ClientAccessServer | fl Name,AutoDiscoverServiceInternalUri,AutoDiscoverSiteScope,WhenCreated
- Внешние клиенты обращаются в DNS за стандартными URLs службы Autodiscover:\\ //%%https://
Set-ServerComponentState -Identity srv.domain.ru -State Active -Requester HealthAPI -Component Imapproxy
Set-ServerComponentState -Identity srv.domain.ru -State Active -Requester HealthAPI -Component PopProxy
==== Учётка в AD блокируется с серверов Exchange ====
++++ Удобный скрипт поиска времени блокировки на контроллерах домена |
<#
.SYNOPSIS
This function will locate the computer that processed a failed user logon attempt which caused the user account to become locked out.
.DESCRIPTION
This function will locate the computer that processed a failed user logon attempt which caused the user account to become locked out.
The locked out location is found by querying the PDC Emulator for locked out events (4740).
The function will display the BadPasswordTime attribute on all of the domain controllers to add in further troubleshooting.
.EXAMPLE
PS C:\>Get-LockedOutLocation -Identity Joe.Davis
This example will find the locked out location for Joe Davis.
.NOTE
This function is only compatible with an environment where the domain controller with the PDCe role to be running Windows Server 2008 SP2 and up.
The script is also dependent the ActiveDirectory PowerShell module, which requires the AD Web services to be running on at least one domain controller.
Author: Jason Walker
Last Modified: 3/20/2013
#>
Function Get-LockedOutLocation {
[CmdletBinding()]
Param(
[Parameter(Mandatory=$True)]
[String]$Identity
)
Begin {
$DCCounter = 0
$LockedOutStats = @()
Try { Import-Module ActiveDirectory -ErrorAction Stop }
Catch {
Write-Warning $_
Break
}
}
Process {
#Get all domain controllers in domain
$DomainControllers = Get-ADDomainController -Filter *
$PDCEmulator = $DomainControllers | Where-Object { $_.OperationMasterRoles -contains "PDCEmulator" }
Write-Verbose "Finding the domain controllers in the domain"
ForEach($DC in $DomainControllers) {
$DCCounter++
Write-Progress -Activity "Contacting DCs for lockout info" -Status "Querying $($DC.Hostname)" -PercentComplete (($DCCounter/$DomainControllers.Count) * 100)
Try { $UserInfo = Get-ADUser -Identity $Identity -Server $DC.Hostname -Properties AccountLockoutTime,LastBadPasswordAttempt,BadPwdCount,LockedOut -ErrorAction Stop }
Catch {
Write-Warning $_
Continue
}
if ($UserInfo.LastBadPasswordAttempt) {
$LockedOutStats += New-Object -TypeName PSObject -Property @{
Name = $UserInfo.SamAccountName
SID = $UserInfo.SID.Value
LockedOut = $UserInfo.LockedOut
BadPwdCount = $UserInfo.BadPwdCount
BadPasswordTime = $UserInfo.BadPasswordTime
DomainController = $DC.Hostname
AccountLockoutTime = $UserInfo.AccountLockoutTime
LastBadPasswordAttempt = ($UserInfo.LastBadPasswordAttempt).ToLocalTime()
}
}
}
$LockedOutStats | Format-Table -Property Name,LockedOut,DomainController,BadPwdCount,AccountLockoutTime,LastBadPasswordAttempt -AutoSize
#Get User Info
Try {
Write-Verbose "Querying event log on $($PDCEmulator.HostName)"
$LockedOutEvents = Get-WinEvent -ComputerName $PDCEmulator.HostName -FilterHashtable @{LogName='Security';Id=4740} -ErrorAction Stop | Sort-Object -Property TimeCreated -Descending
}
Catch {
Write-Warning $_
Continue
}
ForEach ($Event in $LockedOutEvents) {
if ($Event | Where {$_.Properties[2].value -match $UserInfo.SID.Value}) {
$Event | Select-Object -Property @(
@{Label = 'User'; Expression = {$_.Properties[0].Value}}
@{Label = 'DomainController'; Expression = {$_.MachineName}}
@{Label = 'EventId'; Expression = {$_.Id}}
@{Label = 'LockedOutTimeStamp'; Expression = {$_.TimeCreated}}
@{Label = 'Message'; Expression = {$_.Message -split "`r" | Select -First 1}}
@{Label = 'LockedOutLocation'; Expression = {$_.Properties[1].Value}}
)
}
}
}
}
++++
https://github.com/a118n/poweradmin/blob/master/Get-LockedOutLocation.ps1
Потом нужно смотреть в логи IIS на соответствующем сервере, путь
C:\inetpub\logs\LogFiles\W3SVCx
Учитывать, что время в логах IIS в UTC (т. е. нужно вычесть 3 часа).
==== Outlook - ошибка сертификата безопасности прокси-сервера ====
Ошибка возникла после замены сертификата wildcard на прокси-сервере, через который идут клиентские подключения, на обычный Let's Encrypt. При запуске Outlook у некоторых пользователей возникает ошибка вида
{{:service:pasted:20221226-120003.png}}
Оказалось, что в Exchange существует параметр для Outlook Anywhere, который необходим старым клиентам для корректного подключения. Новые клиенты (Outlook 2016) игнорируют этот параметр, поэтому на них ошибка не возникает.
PS>Get-OutlookProvider
Name Server CertPrincipalName TTL
---- ------ ----------------- ---
exch 1
expr msstd:*.example.ru 1
WEB 1
В интернете есть [[https://community.spiceworks.com/topic/2254121-outlook-error-to-exchange-saying-wrong-ssl-certificate-name|рекомендация по удалению]] CertPrincipalName, но это не исправляет ситуацию. Нужно просто переделать имя на реальное вместо wildcard.
PS>Set-OutlookProvider EXPR -CertPrincipalName:msstd:mail.example.ru
[[https://learn.microsoft.com/en-us/answers/questions/146023/question-on-set-outlookprovider-expr.html|Question on Set-OutlookProvider EXPR]]
==== После смены внутреннего сертификата невозможно зайти на OWA и EAC ====
После ввода логина и пароля выбрасывает опять на страницу входа.\\
Решение - поставить тот же сертификат на сайт "Exchange Back End" в IIS, привязка на порт 444.
{{:service:pasted:20230116-080659.png}}
{{:service:pasted:20230116-080837.png}}
{{:service:pasted:20230116-081001.png}}
Затем нужно перезапустить IIS.
https://learn.microsoft.com/en-us/exchange/troubleshoot/client-connectivity/owa-ecp-ems-cannot-connect-after-self-signed-certificate-removed
==== Autodiscover - разрешить этому веб-сайту выполнить настройку параметров сервера? ====
После переключения имени autodiscover.example.com на реверс-прокси с серверов напрямую (DNS round robin), начало выдаваться сообщение:
{{:service:pasted:20230117-140349.png}}
Если выбрать "больше не спрашивать", то в реестре по пути ''HKEY_CURRENT_USER\Software\Microsoft\Office\
function Set-AutodiscoverKey {
param($key,$addr)
if ((gci Registry::$key).property -notcontains $addr) {
Write-Host -fore red "No record $addr, adding it to $($key.name)"
$null = New-ItemProperty `
-Path Registry::$key\RedirectServers `
-Name $addr `
-type None `
-Value ([byte[]]@()) `
-Force
}
else {
Write-Host -fore green "The record $addr exists in $($key.name)"
}
}
$addresses = "mail.example.com","autodiscover.example.com"
$reg = (gci Registry::HKCU\SOFTWARE\Microsoft\Office\*\Outlook\*) -match "autodiscover"
if (!$reg) {exit}
foreach ($key in $reg) {
$addresses |% {
Set-AutodiscoverKey $key $_
}
}
[[https://learn.microsoft.com/ru-ru/outlook/troubleshoot/connectivity/how-to-suppress-autodiscover-redirect-warning|Подавление предупреждения перенаправления автообнаружения в Outlook]]\\
[[https://learn.microsoft.com/ru-ru/outlook/troubleshoot/profiles-and-accounts/unexpected-autodiscover-behavior?source=recommendations|Неожиданное поведение автообнаружения, когда есть настройки в разделе \Autodiscover]]
==== Невозможно удалить сертификат из Exchange Admin Center ====
При попытке удалить сертификат появляется ошибка:
{{:service:pasted:20230130-103336.png}}
Дело в том, что сертификат на подмену уже есть и привязан к службам. Решить проблему можно обходным путём,
Enable-ExchangeCertificate -Thumbprint -Services SMTP
Иначе письма будут застревать в очереди внутренних серверов.
https://learn.microsoft.com/en-us/answers/questions/911472/no-edgesync-credentials-were-found-for-edge-transp
==== Exchange Edge блокирует легитимные вложения ====
Не приходит вложение filename.xlsx.zip, заменяется на txt с содержимым "Вложение было удалено". В списке расширений фильтра вложений это сочетание отсутсвует.
++++ Список расширений в Attachment filter|
(Get-AttachmentFilterEntry).name |sort
*.ade
*.adp
*.app
*.asx
*.bas
*.bat
*.chm
*.cmd
*.com
*.cpl
*.crt
*.csh
*.exe
*.fxp
*.hlp
*.hta
*.inf
*.ins
*.isp
*.js
*.jse
*.ksh
*.lnk
*.mda
*.mdb
*.mde
*.mdt
*.mdw
*.mdz
*.msc
*.msi
*.msp
*.mst
*.ops
*.pcd
*.pif
*.prf
*.prg
*.ps1
*.ps11
*.ps11xml
*.ps1xml
*.ps2
*.ps2xml
*.psc1
*.psc2
*.reg
*.scf
*.scr
*.sct
*.shb
*.shs
*.url
*.vb
*.vbe
*.vbs
*.wsc
*.wsf
*.wsh
*.xnk
application/hta
application/javascript
application/msaccess
application/prg
application/x-javascript
application/x-msdownload
message/partial
text/javascript
text/scriptlet
x-internet-signup
++++
Решение: выключить фильтр
Disable-TransportAgent "Attachment Filtering Agent"
и перенести все расширения в Каспер.
{{:service:pasted:20230130-142749.png?600}}