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

Отправка почты в Go через net/smtp

7 min read Go Email Обновлено 13 Apr 2026
Отправка почты в Go через net/smtp
Отправка почты в Go через net/smtp

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

Вы часто можете потребоваться отправлять письма из программ — для подтверждения аккаунта, уведомлений, логирования или других целей. SMTP отвечает за отправку писем между серверами, а IMAP — за приём. В Go есть стандартный пакет net/smtp, реализующий основные возможности SMTP и поддерживающий расширения (AUTH, STARTTLS, 8BITMIME). Код в этой статье доступен в репозитории на GitHub и распространяется под лицензией MIT.

Для кого эта инструкция

  • Разработчики backend на Go, которые хотят быстро отправлять почту.
  • Девопсы, которым нужно понять, как устроен поток отправки почты через SMTP с TLS.
  • Тестировщики, которым нужно автоматизировать отправку уведомлений.

Важно: в примерах используется SMTP сервера Yahoo как иллюстрация. Шаги применимы и к другим провайдерам, но параметры хоста/порта и требования к аутентификации могут отличаться.

Краткие термины

  • SMTP — протокол для передачи почты между серверами.
  • TLS — безопасный уровень транспортного шифрования.
  • App password — отдельный пароль для приложений, если основной аккаунт защищён 2FA.

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

  • Установленный Go (1.20+ рекомендуется).
  • Учетная запись почтового провайдера и, при необходимости, созданный пароль приложения (app password) или OAuth2-токен.
  • Базовые знания работы с TLS и сетями.

Импорт пакетов и минимальный шаблон

Пакет net/smtp входит в стандартную библиотеку — ничего дополнительно устанавливать не нужно. Также используйте log и crypto/tls для логирования и конфигурации безопасного соединения.

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

Вы можете написать функцию SendMail(), которая отправляет письмо, и вызвать её из main.

func main() {  
    fmt.Print(SendMail())  
}  
func SendMail() string {    
    // Add code here     
}  

Основная идея: как работает отправка писем

SMTP требует набор параметров: адрес отправителя, адрес получателя(ей), хост сервера, порт и содержимое сообщения (заголовки + тело). В общем виде последовательность действий:

  1. Подготовка заголовков и тела сообщения.
  2. Установка TLS-соединения (если нужно).
  3. Аутентификация (PlainAuth или OAuth2).
  4. Инициация SMTP-клиента и отправка DATA.
  5. Закрытие соединения.

Генерация пароля приложения для Yahoo

Если вы используете Yahoo Mail, зайдите в настройки аккаунта -> Account Security и создайте пароль приложения (app password). Этот пароль используется вместо основного пароля и лучше хранится в защищённых секретах среды выполнения (см. раздел Безопасность).

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

Пример переменных в функции SendMail

В функции SendMail вы объявляете переменные: from — адрес отправителя, password — пароль приложения или токен, to — адрес получателя.

from := "yourMail@gmail.com"  
password := "aSecurePasswordHere"  
to := "anemail@gmail.com"  

Если нужно отправить на несколько адресов — используйте срез и цикл.

Хост и порт SMTP

Провайдер определяет хост и порт. Типичные порты:

  • 25 — стандартный SMTP (обычно без шифрования)
  • 465 — SMTPS (SMTP поверх SSL/TLS), часто используется для явного TLS при установке соединения
  • 587 — SMTP с STARTTLS (начинается как незашифрованное соединение, затем переводится в TLS)

Пример для Yahoo:

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

К сведению: Gmail отключил «менее безопасные приложения», поэтому для Gmail часто требуется OAuth2 или использование пароля приложения с включённой двухфакторной аутентификацией.

Формирование заголовков и тела письма

Заголовки — это простая map[string]string; затем вы собираете строку сообщения из заголовков и тела.

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", k, v)  
}  
message += "\r" + body  

Важно: для сложных сообщений (HTML, вложения, кодировка) используйте MIME-заголовки, boundary и кодирование (base64/quoted-printable). Для простых уведомлений этого куска достаточно.

Аутентификация через PlainAuth

Пакет smtp предоставляет smtp.PlainAuth для простой аутентификации:

authenticate := smtp.PlainAuth("", from, password, host)  

