MailKit для C# (.NET): полное руководство с примерами

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

MailKit для C# (.NET): полное руководство с примерами

1. Что это и зачем нужна

MailKit — это мощная, кроссплатформенная библиотека с открытым исходным кодом для работы с электронной почтой в экосистеме .NET. Она предоставляет полный набор инструментов для создания, отправки, получения и обработки email-сообщений. В отличие от устаревшей System.Net.Mail, MailKit предлагает современный API, полную поддержку MIME (Multipurpose Internet Mail Extensions), работу с S/MIME и OpenPGP, а также асинхронные операции, что критически важно для высоконагруженных приложений.

Зачем нужна MailKit? Если вы разрабатываете на C# и сталкиваетесь с необходимостью отправлять email с вложениями, парсить входящие письма, работать с разными почтовыми протоколами (SMTP, POP3, IMAP) или обрабатывать сложные форматы писем (HTML, вложения, подписи), — MailKit станет вашим незаменимым инструментом. Она используется в production-среде тысячами компаний, включая Microsoft (в некоторых внутренних сервисах), и поддерживает .NET Framework, .NET Core, .NET 5+ и даже Xamarin/MAUI.

Ключевые преимущества MailKit перед аналогами: полная поддержка последних стандартов email (RFC 2045-2049, RFC 2822, RFC 5322), встроенная поддержка SSL/TLS, работа с прокси, потоковая обработка больших вложений и высокая производительность благодаря использованию System.IO.Pipelines и async/await.

2. Установка

MailKit устанавливается через менеджер пакетов NuGet. Выполните одну из следующих команд в консоли диспетчера пакетов (Package Manager Console) или в терминале .NET CLI:

// Через .NET CLI
dotnet add package MailKit

// Через Package Manager Console
Install-Package MailKit

// Или через NuGet Package Manager в Visual Studio
// Найдите "MailKit" и установите последнюю стабильную версию

После установки в проект будет добавлена зависимость от MimeKit (базовая библиотека для работы с MIME-сообщениями) — она устанавливается автоматически как транзитивная зависимость.

3. Быстрый старт — минимальный рабочий пример

Ниже приведен минимальный пример отправки простого текстового письма через SMTP-сервер Gmail. Обратите внимание: для работы с Gmail необходимо использовать пароль приложения (App Password) или OAuth 2.0.

using MailKit.Net.Smtp;
using MimeKit;

// Создаем сообщение
var message = new MimeMessage();
message.From.Add(new MailboxAddress("Отправитель", "sender@gmail.com"));
message.To.Add(new MailboxAddress("Получатель", "recipient@example.com"));
message.Subject = "Тестовое письмо из MailKit";
message.Body = new TextPart("plain") { Text = "Привет! Это тестовое сообщение." };

// Отправляем через SMTP
using (var client = new SmtpClient())
{
    client.Connect("smtp.gmail.com", 587, SecureSocketOptions.StartTls);
    client.Authenticate("sender@gmail.com", "your-app-password");
    client.Send(message);
    client.Disconnect(true);
}

Console.WriteLine("Письмо отправлено!");

4. Основные методы/функции/классы

4.1. SmtpClient.Connect()

Сигнатура: Task ConnectAsync(string host, int port, SecureSocketOptions options, CancellationToken cancellationToken = default)

Что делает: Устанавливает соединение с SMTP-сервером. Параметр SecureSocketOptions определяет тип шифрования: None, Auto, SslOnConnect, StartTls.

using var client = new SmtpClient();
await client.ConnectAsync("smtp.mail.ru", 465, SecureSocketOptions.SslOnConnect);

4.2. SmtpClient.Authenticate()

Сигнатура: Task AuthenticateAsync(string userName, string password, CancellationToken cancellationToken = default)

Что делает: Аутентифицирует пользователя на SMTP-сервере. Поддерживает SASL-механизмы (LOGIN, PLAIN, CRAM-MD5 и др.).

await client.AuthenticateAsync("user@example.com", "password");

4.3. SmtpClient.Send()

Сигнатура: Task SendAsync(MimeMessage message, CancellationToken cancellationToken = default, ITransferProgress progress = null)

