Database Mail: Почтовые рассылки прямо из Microsoft SQL ServerИсточник: habrahabr CodeDriller
Многие знают, что начиная с версии 2005 в SQL Server существует встроенная возможность посылать электронные письма, которую администраторы баз данных часто используют для отправки срочных оповещений, например, при сбое задач, выполняемых по расписанию. Однако лишь немногим известно, что посылать письма в SQL Server можно прямо из SQL-запросов, функций и хранимых процедур. И если вы один раз уже настроили почту в SQL Server, то на отправку письма у вас уйдет всего минута, а целую рассылку можно организовать за 15-20 минут. Называется эта система Database Mail (DBMail), и сегодня я хотел бы поделиться опытом ее использования. НастройкаПеред работой с DBMail нужно сначала включить систему и прописать в ней почтовый аккаунт (SMTP), с которого будут рассылаться письма. Работать с IMAP система, к сожалению, не умеет, но это в подавляющем большинстве случаев и не нужно. Я, в свою очередь, покажу сейчас альтернативный вариант: как произвести настройку программно, через SQL-скрипт. Этот вариант не так нагляден, но он быстрее и будет удобнее тем, кому нужно производить настройку DBMail на многих серверах или переносить настройки с сервера на сервер, в этом случае будет достаточно просто запустить этот скрипт на новом сервере. Важно только не забыть, что для использования нижеследующих скриптов нужно войти на сервер как член группы sysadmin, иначе система безопасности укажет на недостаток прав. Перейдем сразу к делу. Вот скрипт, подготавливающий сервер для использования DBMail: Очень массовые почтовые рассылки рекомендуется производить с ящика частного домена. При попытке рассылки с ящиков публичных доменов (ящиков на yandex.ru, mail.ru, gmail.com и т. д.) SMTP-серверы могут счесть вас спамером и заблокировать рассылку или даже весь ящик.
БрандмауэрНепосредственной отправкой писем в SQL Server будет заниматься отдельная программа. В разных версиях SQL Server она называется "DatabaseMail90.exe" или "DatabaseMail.exe" и по умолчанию располагается в папке "C:\Program Files\Microsoft SQL Server\...\MSSQL\Binn\". Важно не забыть разрешить для нее исходящий трафик в брандмауэре (файрволе).
Тестовое письмоПора попробовать, все ли в порядке. Осуществить отправку тестового письма может любой пользователь из группы sysadmin, владелец базы (db_owner) MSDB или пользователь с ролью DatabaseMailUserRole. Для добавления пользователю роли DatabaseMailUserRole используется стандартная процедура sp_addrolemember: sp_addrolemember @rolename = 'DatabaseMailUserRole', @membername = '<имя_пользователя>'; Теперь отправим тестовое письмо: EXEC msdb.dbo.sp_send_dbmail -- Созданный нами профиль администратора почтовых рассылок @profile_name = 'MySite Admin Mailer', -- Адрес получателя @recipients = 'friend@mysite.ru', -- Текст письма @body = N'Испытание системы SQL Server Database Mail', -- Тема @subject = N'Тестовое сообщение', -- Для примера добавим к письму результаты произвольного SQL-запроса @query = 'SELECT TOP 10 name FROM sys.objects'; Дополнительные параметры процедуры sp_send_dbmail можно посмотреть в ее описании в MSDN. Если что-то не в порядке, сначала нужно посмотреть на статус письма: Успешно отправленные письма можно посмотреть таким SQL-запросом: Почтовая рассылкаТеперь предположим, что администратору сайта MySite.ru нужно выбрать из таблицы пользователей своего сайта тех, кто не заходил на сайт более года, и отправить им приглашения. Мы специально возьмем настоящую жизненную ситуацию, чтобы продемонстрировать больше возможностей DBMail и SQL, включая курсоры и циклы. Для усложнения задачи добавим еще несколько условий:
-- Используем условную базу данных mysite USE mysite GO -- Объявим переменные: идентификатор пользователя, имя, -- дата последнего входа на сайт, почтовый адрес DECLARE @user_id int, @user_name nvarchar(255), @last_login_date smalldatetime, @email_address varchar(255); -- Переменная @body будет содержать текст письма в формате HTML DECLARE @body nvarchar(MAX); -- Переменная @no_mail будет обозначать пользователей, отказавшихся от рассылок DECLARE @no_mail int; -- Объявим курсор базы данных, курсор обязательно должен быть локальным -- Для большей скорости также укажем параметр курсора FAST_FORWARD DECLARE users CURSOR LOCAL FAST_FORWARD FOR SELECT id, name, last_login_date, email_address FROM users WHERE user_role IN (3,4,5) AND account_state = 2 AND email_address IS NOT NULL AND DATEDIFF(day, last_login_date, GETDATE()) > 365 ORDER BY id -- Пусть данная рассылка начнется не сейчас, а в 3 часа ночи WAITFOR TIME '03:00:00' -- Открываем курсор users OPEN users -- Возьмем первый ряд выборки из курсора FETCH NEXT FROM users INTO @user_id, @user_name, @last_login_date, @email_address -- Запустим цикл до конца выборки WHILE @@FETCH_STATUS = 0 BEGIN -- Определим, не отказался ли пользователь от рассылок SET @no_mail = (SELECT id FROM users WHERE id = @user_id AND allow_mail = 0) -- Если отказался, то перейдем к следующему пользователю IF @no_mail IS NOT NULL BEGIN PRINT N'Пользователь ' + @user_name + N' отказался от рассылок.' FETCH NEXT FROM users INTO @user_id, @user_name, @last_login_date, @email_address CONTINUE END PRINT N'Отправка письма для ' + @email_address + N' ...' -- Сформируем текст письма SET @body = N' <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <title>Приглашение</title> </head> <body> <p><img style="float:right;" src="http://mysite.ru/images/logo.png"/></p> <p>Здравствуйте, ' + @user_name + N'!</p> <p>Приглашаем Вас снова посетить сайт MySite.ru. У нас появилось много новых интересных функций, обновилось содержание, и мы приложили много усилий для повышения удобства Вашей работы с сайтом.</p> <p>Желаем успехов!</p> <p>С уважением, администрация сайта MySite.ru</p> </body> </html>'; -- Отправим письмо EXEC msdb.dbo.sp_send_dbmail @recipients = @email_address, @subject = N'Приглашаем Вас снова посетить сайт MySite.ru', @body = @body, -- Формат письма может быть либо 'HTML', либо 'TEXT' @body_format = 'HTML', -- При необходимости к письму можно прикрепить файл --@file_attachments ='C:\attachment.jpg', -- Можно также указать адрес для направления копии --@copy_recipients ='me@gmail.com', -- "Blind copy" или "carbon copy" - так называют копии письма, -- получатели которых не видят адресов получателей других копий --@blind_copy_recipients ='me2@gmail.com', -- Укажем созданный ранее профиль администратора почтовых рассылок @profile_name = 'MySite Admin Mailer'; -- Установим интервал в 3 секунды между письмами, чтобы не перегружать SMTP-сервер WAITFOR DELAY '00:00:03'; -- В конце цикла берем следующую запись из курсора FETCH NEXT FROM users INTO @user_id, @user_name, @last_login_date, @email_address END -- Закрываем курсор базы данных CLOSE users GO Всё готово. Можно идти отдыхать. |