Если используется OAuth2, вместо PlainAuth вы должны подготовить специальный механизм аутентификации (токен) и использовать smtp.Auth интерфейс.

Создание TLS-соединения и SMTP-клиента

Некоторые провайдеры требуют прямого TLS-соединения (SMTPS на порту 465). Пример конфигурации TLS:

tlsConfig := &tls.Config{  
    InsecureSkipVerify: true,  
    ServerName: host,  
}  

Важно: InsecureSkipVerify: true отключает проверку сертификата — это удобно в локальной среде, но опасно в продакшене. См. раздел Безопасность ниже.

Установка соединения и создание клиента:


connection, err := tls.Dial("tcp", serverAddress, tlsConfig) err != nil {  
    log.Panic(err)  
}  

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

(В реальном коде разбивайте выражение на строки и правильно обрабатывайте err после вызова Dial.)

Передача параметров и отправка письма

После создания smtpClient выполните аутентификацию, укажите отправителя и получателей и передайте данные:

if err = smtpClient.Auth(authenticate); err != nil {  
    log.Panic(err)  
}  
if err = smtpClient.Mail(from); err != nil {  
    log.Panic(err)  
}  
  
if err = smtpClient.Rcpt(headers["To"]); err != nil {  
    log.Panic(err)  
}  

writer, err := smtpClient.Data()  
if err != nil {  
    log.Panic(err)  
}  
  
_, err = writer.Write([]byte(message))  
if err != nil {  
    log.Panic(err)  
}  

err = writer.Close()  
if err != nil {  
    log.Panic(err)  
}  
err = smtpClient.Quit()  
if err != nil {  
    return  
}  
  
return "Successful, the mail was sent!"  

После вызова SendMail в main вы увидите сообщение об успехе в консоли, а письмо будет доставлено получателю.

Доказательство успешной отправки письма

Когда этот подход не подходит

Важно: net/smtp удобен для простых задач и тестовых скриптов, но имеет ограничения:

  • Для массовых рассылок и статистики нужен сторонний сервис (SendGrid, Mailgun, Amazon SES).
  • Для сложных писем с вложениями и HTML лучше использовать библиотеку, которая умеет строить MIME с boundary и кодировками.
  • Для OAuth2-аутентификации (например, Gmail API) потребуются дополнительные реализации.

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

  • Использовать API сторонних почтовых сервисов (SendGrid, Mailgun, Postmark). Они обеспечивают доставляемость, очереди, шаблоны и статистику.
  • Локальный MTA (Postfix) + отправка через localhost — полезно для изоляции и очередей.
  • SMTP-клиенты/библиотеки, поддерживающие вложения и удобное создание MIME (github.com/jordan-wright/email и пр.).

Безопасность и хранение секретов

Важно соблюдать простые принципы:

  • Никогда не храните пароли в коде. Используйте переменные окружения или менеджеры секретов (Vault, AWS Secrets Manager).
  • Не устанавливайте InsecureSkipVerify: true в продакшене — это отключает проверку сертификатов.
  • Предпочтительно использовать пароль приложения или OAuth2; пароль аккаунта менее безопасен.
  • Лимитируйте количество отправляемых писем и обрабатывайте ошибки отправки, чтобы избежать блокировок у провайдера.

Важно: для соответствия требованиям безопасности и конфиденциальности избегайте включения личных данных в логи.

Отладка и распространённые ошибки

  • net/smtp: unexpected TLS handshake — проверьте порт (465 vs 587) и режим (SMTPS vs STARTTLS).
  • 535 Authentication failed — проверьте правильность пароля/токена и настройки доступа в аккаунте.
  • Connection refused — проверьте, не блокирует ли исходящие соединения ваш хост/файрволл.

Пошаговый план при ошибке:

  1. Проверить корректность host:port.
  2. Попробовать telnet host порт для проверки соединения или openssl s_client -connect host:port.
  3. Проверить логи провайдера (если доступны).
  4. Включить подробное логирование в приложении и проверить содержимое message и заголовков.

Роль‑ориентированные чеклисты

Чеклист разработчика:

  • Код не содержит паролей.
  • Заголовки и кодировка верны.
  • Обработаны ошибки и таймауты.

Чеклист оператора/админа:

  • Открыты нужные исходящие порты.
  • Сертификаты действительны.
  • Мониторинг очередей отправки настроен.

