Передайте туннель CONNECT SMTP-клиенту Go
Используйте smtp.NewClient с уже установленным туннелем и держите имя хоста SMTP и рукопожатие STARTTLS отдельно от настройки прокси.
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.