Верстакфорум практиков
рекламаiprazon: приватные серверные адреса IPv4 и SOCKS5, безлимитный трафик, бесплатный тест до 2 часов
ФорумПочта и рассылки

Отправка почты через SOCKS5: настройка в клиенте и в коде

Юля Ким
Юля Ким
Знаток
сообщений 1240
с мая
22 апреля, 17:27первое сообщение

Задача такая: письма от рассылочного скрипта должны уходить с одного постоянного адреса, хотя сам скрипт крутится то на рабочей машине, то на арендованном сервере.

С почтовым клиентом более-менее понятно, там есть поля для посредника. А вот в коде на Python упёрлась: у smtplib никакого параметра для посредника нет вообще. Обёртки, которые нашла поиском, ставят его только на HTTP.

Как это делают нормально?

Артём Пчёлкин
Артём Пчёлкин
Ветеран
сообщений 2310
с янв
1 сентября, 08:44#2

Нормально это через сокет. SOCKS5 работает уровнем ниже почтового разговора, поэтому библиотеке про него знать необязательно: вы подменяете сам сокет, а smtplib дальше работает как обычно.

import socks, socket, smtplib

socks.set_default_proxy(socks.SOCKS5, "адрес.посредника", 1080, username="login", password="pass", rdns=True) # имена разрешает дальняя сторона socket.socket = socks.socksocket # подмена до создания соединения

s = smtplib.SMTP("smtp.example.net", 587, timeout=30) s.ehlo(); s.starttls(); s.ehlo() s.login(pochta_user, pochta_pass) s.sendmail(ot, komu, pismo) s.quit() ```

Обратите внимание на rdns=True. Без него имя почтового сервера разрешается у вас локально, и на дальнюю сторону уходит уже готовый адрес.

Полина Ждан
Полина Ждан
Новичок
сообщений 120
с мая, второй сезон
8 февраля, 11:01#3

а глобальная подмена сокета не сломает всё остальное в том же скрипте?

hexdump
hexdump
Знаток
сообщений 940
с июн
15 июля, 14:18#4

Сломает, если в том же процессе ходите ещё куда-то. Правильнее оставить глобальный сокет в покое: соберите соединение руками и отдайте его в smtplib.

import socks, smtplib

sock = socks.create_connection(("smtp.example.net", 587), proxy_type=socks.SOCKS5, proxy_addr="адрес.посредника", proxy_port=1080, proxy_username="login", proxy_password="pass", proxy_rdns=True, timeout=30)

s = smtplib.SMTP() s.sock = sock s.file = sock.makefile("rb") s._host = "smtp.example.net" s.ehlo(); s.starttls(); s.ehlo() ```

Тут посредник живёт ровно на одном соединении, остальной код ходит напрямую.

Юля Ким
Юля Ким
Знаток
сообщений 1240
с мая
22 декабря, 17:35#5
hexdump: посредник живёт ровно на одном соединении

Взяла этот вариант, у меня в том же процессе ещё стучится api заказчика. Работает с первого раза.

dev_null_ru
dev_null_ru
Ветеран
сообщений 2560
с фев
1 мая, 08:52#6

Для тех, кто придёт из поиска и сидит на почтовом клиенте: в Thunderbird это «Настройки», раздел сети, ручная настройка, поле для SOCKS5 хоста и порта. Обязательно отметьте пункт про разрешение имён на стороне посредника, иначе будет ровно та же история с локальным разрешением.

И проверьте, что галочка про обход для локальных адресов оставлена, иначе внутренние сервисы тоже поедут через посредника.

Максим Юрьев
Максим Юрьев
Знаток
сообщений 1720
с апр
8 октября, 11:09#7

Из командной строки удобно проверять через curl, он умеет и почтовые схемы, и SOCKS5 в одном флаге.

пробная отправка через посредника
пробная отправка через посредника

Флаг --socks5-hostname берите вместо --socks5: он как раз отдаёт имя дальней стороне.

Полина Ждан
Полина Ждан
Новичок
сообщений 120
с мая, второй сезон
15 марта, 14:26#8

спасибо, curl проще всего для проверки, у меня сразу видно стало где встаёт

Юля Ким
Юля Ким
Знаток
сообщений 1240
с мая
22 августа, 17:43#9

Вопрос по ходу дела. Проверила отправку, всё уходит, но как убедиться, что письмо реально ушло через посредника, а само соединение не проскочило мимо?

Артём Пчёлкин
Артём Пчёлкин
Ветеран
сообщений 2310
с янв
1 января, 08:00#10

Смотрите заголовок Received в доставленном письме: нижняя строка покажет адрес, с которого почтовый сервер принял соединение. Совпал с адресом посредника, значит всё идёт как задумано.

Второй способ грубее, зато нагляднее: слушаете сетевой обмен на машине и убеждаетесь, что соединения на порт 587 напрямую нет вовсе, есть только на порт посредника.

Про постоянство адреса скажу отдельно, раз с этого началась тема. Смысл затеи в том, что почтовый сервер получателя видит один и тот же адрес отправки со всех ваших машин, и репутация набирается на него одного, вместо того чтобы размазываться по десятку. Поэтому берите точку выхода, которая переживёт переезд скрипта на другую машину: мы под это держим сокетные адреса под рассылку, протокол там как раз SOCKS5, привязок в пакете две, чего хватает на рабочую машину и на сервер сразу.

Юля Ким
Юля Ким
Знаток
сообщений 1240
с мая
8 июня, 11:17#11

Сверила по Received, адрес совпадает с посредником на всех письмах, включая повторы из очереди.

Итог для тех, кто найдёт тему поиском: соединение собирается отдельно и отдаётся в smtplib, глобальную подмену сокета не трогаем, имена разрешает дальняя сторона, проверка делается через curl и потом через заголовок доставленного письма. Спасибо всем.