local cqueues = require'cqueues' local socket = require'cqueues.socket' local openssl_context = require'openssl.ssl.context' local base64 = require'base64' local get_default_ehlo_host = function() return 'debian' -- TODO read from /etc/hosts end local send_auth_plain = function(opts) if opts.host==nil or opts.from==nil or opts.to==nil then error('`host`, `from`, and `to` are required.') end local host = opts.host local port = opts.port or 25 --587 local username = opts.username local password = opts.password local ehlo_host = opts.ehlo_host or get_default_ehlo_host() local from = opts.from local to = opts.to -- `message` includes Subject and other headers. Use stmp-message.lua to construct a message string. local message = opts.message or 'Subject: \r\n\r\n\r\n.\r\n' --local subject = opts.subject or '' --local body = opts.body or '' local connection = socket.connect(host, port) connection:settimeout(5) local read = function() local m = connection:read('*l') or '' print('<-- '..m) return m end local read_until = function(code_desired, substring) local substring_needed = (substring ~= nil) local code, line repeat line = read() code = string.sub(line,1,3) until code == code_desired and (not substring_needed or line:find(substring) ~= nil) end local write = function(m) print('--> '..m) connection:write(m) end read_until('220') write('STARTTLS\r\n') read_until('220') local ctx = openssl_context.new('TLSv1_2', false) local ok, err = connection:starttls(ctx) if not ok then print('starttls error', err) end write('EHLO '..ehlo_host..'\r\n') read_until('250','PLAIN') write('AUTH PLAIN '..base64.encode(username..'\0'..username..'\0'..password)..'\r\n') read_until('235') -- auth successful write('MAIL FROM:<'..from..'>\r\n') read_until('250') write('RCPT TO:<'..to..'>\r\n') read_until('250') write('DATA\r\n') read_until('354') write(message) --write('Subject: '..subject..'\r\n\r\n') --write(body..'\r\n') write('\r\n.\r\n') read_until('250') write('QUIT') --read_until('221') connection:close() end return send_auth_plain