Гид по технологиям

Отправка писем в Go через net/smtp

6 min read Backend Обновлено 29 Dec 2025
Отправка писем в Go через net/smtp
Отправка писем в Go через net/smtp

Фото эмодзи сообщения на стене

Введение

Иногда нужно автоматически отправлять письма из программы — для подтверждений, уведомлений, отчётов или аутентификации. SMTP (Simple Mail Transfer Protocol) — стандарт для отправки электронной почты между серверами, а IMAP/POP3 — для получения. Go включает базовую поддержку SMTP в пакете net/smtp и дополнительно использует TLS и стандартную криптографию для безопасного соединения.

Важно: net/smtp предоставляет низкоуровневые инструменты — для сложных сценариев массовых рассылок или удобной обработки HTML/вложений лучше рассмотреть внешние библиотеки или сервисы.

Что нужно знать перед началом

  • Понимание SMTP: отправитель, получатель, хост (сервер), порт и тело сообщения.
  • Учетная запись почты и пароль приложения (app password) для провайдеров, требующих отдельный пароль для внешних клиентов (например, Yahoo).
  • Доступ к порту и хосту SMTP у вашего MSP (Mail Service Provider).

Определения:

  • SMTP: протокол отправки писем между серверами.
  • TLS: шифрование транспортного уровня, защищает соединение.

TL;DR кода

Привожу компактную рабочую реализацию SendMail() для отправки простого текстового письма через SMTP с TLS.

package main

import (
    "crypto/tls"
    "fmt"
    "log"
    "net/smtp"
)

func main() {
    fmt.Println(SendMail())
}

func SendMail() string {
    from := "youremail@yahoo.com"
    password := "yourAppPasswordHere"
    to := "recipient@example.com"

    host := "smtp.mail.yahoo.com"
    port := "465"
    serverAddress := host + ":" + port

    subject := "Пример: проверка отправки"
    body := "Здравствуйте! Это тестовое письмо, отправленное с Go." 

    // Заголовки
    headers := make(map[string]string)
    headers["From"] = from
    headers["To"] = to
    headers["Subject"] = subject

    message := ""
    for k, v := range headers {
        message += fmt.Sprintf("%s: %s\r\n", k, v)
    }
    message += "\r\n" + body

    // Аутентификация
    auth := smtp.PlainAuth("", from, password, host)

    // TLS-конфигурация
    tlsConfig := &tls.Config{
        InsecureSkipVerify: true, // В production рекомендуется проверить сертификат сервера
        ServerName:         host,
    }

    // Установка TCP/TLS соединения
    conn, err := tls.Dial("tcp", serverAddress, tlsConfig)
    if err != nil {
        log.Panic(err)
    }

    client, err := smtp.NewClient(conn, host)
    if err != nil {
        log.Panic(err)
    }

    // Аутентификация на SMTP-сервере
    if err = client.Auth(auth); err != nil {
        log.Panic(err)
    }

    // Отправитель и получатель
    if err = client.Mail(from); err != nil {
        log.Panic(err)
    }
    if err = client.Rcpt(to); err != nil {
        log.Panic(err)
    }

    // Запись тела письма
    w, err := client.Data()
    if err != nil {
        log.Panic(err)
    }
    _, err = w.Write([]byte(message))
    if err != nil {
        log.Panic(err)
    }
    if err = w.Close(); err != nil {
        log.Panic(err)
    }

    // Закрываем соединение корректно
    if err = client.Quit(); err != nil {
        log.Panic(err)
    }

    return "Успешно: письмо отправлено"
}

Важно: в примере InsecureSkipVerify=true — это удобство для тестов и локальной отладки. В продакшне нужно валидировать сертификат сервера или использовать доверенный корневой сертификат.

Разбор ключевых частей решения

  1. Импорты
  • crypto/tls — конфигурация TLS для защищённого соединения.
  • net/smtp — базовый SMTP-клиент.
  • log, fmt — для логирования и форматирования.
  1. Заголовки и тело

SMTP ожидает текст сообщения с заголовками в формате “Header: Value” и пустой строкой перед телом. Наш код собирает map[string]string заголовков и формирует message.

  1. Аутентификация

smtp.PlainAuth идентифицирует клиента. Аргументы: identity (можно пустой), username (обычно адрес), password, host.

  1. TLS + Dial

Многие провайдеры требуют шифрование на уровне транспорта. Мы создаём tls.Config с ServerName и устанавливаем соединение через tls.Dial.

  1. smtp.NewClient

Нужен для выполнения SMTP-команд: Auth, Mail, Rcpt, Data, Quit.

  1. Ошибки

Каждый шаг должен проверяться. Для продакшна вместо log.Panic используйте более мягкую обработку — повторные попытки (retry), логирование в систему мониторинга или отчёт об ошибке.

Настройка для Yahoo (и других провайдеров)

  • Для Yahoo: нужно создать пароль приложения в Account Security → Generate app password. Этот пароль используется вместо основного пароля аккаунта в коде.

Интерфейс генерации пароля приложения Yahoo

  • Хост и порт Yahoo в примере: smtp.mail.yahoo.com:465 (порт 465 — SMTPS по TLS). Провайдеры могут использовать другие порты: 587 (STARTTLS) или 25.

  • Gmail: Google ограничил «менее безопасные приложения». Для Gmail используйте OAuth2 или пароль приложения при включённом 2FA.

Отправка нескольким получателям и массив адресов

Если нужно отправлять письма группе получателей, используйте срез строк и вызов client.Rcpt для каждого адреса.

Пример:

recipients := []string{"a@example.com", "b@example.com"}
for _, rcpt := range recipients {
    if err = client.Rcpt(rcpt); err != nil {
        log.Panic(err)
    }
}

