Сценарий Lua SMTP с STARTTLS не проходит аутентификацию

Вопрос или проблема

🔍 Контекст

Я работаю над Lua-скриптом, который отправляет электронные письма через SMTP с использованием STARTTLS. Скрипт успешно подключается к SMTP-серверу, но аутентификация иногда не удается с ошибкой:

authentication not supported

Это происходит после завершения обмена ключами STARTTLS. Я не уверен, правильно ли я отправляю команды SMTP или проблема заключается в методе аутентификации.
✅ Что делает скрипт

📡 Подключается к SMTP-серверу (поддерживает как TLS, так и SSL)
🔒 Реализует STARTTLS при использовании порта 587
🔑 Аутентифицируется с помощью AUTH LOGIN
🛠 Включает функцию отладки для записи команд и ответов SMTP

⚠️ Описание проблемы

Скрипт подключается к SMTP-серверу (порт 587 или 465).
Если используется порт 587, отправляет EHLO, затем STARTTLS.
После включения TLS пытается выполнить аутентификацию, но сервер отклоняет аутентификацию.
Если используется порт 465, скрипт подключается напрямую через SSL, но аутентификация все равно не удается.

🛠 Пример журнала отладки

Вот пример вывода журнала при использовании порта 587:

[SMTP DEBUG] Sent : EHLO localhost
[SMTP DEBUG] Received : 250-smtp.example.com
[SMTP DEBUG] Sent : STARTTLS
[SMTP DEBUG] Received : 220 Ready to start TLS
[SMTP DEBUG] Sent : EHLO localhost  <-- Нужно ли отправлять это снова?
[SMTP DEBUG] Received : 250-smtp.example.com
[SMTP DEBUG] Sent : AUTH LOGIN
[SMTP DEBUG] Received : 503 5.5.1 Error: authentication not supported

🛠 Полный код на Lua (с отладкой)


local socket = require("socket")
local smtp = require("socket.smtp")
local ssl = require("ssl")

-- ЛОГ-ФАЙЛ
local log_file = "log.txt"

local function log_message(msg)
local file = io.open(log_file, "a")
if file then
file:write(os.date("%Y-%m-%d %H:%M:%S") .. " - " .. msg .. "\n")
file:close()
end
end

-- ФУНКЦИЯ ОТЛАДКИ SMTP
local function debug_smtp(sock, command)
sock:send(command .. "\r\n")
local response = sock:receive("*l")
print("[SMTP DEBUG] Sent : " .. command)
print("[SMTP DEBUG] Received : " .. (response or "No response"))
log_message("[SMTP DEBUG] Sent : " .. command)
log_message("[SMTP DEBUG] Received : " .. (response or "No response"))
return response
end

-- ВВОД ПОЛЬЗОВАТЕЛЯ
io.write("Введите вашу SMTP почту: ")
local smtp_user = io.read()

io.write("Введите ваш SMTP пароль: ")
local smtp_pass = io.read("*l")

io.write("\nВведите SMTP сервер: ")
local smtp_server = io.read()

io.write("Введите SMTP порт (465 для SSL, 587 для TLS): ")
local smtp_port = tonumber(io.read())

-- ФУНКЦИЯ: СОЗДАНИЕ БЕЗОПАСНОГО ПОДКЛЮЧЕНИЯ
local function create_secure_connection()
local sock = socket.tcp()
sock:settimeout(5)

-- ПОДКЛЮЧЕНИЕ К SMTP СЕРВЕРУ
local success, err = sock:connect(smtp_server, smtp_port)
if not success then
print("Ошибка: Подключение не удалось - " .. err)
log_message("Ошибка: Подключение не удалось - " .. err)
return nil
end

-- STARTTLS ДЛЯ ПОРТА 587
if smtp_port == 587 then
debug_smtp(sock, "EHLO localhost") -- Начальная EHLO
local response = debug_smtp(sock, "STARTTLS")

if not response:match("220") then
print("Ошибка: STARTTLS не поддерживается")
log_message("Ошибка: STARTTLS не поддерживается")
return nil
end

-- ОБНОВЛЕНИЕ ДО TLS
sock = ssl.wrap(sock, {mode="client", protocol="tlsv1_2", verify="none"})
sock:dohandshake()

-- ОТПРАВЬТЕ EHLO СНОВА ПОСЛЕ STARTTLS (Это необходимо?)
debug_smtp(sock, "EHLO localhost")
elseif smtp_port == 465 then
-- ПРЯМОЕ ПОДКЛЮЧЕНИЕ ЧЕРЕЗ SSL
sock = ssl.wrap(sock, {mode="client", protocol="tlsv1_2", verify="none"})
sock:dohandshake()
end

return sock
end

-- ПОЛУЧАТЕЛИ ЭЛЕКТРОННОЙ ПОЧТЫ
local recipients = {"[email protected]", "[email protected]"}

-- СООБЩЕНИЕ ДЛЯ ОТПРАВКИ
local subject = "Запрос на удаление аккаунта"
local message = [[
Здравствуйте,

Я хотел бы запросить удаление моих личных данных и учетной записи в соответствии с GDPR.

С уважением.
]]

-- ФУНКЦИЯ: ОТПРАВИТЬ ПИСЬМО
local function send_email(to)
local msg = {
headers = { from = smtp_user, to = to, subject = subject },
body = message
}

local ok, err = smtp.send{
from = smtp_user,
rcpt = to,
source = smtp.message(msg),
server = smtp_server,
port = smtp_port,
user = smtp_user,
password = smtp_pass,
create = create_secure_connection
}

