Отправка почты SMTP (очередная сборка)

by Alexey Knyazev 7. апреля 2010 13:15

В очередной раз обращаюсь к работе с почтой через CLR-сборки. Я уже описывал, как читать почту по протоколу POP3 и IMAP. Теперь небольшая демонстрация, как отправлять почту через SMTP.

SMTP (англ. Simple Mail Transfer Protocol — простой протокол передачи почты) — это сетевой протокол, предназначенный для передачи электронной почты в сетях TCP/IP.

Для отправки почты в SQL Server 2005 и выше используется Компонент Database Mail.

Компонент Database Mail — это решение уровня предприятия для отправки сообщений электронной почты от компонента SQL Server Database Engine. Используя компонент Database Mail, приложения базы данных могут отправлять почтовые сообщения пользователям. Сообщения могут содержать результаты запроса, а также могут включать файлы из любого сетевого ресурса. Компонент Database Mail спроектирован для надежности, масштабируемости, безопасности и простой поддержки.

А я покажу простенький код сборки для отправки почты, не используя Database Mail.

Код сборки:

using System;
using System.Net;
using System.Net.Mail;

public class SMTPClr
{
    public static void SendMessage(string From, string To, string Subject, string Body, string Host, string UserName, string Password)
    {
        MailMessage mes = new MailMessage(From, To, Subject, Body);
        SmtpClient client = new SmtpClient(Host); 
        client.Credentials = new NetworkCredential(UserName, Password); 
        client.Send(mes);
    }
}

 

Вот и всё!!! Smile

Далее регистрируем сборку и отправляем тестовое письмо:

--Регистрируем сборку
CREATE ASSEMBLY SMTPCLR
FROM 'C:\SMTPClr\SMTPCLR.dll'
WITH PERMISSION_SET = EXTERNAL_ACCESS;
GO

--Создаём процедуру отправки почты
CREATE PROCEDURE SendMessage
(
--От кого
@From nvarchar(max),
--Кому
@To nvarchar(max),
--Тема письма
@Subject nvarchar(max),
--Само сообщение
@Body nvarchar(max),
--Имя сервера или его IP (порт 25)
@Host nvarchar(max),
--Имя пользователя
@UserName nvarchar(max),
--Пароль
@Password nvarchar(max)
) 
AS 
EXTERNAL NAME SMTPCLR.SMTPClr.SendMessage
GO

--Отправляем письмо
EXECUTE SendMessage 'admin@microsoft.com', 'a.knyazev@t-sql.ru', 'SMTPClr', 'Hi, Alexey!', 'MySMTPServer', 'MySMTPUserName', 'MySMTPPassword'

И не забываем предварительно включить возможность работы с CLR-сборками:

--Включаем выполнение пользовательских сборок
SP_CONFIGURE 'clr enabled', 1
GO
RECONFIGURE
GO


--Модули базы данных (например, пользовательские функции или хранимые процедуры),
--которые используют контекст олицетворения, могут обращаться к ресурсам,
--находящимся вне базы данных.
ALTER DATABASE [Ваша БД] SET TRUSTWORTHY ON
GO


По просьбе трудящихся, выкладываю саму сборку сюда: SMTPCLR.zip

Tags: ,

SQL Server

Комментарии (20) -

Vlad
Vlad Russia
08.04.2010 22:32:57 #

Это все конечно хорошо, но нужно понимать, что произойдет если, например, сделать бекап и восстановление БД. Отправка писем не заработает.По моему мнению для надежной работы лучше использовать Database Mail. А если вы знаете тонкости настроек CLR сборок, то конечно удобно использовать CLR сборку.

Reply

Admin
Admin Russia
09.04.2010 12:14:33 #

Цель данной заметки не убедить, что отправка почты через сборку лучше, чем Database Mail, а показать возможные альтернативы, а так же продемонстрировать в очередной раз, как с помощью нескольких строк расширить стандартный функционал SQL Server

Reply

Oleg
Oleg Russia
14.04.2010 20:14:52 #

А как можно посмотреть все зарегистрированные сборки? Или это нельзя сделать?

Reply

Admin
Admin Russia
14.04.2010 21:51:39 #

