Для отправки писем в Powershell есть команда Send-MailMessage. С помощью этой команды мы можем выполнять отправку писем используя вложения, HTML формат и множеству получателей. У этой команды есть ряд особенностей, которые мы рассмотрим ниже на примерах.
Настройка SMTP сервера
Что бы вы смогли отправить письмо вы должны знать настройки для вашего сервера. Почтовые сервера, для отправки писем, используют протокол SMTP. Когда сервера SMTP общаются друг с другом они используют 25 порт, а клиент с сервером 465 или 587 порт. Кроме этого вы должны знать по какому адресу отвечает сервер и использует ли он шифрование. Обычно, если вы используете публичного провайдера, эти настройки доступны в документации.
Ниже пример настроек для яндекса:
- smtp.yandex.com;
- SSL;
- 465.
Адрес сервера, в Powershel, можно указать двумя способами. Можно объявить используя специальную встроенную переменную $PSEmailServer:
$PSEmailServer = 'smtp.yandex.com'
Такая переменная будет работать в рамках одной сессии Powershell (до закрытия консоли) и нам не нужно будет указывать ее в каждой команде. Например так:
Send-MailMessage -SmtpServer 'smtp.yandex.ru'
Отмечу, что в случае яндекса и gmail знать логин/пароль и почтовый сервер не достаточно. В случае этих провайдеров, в их веб интерфейсах, понадобится настраивать специфические разрешения. В случае обычных, локальных серверов, этого обычно не требуется.
Порт сервера устанавливается в дополнительном параметре Port. Если он не указан, то будет использоваться порт по умолчанию - 25:
Send-MailMessage -SmtpServer 'smtp.yandex.ru' -Port 465
Аутентификация
Что бы мы могли отправить письмо - мы должны предоставить пару логин и пароль. Это можно сделать с помощью команды 'Get-Credential':
Send-MailMessage -SmtpServer 'smtp.yandex.ru' -Port 465 -Credential (Get-Credential)
Как видно на скриншоте - при каждом выполнении команды у нас появляется окно для ввода логина и пароля. Вы так же можете сохранить учетные данные в переменную и передавать ее в команды:
$cred = Get-Credentials
Send-MailMessage -SmtpServer 'smtp.yandex.ru' -Port 465 -Credential $cred
При работе с командой Get-Credential есть неочевидная деталь - ее запуск создает объект (логин и пароль) в памяти. Любая попытка его экспортировать (сохранить) приведет к шифрованию объекта ключем, индивидуальным для каждого пользователя. Т.е. это плохой вариант, если вы планируете отправлять письма со множества компьютеров - вам просто понадобится вводить эти данные у каждого пользователя.
Вы можете передать пароль обычным текстом, что решит проблему описанную выше:
$login = 'test@yandex.ru'
# Конвертируем пароль в защищенную строку
$password = 'password123' | ConvertTo-SecureString -AsPlainText -Force
# Создаем единый объект с логином и паролем
$cred = New-Object system.Management.Automation.PSCredential($login,$password)
Send-MailMessage -SmtpServer 'smtp.yandex.ru' -Port 465 -Credential $cred
Более подробно, про работу логинов и паролей в Powershell, описывалось в предыдущих статьях.
Как подставлять значения переменных в строках с Powershell
Отправка писем
Разобравшись с предыдущими параметрами мы можем отправить письмо. Дополнительно мы должны указать следующие параметры:
- UseSsl - так как наше подключение шифруется;
- From - ящик, с которого отправляется письмо;
- To - кому отправляем;
- Subject - тема письма;
- Body - содержание письма.
В моем случае команда будет выглядеть так:
$PSEmailServer = 'smtp.yandex.com'
$cred = Get-Credential
Send-MailMessage -Port 465 `
-From 'test@yandex.ru' `
-To 'test@yandex.ru' `
-Subject 'Тема письма' `
-Body 'Текст письма' `
-UseSsl `
-Credential $cred
Данная команда, в случая yandex и многих других, публичных, провайдеров вернет ошибку:
- Send-MailMessage : Не удается прочитать данные из транспортного соединения: net_io_connectionclosed.
Эта проблема связана с тем, что библиотека .NET SmtpClient, которая работает с командой Send-MailMessage, может использовать шифрование SSL/TLS только с поддержкой STARTTLS. Стандарт STARTTLS расширял возможности шифрования и должен был стать массовым, но этого не случилось (и скорее всего не случится). Во время публикации стандарта STARTTLS был объявлен новый порт для SMTP - 587(msa), а порт 465 (smtps) объявили устаревшим. Так как новый стандарт так и не приобрел массовость провайдеры, чаще всего, пишут только про 465 порт, но и 587 так же у многих провайдеров работает.
Подводя коротко итог предыдущего абзаца, если провайдер пишет про 465 порт, а он не работает - попробуйте 587. В случае с яндексом это именно так.
Так же, если вам нужно что бы у получателя выводилось ваше имя/название компании, используйте следующий формат во From:
-From 'Александр Мельников <test@yandex.ru>'
Несколько адресатов
Так же как и в случае обычного почтового клиента мы можем отправлять письма нескольким адресатам используя:
- To - обычный получатель;
- Cc - получатель копии;
- Bcc - получатель скрытой копии.
Если планируется использовать несколько почтовых ящиков, в одном параметре, разделяйте их запятыми:
$PSEmailServer = 'smtp.yandex.com'
$cred = Get-Credential
Send-MailMessage -Port 465 `
-From 'test@yandex.ru' `
-To 'test1@yandex.ru', 'test2@yandex.ru', `
-Bcc 'test3@yandex.ru', `
-Subject 'Тема письма' `
-Body 'Текст письма' `
-UseSsl `
-Credential $cred
Кодировка
Как вы знаете Windows пока не перевела работу ОС на UTF8 (используется ANSI и ASCII). В это же время UTF8 является стандартом для работы в интернете. По этой причине, если вы не укажете кодировку, то может получится следующая картина:
Отмечу, что это проблема возникнет в Powershell 5.1, которая установлена по умолчанию в Windows. В случае с Powershell 7.1, по умолчанию используется UTF8. Тем не менее вы можете установить свое значение:
- ASCII;
- BigEndianUnicode;
- Default;
- OEM;
- Unicode;
- UTF7;
- UTF8;
- UTF32.
Значения устанавливаются в параметре Encoding:
$PSEmailServer = 'smtp.yandex.com'
$cred = Get-Credential
Send-MailMessage -Port 465 `
-From 'test@yandex.ru' `
-To 'test1@yandex.ru', 'test2@yandex.ru', `
-Bcc 'test3@yandex.ru', `
-Subject 'Тема сообщения' `
-Body 'Текст письма' `
-UseSsl `
-Credential $cred `
-Encoding 'UTF8'
Отправка письма с разметкой HTML
Письма могут быть посланы как обычный текст или с HTML разметкой. Для разметки дополнительно к параметру Body нужно указать BodyAsHtml:
$body = '
<table style="width:100%">
<tr>
<th>Размер диска</th>
<th>100Мб</th>
<th>200Мб</th>
</tr>
</table>
'
$PSEmailServer = 'smtp.yandex.com'
$cred = Get-Credential
Send-MailMessage -Port 465 `
-From 'test@yandex.ru' `
-To 'test1@yandex.ru' `
-Subject 'Тема сообщения' `
-Body $body `
-BodyAsHtml `
-UseSsl `
-Credential $cred `
-Encoding 'UTF8'
Вложения
Вложения можно перечислить используя параметр Attachments и пути до файлов:
Send-MailMessage -Port 465 `
-From 'test@yandex.ru' `
-To 'test1@yandex.ru' `
-Subject 'Тема письма' `
-Body $body `
-UseSsl `
-Credential $cred `
-Encoding 'UTF8' `
-Attachments 'C:\pic1.jpg','C:\pic2.jpg'
Этот параметр так же принимает значения через конвейер т.е. мы можем получить все файлы в папке и отправить их:
Get-ChildItem -Path 'C:\Docs' | Send-MailMessage -Port 465 `
-From 'test@domain.local' `
-To 'test1@domain.local' `
-Subject 'Тема сообщения' `
-Body $body `
-UseSsl `
-Credential $cred `
-Encoding 'UTF8'
Уведомления о доставке
Мы можем получить уведомления, если установим следующие параметры у -DeliveryNotificationsOptions:
- OnSuccess - при успешной доставке;
- OnFailure - если сообщение не доставлено;
- Delay - при задержке SMTP сервером.
Через запятую их можно установить несколько:
Send-MailMessage -Port 465 `
-From 'test@domain.local' `
-To 'test1@domain.local' `
-Subject 'Тема' `
-Body $body `
-UseSsl `
-DeliveryNotificationsOptions 'OnSuccess', 'OnFailure'
Уведомление будет доставлено на почтовый ящик.
Приоритет
Вы можете установить приоритет, который увидит получатель письма. Отмечу, что такой приоритет отображается не во всех клиентах. Приоритет определяется в параметре Priority со значениями:
- Normal (по умолчанию)
- High
- Low
...
Подписывайтесь на наш Telegram канал
Теги: #powershell