Что делает: Отправляет подготовленное MIME-сообщение. Возвращает уникальный идентификатор письма (Message-Id).

var response = await client.SendAsync(message);
Console.WriteLine($"Письмо отправлено. ID: {response}");

4.4. ImapClient.Inbox.Open()

Сигнатура: Task OpenAsync(FolderAccess access, CancellationToken cancellationToken = default)

Что делает: Открывает папку "Входящие" (Inbox) с указанным уровнем доступа (ReadOnly или ReadWrite).

using var imap = new ImapClient();
await imap.ConnectAsync("imap.gmail.com", 993, SecureSocketOptions.SslOnConnect);
await imap.AuthenticateAsync("user@gmail.com", "password");
var inbox = imap.Inbox;
await inbox.OpenAsync(FolderAccess.ReadOnly);
Console.WriteLine($"Всего писем: {inbox.Count}");

4.5. IMailFolder.GetMessage()

Сигнатура: Task GetMessageAsync(UniqueId uid, CancellationToken cancellationToken = default)

Что делает: Загружает полное MIME-сообщение по его уникальному идентификатору (UID).

var uid = new UniqueId(12345);
var message = await inbox.GetMessageAsync(uid);
Console.WriteLine($"Тема: {message.Subject}");

4.6. MimeMessage.BodyParts

Сигнатура: Свойство IList BodyParts { get; }

Что делает: Возвращает коллекцию всех частей тела письма (текст, HTML, вложения). Позволяет итерировать и обрабатывать каждую часть.

foreach (var part in message.BodyParts)
{
    if (part is TextPart textPart)
        Console.WriteLine($"Текст: {textPart.Text}");
    if (part is MimePart mimePart && mimePart.IsAttachment)
        Console.WriteLine($"Вложение: {mimePart.FileName}");
}

4.7. TextPart и Multipart

Сигнатура: TextPart(string mediaSubtype) и Multipart(string mediaSubtype)

Что делает: TextPart представляет текстовую часть письма (plain text или HTML). Multipart — контейнер для нескольких частей (например, текст + вложение).

var body = new Multipart("mixed");
body.Add(new TextPart("plain") { Text = "Текст письма" });
body.Add(new MimePart("application", "pdf")
{
    Content = new MimeContent(File.OpenRead("document.pdf")),
    FileName = "document.pdf"
});
message.Body = body;

4.8. MailboxAddress

Сигнатура: MailboxAddress(string name, string address)

Что делает: Создает объект, представляющий email-адрес с отображаемым именем. Используется в полях From, To, Cc, Bcc.

message.From.Add(new MailboxAddress("Иван Иванов", "ivan@example.com"));
message.To.Add(new MailboxAddress("Петр Петров", "petr@example.com"));

4.9. HeaderList

Сигнатура: Свойство HeaderList Headers { get; }

Что делает: Предоставляет доступ к заголовкам письма. Позволяет добавлять, изменять или читать кастомные заголовки.

message.Headers.Add("X-Custom-Header", "my-value");
string replyTo = message.Headers["Reply-To"];

4.10. Pop3Client.GetMessage()

Сигнатура: Task GetMessageAsync(int index, CancellationToken cancellationToken = default)

Что делает: Загружает сообщение с POP3-сервера по его порядковому номеру (начиная с 0).

using var pop3 = new Pop3Client();
await pop3.ConnectAsync("pop.gmail.com", 995, SecureSocketOptions.SslOnConnect);
await pop3.AuthenticateAsync("user@gmail.com", "password");
var message = await pop3.GetMessageAsync(0);
Console.WriteLine($"Первое письмо: {message.Subject}");
await pop3.DisconnectAsync(true);

5. Реальный практический пример (100-200 строк кода)

Ниже представлен полноценный пример приложения, которое подключается к IMAP-серверу, сканирует папку "Входящие", находит письма с определенной темой, скачивает все вложения и отправляет отчет на указанный email.

using MailKit;
using MailKit.Net.Imap;
using MailKit.Net.Smtp;
using MailKit.Search;
using MimeKit;