Чеклист специалиста по безопасности:

  • Используются секретные хранилища.
  • Нет InsecureSkipVerify в проде.
  • Минимальные привилегии для аккаунтов/токенов.

Чеклист QA:

  • Тесты на успешную отправку и обработку ошибок.
  • Проверка заголовков и отображения в популярных почтовых клиентах.

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

  • Письмо доставлено на указанный адрес и отображается корректно в почтовом клиенте.
  • В логах приложения фиксируется статус отправки/ошибки.
  • Секреты не находятся в репозитории.
  • Для массовой рассылки используется сторонний сервис или очередь.

Тесты и сценарии приёмки

  1. Отправка простого текста одному получателю. Ожидается: статус успешен, письмо получено.
  2. Отправка на несколько получателей. Ожидается: все получатели получают письмо.
  3. Некорректный пароль. Ожидается: получение ошибки аутентификации и корректный лог.
  4. Неправильный хост/порт. Ожидается: ошибка соединения и корректный лог.

Шаблоны и сниппеты

Отправка на несколько получателей (пример):

recipients := []string{"user1@example.com", "user2@example.com"}
for _, r := range recipients {
    if err := smtpClient.Rcpt(r); err != nil {
        log.Printf("rcpt failed for %s: %v", r, err)
    }
}

Использование STARTTLS (если сервер поддерживает порт 587):

// Подключиться через net.Dial, затем вызвать smtp.NewClient, затем c.StartTLS(tlsConfig)

(Полный пример STARTTLS выходит за рамки краткого сниппета — используйте официальную документацию и примеры в сети.)

Соответствие приватности и GDPR

Если вы отправляете персональные данные (имена, адреса, данные аккаунтов), убедитесь, что у вас есть основание для обработки (согласие или контракт). Храните адреса и логи в соответствии с политиками хранения данных и предоставляйте возможность удаления/экспорта данных по запросу.

Ментальная модель процесса отправки почты

Представьте себе конвейер: вы упаковываете сообщение (заголовки + тело), передаёте в «почтовый клиент» (smtpClient), который говорит «я — отправитель», затем получает подтверждение от сервера-почтовика и кладёт письмо в очередь доставки. На каждом этапе возможны ошибки: упаковка (MIME), соединение (TLS), аутентификация, передача.

Когда стоит перейти на сторонний сервис

  • Вам нужна статистика доставляемости и кликов.
  • Огромные объёмы отправки и требования к очередям.
  • Обработка отказов, повторов и блокировок.

Полезные рекомендации по миграции

  • Разделите логику формирования письма и транспорт (SMTP). Это упростит замену транспорта на API SendGrid/SES без изменения генерации писем.
  • Внедрите очередь сообщений (RabbitMQ, Kafka) для сглаживания пиков отправки.

1‑строчная глоссарий

  • SMTP — протокол отправки почты.
  • TLS — шифрование канала.
  • App password — отдельный пароль для приложений при 2FA.

Заключение

net/smtp в Go — удобный инструмент для простых сценариев отправки почты. Для продакшена обратите внимание на безопасность, правильную обработку ошибок, хранение секретов и масштабируемость. Если требования возрастают, рассмотрите специализированные сервисы или внешние API.

Резюме

  • net/smtp подходит для простых сценариев отправки писем и тестирования.
  • Всегда защищайте секреты и не отключайте проверку сертификатов в проде.
  • Для массовых рассылок и аналитики лучше использовать сторонние сервисы.
Поделиться: X/Twitter Facebook LinkedIn Telegram
Автор
Редакция

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

Как полностью переустановить ChromeOS на Chromebook
Инструкции

Как полностью переустановить ChromeOS на Chromebook

Идеальные скриншоты в Windows
Инструкции

Идеальные скриншоты в Windows

Проверка скорости Wi‑Fi: тесты и устранение проблем
Wi‑Fi

Проверка скорости Wi‑Fi: тесты и устранение проблем

Виджеты и гаджеты для Windows 10
Windows

Виджеты и гаджеты для Windows 10

Коды BSOD Windows 10/11: как найти и исправить
Windows

Коды BSOD Windows 10/11: как найти и исправить

Ограничить чувствительную рекламу в Google
Конфиденциальность

Ограничить чувствительную рекламу в Google