if ok then
print("Письмо отправлено на " .. to)
log_message("Успешно: Письмо отправлено на " .. to)
else
print("Ошибка: " .. to .. " - " .. tostring(err))
log_message("Ошибка: " .. to .. " - " .. tostring(err))
end
end

-- ЦИКЛ ДЛЯ ОТПРАВКИ ПИСЕМ
for _, email in ipairs(recipients) do
send_email(email)
socket.sleep(2)
end

print("Процесс завершен. Проверьте 'log.txt' для деталей.")

📊 Поток отладки SMTP (диаграмма Mermaid)

sequenceDiagram
participant Client as Lua Script
participant SMTP as SMTP Server

Client->>SMTP: Connect to SMTP (port 587 or 465)
alt Port 587 (STARTTLS)
SMTP->>Client: 220 Service Ready
Client->>SMTP: EHLO localhost
SMTP->>Client: 250-AUTH PLAIN LOGIN
Client->>SMTP: STARTTLS
SMTP->>Client: 220 Ready to start TLS
Client->>Client: Upgrade to TLS Mode
Client->>SMTP: EHLO localhost (again?)
else Port 465 (SSL Direct)
Client->>Client: Direct SSL/TLS Connection
end

Client->>SMTP: AUTH LOGIN
SMTP->>Client: 334 Username Prompt
Client->>SMTP: (Base64 Encoded Email)
SMTP->>Client: 334 Password Prompt
Client->>SMTP: (Base64 Encoded Password)
SMTP->>Client: 235 Authentication Successful

Client->>SMTP: MAIL FROM:<[email protected]>
SMTP->>Client: 250 OK
Client->>SMTP: RCPT TO:<[email protected]>
SMTP->>Client: 250 OK
Client->>SMTP: DATA
SMTP->>Client: 354 Start mail input
Client->>SMTP: (Email Content)
Client->>SMTP: .
SMTP->>Client: 250 Message Accepted

Client->>SMTP: QUIT
SMTP->>Client: 221 Bye

Вопросы

Нужно ли отправлять EHLO снова после STARTTLS?
Правильно ли расположены мои команды SMTP?
Как я могу дополнительно выполнять отладку сбоя аутентификации?

Любая помощь будет очень полезна! 🚀


Ответ или решение

Для решения проблемы с аутентификацией в Lua-скрипте, отправляющем электронные письма через SMTP с использованием STARTTLS, давайте подробно разберем процесс и выявим возможные причины ошибки "authentication not supported".

Теория

При подключении к серверу SMTP с использованием STARTTLS важно соблюдать определенный порядок SMTP-команд. Основные этапы процесса следующие:

  1. Подключение: Установление соединения с сервером SMTP.
  2. EHLO: Отправка команды EHLO для инициализации сессии и получения списка возможностей сервера.
  3. STARTTLS: Начало TLS-сессии для шифрования обмена данными.
  4. Повторный EHLO: Эта команда отправляется после установки безопасного соединения для повторного обмена функциями безопасности.
  5. Аутентификация: Использование AUTH LOGIN для входа в систему.

Ошибка "authentication not supported" может указывать на нехватку функциональности на стороне сервера или неправильное использование команд.

Пример

Ниже приведен пример процесса обмена командами между клиентом и сервером:

  1. Клиент: Подключается к серверу SMTP.
  2. Сервер: Возвращает 220 - готовность к соединению.
  3. Клиент: Отправляет EHLO localhost.
  4. Сервер: Возвращает 250 с перечнем возможностей, включая доступные методы аутентификации.
  5. Клиент: Отправляет команду STARTTLS.
  6. Сервер: Возвращает 220 - готовность к TLS.
  7. Клиент: Переходит на зашифрованный TLS-канал и повторно отправляет EHLO для обновления информации о функциях сервера.
  8. Сервер: Отвечает 250 с возможностями для зашифрованного соединения.

Если сервер правильно поддерживает STARTTLS и аутентификацию через AUTH LOGIN, но вы видите ошибку после шага 7, причиной может быть нехватка возможностей на сервере для текущего состояния соединения.

Применение

1. Повторная отправка EHLO:

Вы задали правильный вопрос - действительно ли необходимо повторно отправлять EHLO после STARTTLS. Правильный ответ: да, это нужно делать. При установлении безопасного соединения сервер может предложить другой набор возможностей. В вашем случае вы это делаете правильно.

2. Проверка функций сервера:

Проверьте, поддерживает ли ваш SMTP-сервер метод AUTH LOGIN после установки соединения через TLS. Некоторые серверы могут иметь ограничения или могут быть настроены так, что требуется другой метод аутентификации, например, AUTH PLAIN.

3. Обновление конфигурации:

Проверьте конфигурацию вашего SMTP-сервера (если у вас есть доступ), чтобы подтвердить, что в нём действительно включена поддержка аутентификации после STARTTLS. Если используете облачное решение, рассмотрите возможность обращения в поддержку.

4. Отладка:

Если вы не можете изменить сервер, рассмотрите возможность использования других библиотек или методов, которые могут более корректно работать с вашим SMTP-сервером.

5. Инструменты диагностики:

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

6. Шифрование и методы:

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

Заключение

Проблема с аутентификацией может быть связана с различными факторами, включая настройки сервера, порядок отправки команд и ограничения на уровне сети. Внимательное изучение возможностей вашего SMTP-сервера и корректная настройка последовательности команд в скрипте должны помочь решить проблему. Важно также учитывать, что аутентификационные методы и поддержка TLS могут отличаться на различных серверах. Игнорирование или недооценка этих аспектов может привести к возникновению подобных ошибок.

Оцените материал
Добавить комментарий

Капча загружается...