Отсылка e-mail через C#
C# 14.06.2008
Этот кусок кода показывает, как можно программно отослать электронное письмо средствами C#. Письмо отсылается через указанный SMTP-сервер, который требует авторизацию. Так же к письму можно прикрепить одно или несколько вложений.
//Адрес SMTP-сервера
String smtpHost = "SMTP.SERVER.RU";
//Порт SMTP-сервера
int smtpPort = 25;
//Логин
String smtpUserName = "LOGIN";
//Пароль
String smtpUserPass = "PASSWORD";
//Создание подключения
SmtpClient client = new SmtpClient(smtpHost, smtpPort);
client.Credentials = new NetworkCredential(smtpUserName, smtpUserPass);
//Адрес для поля "От"
String msgFrom = "LOGIN@SERVER.RU";
//Адрес для поля "Кому" (адрес получателя)
String msgTo = "KUDA@TO.RU";
//Тема письма
String msgSubject = "Письмо от C#";
//Текст письма
String msgBody = "Привет!\r\n\r\nЭто тестовое письмо\r\n\r\n--\r\nС уважением, C# :-)";
//Вложение для письма
//Если нужно больше вложений, для каждого вложения создаем свой объект Attachment с нужным путем к файлу
Attachment attachData = new Attachment("D:\Тестовое вложение.zip");
//Создание сообщения
MailMessage message = new MailMessage(msgFrom, msgTo, msgSubject, msgBody);
//Крепим к сообщению подготовленное заранее вложение
message.Attachments.Add(attachData);
try
{
//Отсылаем сообщение
client.Send(message);
}
catch (SmtpException ex)
{
//В случае ошибки при отсылке сообщения можем увидеть, в чем проблема
Console.WriteLine(ex.InnerException.Message.ToString());
}
Тело письма и его заголовок будут созданы и отосланы в кодировке - UTF-8. Если же захочется отослать письмо в кодировке windows-1251, то начинаются проблемы. Мне удалось найти только одно достаточно подробное описание этой проблемы. И в более свежих версиях фреймворка (помимо .Net Framework 2.0) точно такая же проблема.
Да, отчасти помогает прописывание вручную заголовка, говорящего о кодировке всего письма, но с другой стороны, не так уж все радужно. Итак, перед кодом отсылки сообщения (после 29-ой строки) добавляем следующий код:
message.SubjectEncoding = Encoding.Default; message.BodyEncoding = Encoding.Default; message.Headers["Content-type"] = "text/plain; charset=windows-1251";
В итоге мы имеем письмо, у которого два раза (второй раз вставляется автоматом) повторяется заголовок Content-type, в первом указана кодировка windows-1251, а во втором настырный .Net вставляет UTF-8. Не думаю, что такое дублирование заголовков можно назвать корректным. Но это, похоже, единственный способ добиться какой-то адекватности отображения тела письма в почтовой программе, которая получит его.
Для просмотра писем я использую Mozilla Thunderbird. В нем тело письма отображается нормально, но при этом он не понимает кодировки заголовка письма и отображает его некорректно. Если оставить заголовок в кодировке UTF-8, а тело письма создавать в windows-1251:
message.BodyEncoding = Encoding.Default; message.Headers["Content-type"] = "text/plain; charset=windows-1251";
Тогда Thunderbird правильно отображает письмо. Но все эти ухищрения достаточно сомнительны из-за того, что каждый почтовый клиент может по-своему трактовать двойной и противоречивый заголовок Content-type. Так, к примеру, если посмотреть на такое письмо через вэбовский клиент mail.ru, то при любых раскладах тело письма отображается коряво. Тема же отображается правильно, только если отсылать ее в UTF-8.
Глядя на эту печальную картину, в голову приходит только два варианта решения проблемы. Плюнуть и отсылать письма в UTF-8 или же самостоятельно подключаться к SMTP-серверу и “вручную общаться” с ним по протоколу SMTP, а не использовать готовую реализацию в виде класса SmtpClient.