SELECT * FROM sys.assemblies

Reply

Роман
Роман Ukraine
21.09.2010 0:18:11 #

У меня не получается отправить СМС на моб.телефон с помощью этой компоненты. Приходит абракадабра. Догадуюсь, что надо как то перекодировать в gsm38 но как это сделать мыслей нет.

Reply

Alexey Knyazev
Alexey Knyazev Russia
22.09.2010 21:17:14 #

msdn.microsoft.com/.../...essage.bodyencoding.aspx можно задать кодировку через BodyEncoding

Reply

Роман
Роман Ukraine
20.10.2010 21:44:01 #

не совсем понял, можно подробнее?
мне нужно сменить кодировку тела письма(по умолчанию оно в utf-8)

Reply

Alexey Knyazev
Alexey Knyazev Russia
20.10.2010 22:28:21 #

Да, подправте мой код, думаю дело именно в кодировке

Reply

Роман
Роман Ukraine
21.10.2010 19:29:54 #

Не получается выполнить код:
CREATE ASSEMBLY SMTPCLR
03  FROM 'C:\SMTPClr\SMTPCLR.dll'
04  WITH PERMISSION_SET = EXTERNAL_ACCESS;
05  GO
ругается что, CREATE ASSEMBLY failed because it could not open the physical file "c:\Temp\SMTPClr\SMTPClr.dll": 3(Системе не удается найти указанный путь.).
но файл там лежит точно!
Все, права что в Винде, что разрешения в самом SQL Server'e настроены.

Reply

Alexey Knyazev
Alexey Knyazev Russia
21.10.2010 22:05:31 #

Под кем стартует сам SQL Server? У этой УЗ есть доступ к этой дирректории?

Reply

Роман
Роман Ukraine
22.10.2010 3:47:06 #

На домашнем компе попробывал(на работе походу, что-то с правами намучено), процедура создалась нормально, но при отправке след. ругань:

Msg 6522, Level 16, State 1, Procedure SendMessage, Line 0
A .NET Framework error occurred during execution of user defined routine or aggregate 'SendMessage':
System.Net.Mail.SmtpException: Failure sending mail. ---> System.FormatException: An invalid character was found in the mail header.
System.FormatException:
   at System.Net.BufferBuilder.Append(String value, Int32 offset, Int32 count)
   at System.Net.Mail.EHelloCommand.PrepareCommand(SmtpConnection conn, String domain)
   at System.Net.Mail.EHelloCommand.Send(SmtpConnection conn, String domain)
   at System.Net.Mail.SmtpConnection.GetConnection(String host, Int32 port)
   at System.Net.Mail.SmtpTransport.GetConnection(String host, Int32 port)
   at System.Net.Mail.SmtpClient.GetConnection()
   at System.Net.Mail.SmtpClient.Send(MailMessage message)
System.Net.Mail.SmtpException:
   at System.Net.Mail.SmtpClient.Send(MailMessage message)
   at SMTPClr.SendMessage(String From, String To, String Subject, String Body, String Host, String UserName, String Password)

Reply

Alexey Knyazev
Alexey Knyazev Russia
23.10.2010 1:53:48 #

--Модули базы данных (например, пользовательские функции или хранимые процедуры),
--которые используют контекст олицетворения, могут обращаться к ресурсам,
--находящимся вне базы данных.
ALTER DATABASE [Ваша БД] SET TRUSTWORTHY ON
GO

Reply

Роман
Роман Ukraine
25.10.2010 2:50:58 #

Не, причина была не в этом. А в кирилических символах в заголовке. Сначала обходил это с помощью возножности - сменить язык системы(Win7) на english. А потом прочел, что такое возможно из-за кирилического названия компа. Переименовал и все получилось! Спасибо Вам!

Reply

Константин
Константин Russia
15.11.2010 23:33:26 #

Алексей, был бы очень сильно признателен ,если вышлите скомпилированную сборку SMTPCLR.dll
на timpost@bk.ru

Reply

Alexey Knyazev
Alexey Knyazev Russia
16.11.2010 23:45:02 #

Качайте: http://www.t-sql.ru/Tools/SMTPCLR.zip

Reply

Константин
Константин Russia
17.11.2010 17:29:30 #