Когда net/smtp не подходит (примеры)

  • Нужна отправка HTML с вложениями и многоформатная обработка — net/smtp требует ручной сборки MIME-частей.
  • Массовые рассылки с отслеживанием и аналитикой — лучше сервисы типа SendGrid, Mailgun или SMTP API провайдеров.
  • Аутентификация по OAuth2 (например, Gmail API): net/smtp с PlainAuth не покрывает OAuth2.

Альтернативные подходы

  • Использовать готовые Go-библиотеки: gomail (github.com/go-gomail/gomail), mailgun-go, sendgrid-go.
  • API внешних сервисов: SendGrid, Mailgun, Amazon SES — удобно для масштабирования и аналитики.
  • Gmail API + OAuth2 для отправки через Gmail с современной авторизацией.

Безопасность и соответствие требованиям

  • Никогда не хардкодьте реальные пароли в репозитории. Используйте переменные окружения или секреты (Vault, AWS Secrets Manager).
  • В production включите проверку сертификатов TLS (InsecureSkipVerify=false) и применяйте ограничение доверенных корней.
  • Хранение и обработка персональных данных: если отправляете личные данные, убедитесь в соблюдении GDPR/локального законодательства — минимизация данных, шифрование, аудит.

Чек-листы по ролям

Разработчик:

  • Использует переменные окружения для секретов
  • Добавил обработку ошибок и retries
  • Покрыл unit-тестами шаблоны сообщений

Операции (Ops):

  • Настроены DNS / PTR / SPF / DKIM / DMARC для домена отправителя
  • Мониторинг отказов и очередей
  • Лимиты отправки и rate limiting

Информационная безопасность:

  • TLS с проверкой сертификата
  • Аудит логов отправки
  • Контроль доступа к секретам

Продукт / Менеджмент:

  • Согласован формат писем с поддержкой и дизайном
  • Планы на обработку отписок и жалоб на спам

Мини-методология развёртывания

  1. Разработать локальную реализацию и протестировать с тестовой почтой.
  2. Вынести секреты в безопасное хранилище.
  3. Настроить мониторинг (удачные/неудачные попытки, latency).
  4. Запускать через очередь задач (background worker) для устойчивости.
  5. Обеспечить откат и фолбек на внешний сервис при массовых ошибках.

Диагностика и частые ошибки

  • “535 Authentication failed” — неверный пароль или неправильный формат аутентификации.
  • “connection reset” или “certificate error” — проблемы с TLS, проверьте ServerName и доверенные CA.
  • Письма не доходят — проверьте SPF/DKIM/DMARC, и не попадание в спам-фильтры.

Пример потока решений (Mermaid)

flowchart TD
    A[Нужно отправить почту?] --> B{Объём и требования}
    B -->|Один раз / небольшие уведомления| C[Использовать net/smtp]
    B -->|HTML/вложения/массовые рассылки| D[Использовать внешнюю библиотеку или API]
    D --> E[SendGrid / Mailgun / Amazon SES]
    C --> F[Настроить TLS и аутентификацию]
    F --> G[Тестирование и мониторинг]

Критерии приёмки

  • Письмо успешно отправляется в тестовой среде и приходит на почтовый ящик получателя.
  • Секреты вынесены и не попадают в репозиторий.
  • TLS в продакшне валидируется, логиируют ошибки и метрики.

Краткая таблица совместимости и подсказки по миграции

  • Yahoo: smtp.mail.yahoo.com, порт 465 (TLS) или 587 (STARTTLS), требуется пароль приложения.
  • Gmail: порт 587 (STARTTLS) или Gmail API с OAuth2; пароль приложения возможен только при 2FA и включенных настройках.
  • Outlook/Office365: smtp.office365.com, порт 587 (STARTTLS).

При миграции на API-сервис (SendGrid и пр.) обычно меняется код отправки на HTTP-запросы и добавляется поддержка более надёжной обработки ошибок и аналитики.

Шаблон простого плейбука для инцидента: “Письма не отправляются”

  1. Проверить логи приложения — ошибки соединения, аутентификация.
  2. Проверить доступность хоста (ping/telnet host:port).
  3. Проверить сроки действия/смену паролей приложений.
  4. Проверить изменения в политике провайдера (например, ограничение по IP).
  5. При массовых отказах переключиться на резервный SMTP/API сервис.

Подтверждение успешной отправки письма

Резюме

net/smtp — простой и прозрачный инструмент для отправки базовых писем из Go. Для прототипа и небольших задач он отлично подходит. Для более сложных требований (HTML, вложения, массовые рассылки, аналитика, OAuth2) рассмотрите дополнительные библиотеки или SaaS-решения. Всегда используйте безопасное хранение секретов и корректную проверку TLS в продакшне.

Важные заметки:

  • Используйте пароль приложения у поставщиков, которые их поддерживают (Yahoo, Gmail с 2FA).
  • Не игнорируйте проверку сертификатов TLS в production.

Конец статьи.

Поделиться: X/Twitter Facebook LinkedIn Telegram
Автор
Редакция

Похожие материалы

Как перестать откладывать решения
Саморазвитие

Как перестать откладывать решения

Просмотр метаданных фото на iPhone (iOS 15)
iOS

Просмотр метаданных фото на iPhone (iOS 15)

Как воспроизвести два видео одновременно в VLC
Руководство

Как воспроизвести два видео одновременно в VLC

Split View на Mac — разделение экрана и советы
macOS

Split View на Mac — разделение экрана и советы

Конвертация видео в GIF на Linux
Инструкция

Конвертация видео в GIF на Linux

Как оценить реальный SEO‑рейтинг сайта
Поисковая оптимизация

Как оценить реальный SEO‑рейтинг сайта