31.08.2008 в 23:06
Часть кода спамерской проги, очень полезно
01.09.2008 в 14:57
Хм, ну если все спамеры начнут вот так вот (с авторизацией через smtp сервер) рассылать письма, то возможно наступит золотой век и их всех можно будет легко обнаружить
Этим способом можно разве что какому-то кругу людей что-то рассылать, на что они дали согласие, и то, это мероприятие будет достаточно сомнительным. Куда прогрессивнее думать в сторону RSS, в таком случае…
12.11.2008 в 17:12
02.12.2008 в 03:15
Отправка через известные смтп сервера не поддерживается, тк они закрыты.. лучше поиши менее известные, тогда точно должна отсылка работать…вот этим пользуюсь gawab.com
17.02.2009 в 16:32
Неработает
String msgFrom = “LOGIN@SERVER.RU”;
пишет что недопустимый символ в електронной почте!
Что мне делать? И как правильно прописать електронную почту?
Заранее спасибо
26.02.2009 в 17:37
Добрый день!
Статья супер, но вот такой вопрос, а можно ли обойтись без сторонних серверов для отправки email сообщения?
05.03.2009 в 00:27
если добавить строку
message.Headers["Content-type"] = “text/plain; charset=windows-1251″;
и письмо содержит attachments, их содержимое определяется как обычный текст на некоторых клиентах (например в веб-интерфейсе rambler)
Заменил на
message.Headers["Content-type"] = “;сharset=windows-1251″;
Тогда аттачменты для всех клиентов, с которыми я работал отображаются корректно.
…и мое мнение: SmtpClient связывает разработчика по рукам и ногам! довольно скудный класс, предоставляющий минимальный интерфейс даже в методах protected! лучше сразу от него отказаться и использовать уже опенсоурсные смтп-клиенты
14.05.2009 в 01:13
У меня пишет : Недопустимый знак в заголовке электронной почты.
Что делать ?
19.05.2009 в 14:20
а у меня не авторизовывается, блин делал на C++ Builder все замечательно работало, но тему письма в нормаьный вид не смог привести а тут блин вообще лажа ни чего не работает, говорит подленность не пройдена, хотя все нормально работает на smtp.mail.ru я просто в шоке, немогу понят что такое.. может кто сталкивался…
ПС Пароль и логин я точно знаю и ввести его не правльно я не мог..
08.06.2009 в 12:35
Я тут сваял простенький отправлятель почты по SMTP
не обессудьте если что.
Но проверил - ВСЕ работает
вот выложил сюда больше под руку никуда не попалось
08.06.2009 в 13:32
yannik,
А исходники может кому и пригодились бы для обучения.
Извините, но ссылку я удалил, так как намного актуальнее были бы выложенные исходники (проект), а не exe файл. Ведь мало ли, может эта программка пароли куда-то еще шлет от мыла
01.09.2009 в 00:06
Уже лет пять пользуюсь своей процедурой рассылки. Работает идеально со всеми почтовиками, как в Win32 так и в Web
public static bool SendMail(string fromaddress, string toaddress, string subject, string messagestr)
{
System.Configuration.Configuration config = WebConfigurationManager.OpenWebConfiguration(HttpContext.Current.Request.ApplicationPath);
System.Net.Configuration.MailSettingsSectionGroup settings = (System.Net.Configuration.MailSettingsSectionGroup)config.GetSectionGroup(”system.net/mailSettings”);
MailAddress from;
if (settings.Smtp.From != null)
{
from = new MailAddress(fromaddress);
}
else
{
return false;
}
MailMessage message = new MailMessage();
message.From = from;
if (!toaddress.Contains(”;”))
{
message.To.Add(new MailAddress(toaddress));
}
else
{
foreach (string tAddress in toaddress.Split(new string[] { “;” }, StringSplitOptions.RemoveEmptyEntries))
{
if (tAddress != “”)
{
message.To.Add(new MailAddress(tAddress));
}
}
}
message.Subject = subject;
message.Body = messagestr;
message.BodyEncoding = System.Text.Encoding.GetEncoding(”KOI8-R”);
message.SubjectEncoding = System.Text.Encoding.GetEncoding(”KOI8-R”);
message.IsBodyHtml = true;
SmtpClient client = new SmtpClient();
System.Net.NetworkCredential authuser = new System.Net.NetworkCredential(settings.Smtp.Network.UserName, settings.Smtp.Network.Password);
client.Host = settings.Smtp.Network.Host;
if (MainClass.IsNumeric(settings.Smtp.Network.Port.ToString()))
{
client.Port = Convert.ToInt32(settings.Smtp.Network.Port);
}
else
{
client.Port = 25;
}
if (settings.Smtp.Network.UserName != string.Empty && settings.Smtp.Network.Password != string.Empty)
{
client.Credentials = authuser;
}
else
{
client.Credentials = System.Net.CredentialCache.DefaultNetworkCredentials;
}
client.Send(message);
return true;
}
23.11.2009 в 10:12
Я понимаю что торможу но, интересно насколько вот такое извращение, имеет право на жизнь:
class mrcEncoder:Encoding
{
private Encoding enc;
private mrcEncoder()
{}
public mrcEncoder(int codePage): base(codePage)
{
enc = Encoding.GetEncoding(codePage);
//this.codePage=codePage
}
public override string BodyName
{
get
{
if (base.CodePage == 1251) return “windows-1251″;
return base.BodyName;
}
}
public override int GetByteCount(char[] a, int b, int c)
{
return enc.GetByteCount(a, b, c);
}
public override int GetCharCount(byte[] a, int b, int c)
{
return enc.GetCharCount(a, b, c);
}
public override int GetChars(byte[] a, int b, int c,char [] d,int e)
{
return enc.GetChars(a, b, c,d,e);
}
public override int GetBytes(char[] a, int b, int c, byte[] d, int e)
{
return enc.GetBytes(a, b, c, d, e);
}
public override int GetMaxCharCount(int a)
{
return enc.GetMaxCharCount(a);
}
public override int GetMaxByteCount(int a)
{
return enc.GetMaxByteCount(a);
}
}
и соответственно
MailMessage mail = new MailMessage(”LOGIN@SERVER.RU”, “kuda@to.ru”);
mrcEncoder enc=new mrcEncoder(1251);
mail.SubjectEncoding = enc;
mail.Subject = “Письмо в win-1251″;
mail.BodyEncoding = enc;
mail.IsBodyHtml = false;
mail.Body = “Текст письма”;
SmtpClient snd = new SmtpClient(”SMTP.SERVER.RU”, 25);
snd.Send(mail);