60 lines
1.6 KiB
Ruby
60 lines
1.6 KiB
Ruby
require 'socket'
|
|
|
|
#
|
|
# minimal smtp server for DataPipeline::Email tests: EHLO, AUTH LOGIN, MAIL, RCPT, DATA, QUIT
|
|
# server = TestSmtpServer.new
|
|
# server.mails -> [{ from:, to: [...], data:, auth: [user, password] }]
|
|
#
|
|
class TestSmtpServer
|
|
attr_reader :mails
|
|
|
|
def initialize
|
|
@mails = []
|
|
@server = TCPServer.new('127.0.0.1', 0)
|
|
@thread = Thread.new { loop { serve(@server.accept) } }
|
|
end
|
|
|
|
def port = @server.addr[1]
|
|
|
|
def stop
|
|
@thread.kill
|
|
@server.close
|
|
end
|
|
|
|
private
|
|
|
|
def serve client
|
|
mail = { to: [] }
|
|
client.write "220 test ESMTP\r\n"
|
|
while (line = client.gets)
|
|
case line
|
|
when /\AEHLO/i then client.write "250-test\r\n250 AUTH LOGIN PLAIN\r\n"
|
|
when /\AAUTH LOGIN/i
|
|
client.write "334 VXNlcm5hbWU6\r\n"
|
|
user = client.gets.unpack1('m')
|
|
client.write "334 UGFzc3dvcmQ6\r\n"
|
|
mail[:auth] = [user, client.gets.unpack1('m')]
|
|
client.write "235 ok\r\n"
|
|
when /\AMAIL FROM:<(.*)>/i then mail[:from] = $1; client.write "250 ok\r\n"
|
|
when /\ARCPT TO:<(.*)>/i then mail[:to] << $1; client.write "250 ok\r\n"
|
|
when /\ADATA/i
|
|
client.write "354 go\r\n"
|
|
data = +''
|
|
while (part = client.gets) && part != ".\r\n"
|
|
data << part
|
|
end
|
|
mail[:data] = data
|
|
@mails << mail
|
|
mail = { to: [] }
|
|
client.write "250 queued\r\n"
|
|
when /\AQUIT/i then client.write "221 bye\r\n"; break
|
|
else client.write "250 ok\r\n"
|
|
end
|
|
end
|
|
rescue StandardError => e
|
|
warn "TestSmtpServer: #{e.class}: #{e.message}"
|
|
ensure
|
|
client.close
|
|
end
|
|
end
|