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

Отправка писем в 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
Автор
Редакция

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

RDP: полный гид по настройке и безопасности
Инфраструктура

RDP: полный гид по настройке и безопасности

Android как клавиатура и трекпад для Windows
Гайды

Android как клавиатура и трекпад для Windows

Советы и приёмы для работы с PDF
Документы

Советы и приёмы для работы с PDF

Calibration в Lightroom Classic: как и когда использовать
Фото

Calibration в Lightroom Classic: как и когда использовать

Отключить Siri Suggestions на iPhone
iOS

Отключить Siri Suggestions на iPhone

Рисование таблиц в Microsoft Word — руководство
Office

Рисование таблиц в Microsoft Word — руководство