smtp.Dial открывает новое соединение по своему адресу. Получив соединение через прокси HTTP CONNECT, передайте этот существующий поток в smtp.NewClient вместо этого.

Для SMTP-сервера, требующего STARTTLS на порту отправки, передача может выглядеть так:

func smtpOverTunnel(conn net.Conn, mailHost string) (*smtp.Client, error) {
    client, err := smtp.NewClient(conn, mailHost)
    if err != nil {
        conn.Close()
        return nil, err
    }
    err = client.StartTLS(&tls.Config{
        ServerName: mailHost,
        MinVersion: tls.VersionTLS12,
    })
    if err != nil {
        client.Close()
        return nil, err
    }
    return client, nil
}

Пакеты — net, net/smtp и crypto/tls. Вызывающая сторона предоставляет туннель, уже подключённый к нужному хосту и порту SMTP, с завершённым обменом CONNECT прокси. Просто открыть TCP к прокси недостаточно: ответ HTTP — не приветствие SMTP.

mailHost — это имя хоста SMTP-сервера без порта. Сохраняйте эту идентичность для аутентификации SMTP и проверки сертификата. TLS-соединение с прокси HTTPS защищает другой участок маршрута.

Возвращённый клиент готов к существующей аутентификации SMTP и почтовой транзакции приложения. Закройте его по завершении. Ограничьте набор, CONNECT и последующие протокольные операции политикой сроков приложения.

Прокси должен разрешать CONNECT к выбранному почтовому порту. Некоторые ограничивают его HTTPS-назначениями на порту 443. Для SMTP с неявным TLS установите TLS-сеанс назначения перед вызовом NewClient, а не выдавайте STARTTLS.

Похожие статьи