class EmailProcessor
{
    private const string ImapHost = "imap.example.com";
    private const int ImapPort = 993;
    private const string SmtpHost = "smtp.example.com";
    private const int SmtpPort = 587;
    private const string UserName = "user@example.com";
    private const string Password = "your-password";
    private const string ReportEmail = "admin@example.com";

    public async Task ProcessInboxAsync()
    {
        // 1. Подключаемся к IMAP
        using var imap = new ImapClient();
        await imap.ConnectAsync(ImapHost, ImapPort, SecureSocketOptions.SslOnConnect);
        await imap.AuthenticateAsync(UserName, Password);
        var inbox = imap.Inbox;
        await inbox.OpenAsync(FolderAccess.ReadOnly);

        // 2. Ищем письма с темой "Invoice" за последние 7 дней
        var query = SearchQuery.SubjectContains("Invoice")
                    .And(SearchQuery.DeliveredAfter(DateTime.UtcNow.AddDays(-7)));
        var uids = await inbox.SearchAsync(query);
        Console.WriteLine($"Найдено писем: {uids.Count}");

        var attachmentsDir = Path.Combine(Directory.GetCurrentDirectory(), "attachments");
        Directory.CreateDirectory(attachmentsDir);
        var downloadedFiles = new List();

        // 3. Обрабатываем каждое письмо
        foreach (var uid in uids)
        {
            var message = await inbox.GetMessageAsync(uid);
            Console.WriteLine($"Обработка: {message.Subject} от {message.Date}");

            // Сохраняем вложения
            foreach (var attachment in message.Attachments)
            {
                if (attachment is MimePart mimePart)
                {
                    var fileName = mimePart.FileName ?? $"attachment_{Guid.NewGuid()}.bin";
                    var filePath = Path.Combine(attachmentsDir, fileName);
                    using var stream = File.Create(filePath);
                    await mimePart.Content.DecodeToAsync(stream);
                    downloadedFiles.Add(filePath);
                    Console.WriteLine($"Сохранено: {filePath}");
                }
            }
        }

        await imap.DisconnectAsync(true);

        // 4. Отправляем отчет
        if (downloadedFiles.Count > 0)
        {
            await SendReportAsync(downloadedFiles);
        }
    }

    private async Task SendReportAsync(List files)
    {
        var message = new MimeMessage();
        message.From.Add(new MailboxAddress("Email Processor", UserName));
        message.To.Add(new MailboxAddress("Admin", ReportEmail));
        message.Subject = $"Отчет: обработано {files.Count} вложений";

        var body = new TextPart("plain")
        {
            Text = $"Были загружены следующие файлы:\n{string.Join("\n", files)}"
        };

        using var client = new SmtpClient();
        await client.ConnectAsync(SmtpHost, SmtpPort, SecureSocketOptions.StartTls);
        await client.AuthenticateAsync(UserName, Password);
        await client.SendAsync(message);
        await client.DisconnectAsync(true);

        Console.WriteLine("Отчет отправлен.");
    }

    public static async Task Main()
    {
        var processor = new EmailProcessor();
        await processor.ProcessInboxAsync();
    }
}

6. Советы по производительности и типичные ошибки

Советы по производительности

  • Всегда используйте асинхронные методы (ConnectAsync, SendAsync и т.д.). Это особенно важно для серверных приложений, чтобы не блокировать потоки.
  • Повторно используйте SMTP-клиент для отправки нескольких писем. Создание нового подключения для каждого письма — дорогая операция. Используйте пул соединений или один экземпляр SmtpClient.
  • Используйте потоковую обработку для больших вложений. Вместо загрузки всего вложения в память, используйте Content.DecodeToAsync(stream) для записи напрямую в файл.
  • Ограничивайте количество одновременных подключений к IMAP/POP3. Большинство почтовых серверов имеют лимиты (обычно 10-20 одновременных соединений).
  • Кэшируйте UniqueId писем, чтобы не сканировать всю папку каждый раз. Используйте IMailFolder.Fetch() для выборочной загрузки только нужных полей.

Типичные ошибки

  • Игнорирование SSL-сертификатов: Никогда не используйте client.ServerCertificateValidationCallback = (

Рекомендаций