mirror of
https://github.com/lunarmodules/luasocket.git
synced 2024-11-19 11:48:21 +01:00
307 lines
6.3 KiB
Lua
307 lines
6.3 KiB
Lua
|
local sent = {}
|
||
|
|
||
|
local from = "luasock@tecgraf.puc-rio.br"
|
||
|
local server = "mail.tecgraf.puc-rio.br"
|
||
|
local rcpt = "luasock@tecgraf.puc-rio.br"
|
||
|
|
||
|
local parse = {}
|
||
|
|
||
|
local name = "/var/spool/mail/luasock"
|
||
|
|
||
|
local t = _time()
|
||
|
local err
|
||
|
|
||
|
function mysetglobal (varname, oldvalue, newvalue)
|
||
|
print("changing " .. varname)
|
||
|
%rawset(%globals(), varname, newvalue)
|
||
|
end
|
||
|
function mygetglobal (varname, newvalue)
|
||
|
print("checking " .. varname)
|
||
|
return %rawget(%globals(), varname)
|
||
|
end
|
||
|
settagmethod(tag(nil), "setglobal", mysetglobal)
|
||
|
settagmethod(tag(nil), "getglobal", mygetglobal)
|
||
|
|
||
|
assert(dofile("../lua/smtp.lua"))
|
||
|
assert(dofile("../lua/cl-compat.lua"))
|
||
|
|
||
|
local total = function()
|
||
|
local t = 0
|
||
|
for i = 1, getn(%sent) do
|
||
|
t = t + %sent[i].count
|
||
|
end
|
||
|
return t
|
||
|
end
|
||
|
|
||
|
local similar = function(s1, s2)
|
||
|
return strlower(gsub(s1, "%s", "")) == strlower(gsub(s2, "%s", ""))
|
||
|
end
|
||
|
|
||
|
function parse.headers(headers_s)
|
||
|
local headers = {}
|
||
|
headers_s = "\n" .. headers_s .. "$$$:\n"
|
||
|
local i, j = 1, 1
|
||
|
local name, value, _
|
||
|
while 1 do
|
||
|
j = strfind(headers_s, "\n%S-:", i+1)
|
||
|
if not j then break end
|
||
|
_, _, name, value = strfind(strsub(headers_s, i+1, j-1), "(%S-): (.*)")
|
||
|
value = gsub(value, "\r\n", "\n")
|
||
|
value = gsub(value, "\n%s*", " ")
|
||
|
name = strlower(name)
|
||
|
if headers[name] then headers[name] = headers[name] .. ", " .. value
|
||
|
else headers[name] = value end
|
||
|
i, j = j, i
|
||
|
end
|
||
|
headers["$$$"] = nil
|
||
|
return headers
|
||
|
end
|
||
|
|
||
|
function parse.message(message_s)
|
||
|
message_s = gsub(message_s, "^.-\n", "")
|
||
|
local _, headers_s, body
|
||
|
_, _, headers_s, body = strfind(message_s, "^(.-\n)\n(.*)")
|
||
|
headers_s = headers_s or ""
|
||
|
body = body or ""
|
||
|
return { headers = %parse.headers(headers_s), body = body }
|
||
|
end
|
||
|
|
||
|
function parse.mbox(mbox_s)
|
||
|
local mbox = {}
|
||
|
mbox_s = "\n" .. mbox_s .. "\nFrom "
|
||
|
local i, j = 1, 1
|
||
|
while 1 do
|
||
|
j = strfind(mbox_s, "\nFrom ", i + 1)
|
||
|
if not j then break end
|
||
|
tinsert(mbox, %parse.message(strsub(mbox_s, i + 1, j - 1)))
|
||
|
i, j = j, i
|
||
|
end
|
||
|
return mbox
|
||
|
end
|
||
|
|
||
|
local readfile = function(name)
|
||
|
local f = readfrom(name)
|
||
|
if not f then return nil end
|
||
|
local s = read("*a")
|
||
|
readfrom()
|
||
|
return s
|
||
|
end
|
||
|
|
||
|
local capture = function(cmd)
|
||
|
readfrom("| " .. cmd)
|
||
|
local s = read("*a")
|
||
|
readfrom()
|
||
|
return s
|
||
|
end
|
||
|
|
||
|
local fail = function(s)
|
||
|
s = s or "failed!"
|
||
|
print(s)
|
||
|
exit()
|
||
|
end
|
||
|
|
||
|
local empty = function()
|
||
|
local f = openfile(%name, "w")
|
||
|
closefile(f)
|
||
|
end
|
||
|
|
||
|
local get = function()
|
||
|
return %readfile(%name)
|
||
|
end
|
||
|
|
||
|
local list = function()
|
||
|
return %capture("ls -l " .. %name)
|
||
|
end
|
||
|
|
||
|
local check_headers = function(sent, got)
|
||
|
sent = sent or {}
|
||
|
got = got or {}
|
||
|
for i,v in sent do
|
||
|
if not %similar(v, got[i]) then %fail("header " .. v .. "failed!") end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
local check_body = function(sent, got)
|
||
|
sent = sent or ""
|
||
|
got = got or ""
|
||
|
if not %similar(sent, got) then %fail("bodies differ!") end
|
||
|
end
|
||
|
|
||
|
local check = function(sent, m)
|
||
|
write("checking ", m.headers.title, ": ")
|
||
|
for i = 1, getn(sent) do
|
||
|
local s = sent[i]
|
||
|
if s.title == m.headers.title and s.count > 0 then
|
||
|
%check_headers(s.headers, m.headers)
|
||
|
%check_body(s.body, m.body)
|
||
|
s.count = s.count - 1
|
||
|
print("ok")
|
||
|
return
|
||
|
end
|
||
|
end
|
||
|
%fail("not found")
|
||
|
end
|
||
|
|
||
|
local insert = function(sent, message)
|
||
|
if type(message.rcpt) == "table" then
|
||
|
message.count = getn(message.rcpt)
|
||
|
else message.count = 1 end
|
||
|
message.headers = message.headers or {}
|
||
|
message.headers.title = message.title
|
||
|
tinsert(sent, message)
|
||
|
end
|
||
|
|
||
|
local mark = function()
|
||
|
local time = _time()
|
||
|
return { time = time }
|
||
|
end
|
||
|
|
||
|
local wait = function(sentinel, n)
|
||
|
local to
|
||
|
write("waiting for ", n, " messages: ")
|
||
|
while 1 do
|
||
|
local mbox = %parse.mbox(%get())
|
||
|
if n == getn(mbox) then break end
|
||
|
if _time() - sentinel.time > 50 then
|
||
|
to = 1
|
||
|
break
|
||
|
end
|
||
|
_sleep(1)
|
||
|
write(".")
|
||
|
flush(_STDOUT)
|
||
|
end
|
||
|
if to then %fail("timeout")
|
||
|
else print("ok") end
|
||
|
end
|
||
|
|
||
|
local stuffed_body = [[
|
||
|
This message body needs to be
|
||
|
stuffed because it has a dot
|
||
|
.
|
||
|
by itself on a line.
|
||
|
Otherwise the mailer would
|
||
|
think that the dot
|
||
|
.
|
||
|
is the end of the message
|
||
|
and the remaining will cause
|
||
|
a lot of trouble.
|
||
|
]]
|
||
|
|
||
|
insert(sent, {
|
||
|
from = from,
|
||
|
rcpt = {
|
||
|
"luasock2@tecgraf.puc-rio.br",
|
||
|
"luasock",
|
||
|
"luasock1"
|
||
|
},
|
||
|
body = "multiple rcpt body",
|
||
|
title = "multiple rcpt",
|
||
|
})
|
||
|
|
||
|
insert(sent, {
|
||
|
from = from,
|
||
|
rcpt = {
|
||
|
"luasock2@tecgraf.puc-rio.br",
|
||
|
"luasock",
|
||
|
"luasock1"
|
||
|
},
|
||
|
headers = {
|
||
|
header1 = "header 1",
|
||
|
header2 = "header 2",
|
||
|
header3 = "header 3",
|
||
|
header4 = "header 4",
|
||
|
header5 = "header 5",
|
||
|
header6 = "header 6",
|
||
|
},
|
||
|
body = stuffed_body,
|
||
|
title = "complex message",
|
||
|
})
|
||
|
|
||
|
insert(sent, {
|
||
|
from = from,
|
||
|
rcpt = rcpt,
|
||
|
server = server,
|
||
|
body = "simple message body",
|
||
|
title = "simple message"
|
||
|
})
|
||
|
|
||
|
insert(sent, {
|
||
|
from = from,
|
||
|
rcpt = rcpt,
|
||
|
server = server,
|
||
|
body = stuffed_body,
|
||
|
title = "stuffed message body"
|
||
|
})
|
||
|
|
||
|
insert(sent, {
|
||
|
from = from,
|
||
|
rcpt = rcpt,
|
||
|
headers = {
|
||
|
header1 = "header 1",
|
||
|
header2 = "header 2",
|
||
|
header3 = "header 3",
|
||
|
header4 = "header 4",
|
||
|
header5 = "header 5",
|
||
|
header6 = "header 6",
|
||
|
},
|
||
|
title = "multiple headers"
|
||
|
})
|
||
|
|
||
|
insert(sent, {
|
||
|
from = from,
|
||
|
rcpt = rcpt,
|
||
|
title = "minimum message"
|
||
|
})
|
||
|
|
||
|
write("testing host not found: ")
|
||
|
local c, e = connect("wrong.host", 25)
|
||
|
local err = SMTP.mail{
|
||
|
from = from,
|
||
|
rcpt = rcpt,
|
||
|
server = "wrong.host"
|
||
|
}
|
||
|
if e ~= err then fail("wrong error message")
|
||
|
else print("ok") end
|
||
|
|
||
|
write("testing invalid from: ")
|
||
|
local err = SMTP.mail{
|
||
|
from = ' " " (( _ * ',
|
||
|
rcpt = rcpt,
|
||
|
}
|
||
|
if not err then fail("wrong error message")
|
||
|
else print(err) end
|
||
|
|
||
|
write("testing no rcpt: ")
|
||
|
local err = SMTP.mail{
|
||
|
from = from,
|
||
|
}
|
||
|
if not err then fail("wrong error message")
|
||
|
else print(err) end
|
||
|
|
||
|
write("clearing mailbox: ")
|
||
|
empty()
|
||
|
print("ok")
|
||
|
|
||
|
write("sending messages: ")
|
||
|
for i = 1, getn(sent) do
|
||
|
err = SMTP.mail(sent[i])
|
||
|
if err then fail(err) end
|
||
|
write("+")
|
||
|
flush(_STDOUT)
|
||
|
end
|
||
|
print("ok")
|
||
|
|
||
|
wait(mark(), total())
|
||
|
|
||
|
write("parsing mailbox: ")
|
||
|
local mbox = parse.mbox(get())
|
||
|
print(getn(mbox) .. " messages found!")
|
||
|
|
||
|
for i = 1, getn(mbox) do
|
||
|
check(sent, mbox[i])
|
||
|
end
|
||
|
|
||
|
|
||
|
print("passed all tests")
|
||
|
print(format("done in %.2fs", _time() - t))
|