π Context
I'm working on a Lua script that sends emails via SMTP with STARTTLS. The script successfully connects to the SMTP server, but authentication sometimes fails with the error:
authentication not supported
This happens after the STARTTLS handshake. I'm not sure if I'm sending the SMTP commands in the correct order or if there's an issue with the authentication method. β What the Script Does
π‘ Connects to an SMTP server (supports both TLS and SSL) π Implements STARTTLS when using port 587 π Authenticates using AUTH LOGIN π Includes a debugging function to log SMTP commands and responses β οΈ Issue Description
The script connects to the SMTP server (port 587 or 465). If using port 587, it sends EHLO, then STARTTLS. After TLS is enabled, it tries to authenticate, but the server rejects authentication. If using port 465, the script connects via SSL directly, but authentication still fails. π Debugging Log Sample
Hereβs an example of the log output when using port 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 <-- Should I send this again? [SMTP DEBUG] Received : 250-smtp.example.com [SMTP DEBUG] Sent : AUTH LOGIN [SMTP DEBUG] Received : 503 5.5.1 Error: authentication not supported π Full Lua Code (With Debugging)
local socket = require("socket") local smtp = require("socket.smtp") local ssl = require("ssl") -- LOG FILE 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 DEBUG FUNCTION 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 -- USER INPUT io.write("Enter your SMTP email: ") local smtp_user = io.read() io.write("Enter your SMTP password: ") local smtp_pass = io.read("*l") io.write("\nEnter the SMTP server: ") local smtp_server = io.read() io.write("Enter the SMTP port (465 for SSL, 587 for TLS): ") local smtp_port = tonumber(io.read()) -- FUNCTION: CREATE SECURE CONNECTION local function create_secure_connection() local sock = socket.tcp() sock:settimeout(5) -- CONNECT TO SMTP SERVER local success, err = sock:connect(smtp_server, smtp_port) if not success then print("Error: Connection failed - " .. err) log_message("Error: Connection failed - " .. err) return nil end -- STARTTLS FOR PORT 587 if smtp_port == 587 then debug_smtp(sock, "EHLO localhost") -- Initial EHLO local response = debug_smtp(sock, "STARTTLS") if not response:match("220") then print("Error: STARTTLS not supported") log_message("Error: STARTTLS not supported") return nil end -- UPGRADE TO TLS sock = ssl.wrap(sock, {mode="client", protocol="tlsv1_2", verify="none"}) sock:dohandshake() -- SEND EHLO AGAIN AFTER STARTTLS (Is this needed?) debug_smtp(sock, "EHLO localhost") elseif smtp_port == 465 then -- DIRECT SSL CONNECTION sock = ssl.wrap(sock, {mode="client", protocol="tlsv1_2", verify="none"}) sock:dohandshake() end return sock end -- EMAIL RECIPIENTS local recipients = {"[email protected]", "[email protected]"} -- EMAIL MESSAGE local subject = "Account Deletion Request" local message = [[ Hello, I would like to request the deletion of my personal data and account according to GDPR. Best regards. ]] -- FUNCTION: SEND EMAIL 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("Email sent to " .. to) log_message("Success: Email sent to " .. to) else print("Error: " .. to .. " - " .. tostring(err)) log_message("Error: " .. to .. " - " .. tostring(err)) end end -- LOOP TO SEND EMAILS for _, email in ipairs(recipients) do send_email(email) socket.sleep(2) end print("Process completed. Check 'log.txt' for details.") ´´´ π SMTP Debugging Flow (Mermaid Diagram) ´´´ 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 Questions
Do I need to send EHLO again after STARTTLS? Are my SMTP commands correctly ordered? How can I further debug the authentication failure?
Any help would be greatly appreciated! π