Спасибо!

Reply

Oleg
Oleg Russia
18.10.2012 14:02:40 #

поясните, пожалуйста, а как этой компонентой можно рассылать СМС??
спасибо

Reply

Alexey Knyazev
Alexey Knyazev Russia
13.11.2012 16:14:12 #

многие операторы поддерживают сервис mail-to-sms, т.е. отсылка коротких сообщений на телефон ничем не отличается от обычного почтового сообщения
для "большой тройки" это письма на адреса в виде:
79ххххххххх@megafonural.ru
79xxxxxxxxx@sms.beemail.ru
79xxxxxxxxx@sms.mts.ru

но данная услуга должна быть включена у конечного адресата (абонента), т.к. по умолчанию любые сообщения через smtp блокируются

Reply

Михаил
Михаил Russia
18.12.2012 8:39:59 #


.Сообщение 6522, уровень 16, состояние 1, процедура SendMessage, строка 0
Произошла ошибка .NET Framework во время выполнения определяемой пользователем подпрограммы или агрегатной функции "SendMessage":
System.Net.Mail.SmtpException: Сбой при отправке сообщения электронной почты. ---> System.Net.WebException: Невозможно соединиться с удаленным сервером ---> System.Net.Sockets.SocketException: Сделана попытка доступа к сокету методом, запрещенным правами доступа 74.125.143.108:25
System.Net.Sockets.SocketException:
   в System.Net.Sockets.Socket.DoConnect(EndPoint endPointSnapshot, SocketAddress socketAddress)
   в System.Net.ServicePoint.ConnectSocketInternal(Boolean connectFailure, Socket s4, Socket s6, Socket& socket, IPAddress& address, ConnectSocketState state, IAsyncResult asyncResult, Int32 timeout, Exception& exception)
System.Net.WebException:
   в System.Net.ServicePoint.GetConnection(PooledStream PooledStream, Object owner, Boolean async, IPAddress& address, Socket& abortSocket, Socket& abortSocket6, Int32 timeout)
   в System.Net.PooledStream.Activate(Object owningObject, Boolean async, Int32 timeout, GeneralAsyncDelegate asyncCallback)
   в System.Net.PooledStream.Activate(Object owningObject, GeneralAsyncDelegate asyncCallback)
   в System.Net.ConnectionPool.GetConnection(Object owningObject, GeneralAsyncDelegate asyncCallback, Int32 creationTimeout)
   в System.Net.Mail.SmtpConnection.GetConnection(String host, Int32 port)
   в System.Net.Mail.SmtpClient.Send(MailMessage message)
System.Net.Mail.SmtpException:
   в System.Net.Mail.SmtpClient.Send(MailMessage message)
   в SMTPClr.SendMessage(String From, String To, String Subject, String Body, String Host, String UserName, String Password)

Reply

Alexey Knyazev
Alexey Knyazev Russia
26.04.2013 13:36:00 #

Пример на PowerShell:

$Server = "192.168.1.1"
#$SmtpServerPort = "999"
#$SmtpUser = "username"
#$SmtpPass = "password"
$From = "user@mail.ru"
$To = "user1@mail.ru, user2@mail.ru"
$Subject = "Test"
$Body = "<table border=1><tr><td>Раз</td><td>Два</td></tr><tr><td><font color=""red"">PowerShell</font></td><td><b>РУЛИТ!!!</b></td></tr></table>"
$SmtpClient = New-Object System.Net.Mail.SmtpClient
$Message = New-Object System.Net.Mail.MailMessage
$SmtpClient.Host = $Server
#$SmtpClient.Port = $SmtpServerPort
$Message.From = $From
$Message.To.Add($To)
$Message.Subject = $Subject
$Message.Body = $Body
$SMTPClient.EnableSsl = $true
$Message.IsBodyHTML = $true
#$SMTPClient.Credentials = New-Object System.Net.NetworkCredential( $emailSmtpUser , $emailSmtpPass );
$SmtpClient.Send($Message)
Write-Host "Complete!"
$Message.Dispose()

Reply

Добавить комментарий

  Country flag

biuquote
  • Комментарий
  • Предпросмотр
Loading