smtptest.lua 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. local sent = {}
  2. local from = "diego@localhost"
  3. local server = "localhost"
  4. local rcpt = "luasocket@localhost"
  5. local files = {
  6. "/var/spool/mail/luasocket",
  7. "/var/spool/mail/luasock1",
  8. "/var/spool/mail/luasock2",
  9. "/var/spool/mail/luasock3",
  10. }
  11. local t = socket.time()
  12. local err
  13. dofile("mbox.lua")
  14. local parse = mbox.parse
  15. dofile("testsupport.lua")
  16. local total = function()
  17. local t = 0
  18. for i = 1, #sent do
  19. t = t + sent[i].count
  20. end
  21. return t
  22. end
  23. local similar = function(s1, s2)
  24. return
  25. string.lower(string.gsub(s1, "%s", "")) ==
  26. string.lower(string.gsub(s2, "%s", ""))
  27. end
  28. local fail = function(s)
  29. s = s or "failed!"
  30. print(s)
  31. os.exit()
  32. end
  33. local readfile = function(name)
  34. local f = io.open(name, "r")
  35. if not f then
  36. fail("unable to open file!")
  37. return nil
  38. end
  39. local s = f:read("*a")
  40. f:close()
  41. return s
  42. end
  43. local empty = function()
  44. for i,v in ipairs(files) do
  45. local f = io.open(v, "w")
  46. if not f then
  47. fail("unable to open file!")
  48. end
  49. f:close()
  50. end
  51. end
  52. local get = function()
  53. local s = ""
  54. for i,v in ipairs(files) do
  55. s = s .. "\n" .. readfile(v)
  56. end
  57. return s
  58. end
  59. local check_headers = function(sent, got)
  60. sent = sent or {}
  61. got = got or {}
  62. for i,v in pairs(sent) do
  63. if not similar(v, got[i]) then fail("header " .. v .. "failed!") end
  64. end
  65. end
  66. local check_body = function(sent, got)
  67. sent = sent or ""
  68. got = got or ""
  69. if not similar(sent, got) then fail("bodies differ!") end
  70. end
  71. local check = function(sent, m)
  72. io.write("checking ", m.headers.title, ": ")
  73. for i = 1, #sent do
  74. local s = sent[i]
  75. if s.title == m.headers.title and s.count > 0 then
  76. check_headers(s.headers, m.headers)
  77. check_body(s.body, m.body)
  78. s.count = s.count - 1
  79. print("ok")
  80. return
  81. end
  82. end
  83. fail("not found")
  84. end
  85. local insert = function(sent, message)
  86. if type(message.rcpt) == "table" then
  87. message.count = #message.rcpt
  88. else message.count = 1 end
  89. message.headers = message.headers or {}
  90. message.headers.title = message.title
  91. table.insert(sent, message)
  92. end
  93. local mark = function()
  94. local time = socket.time()
  95. return { time = time }
  96. end
  97. local wait = function(sentinel, n)
  98. local to
  99. io.write("waiting for ", n, " messages: ")
  100. while 1 do
  101. local mbox = parse(get())
  102. if n == #mbox then break end
  103. if socket.time() - sentinel.time > 50 then
  104. to = 1
  105. break
  106. end
  107. socket.sleep(1)
  108. io.write(".")
  109. io.stdout:flush()
  110. end
  111. if to then fail("timeout")
  112. else print("ok") end
  113. end
  114. local stuffed_body = [[
  115. This message body needs to be
  116. stuffed because it has a dot
  117. .
  118. by itself on a line.
  119. Otherwise the mailer would
  120. think that the dot
  121. .
  122. is the end of the message
  123. and the remaining text would cause
  124. a lot of trouble.
  125. ]]
  126. insert(sent, {
  127. from = from,
  128. rcpt = {
  129. "luasocket@localhost",
  130. "[email protected]",
  131. "[email protected]"
  132. },
  133. body = "multiple rcpt body",
  134. title = "multiple rcpt",
  135. })
  136. insert(sent, {
  137. from = from,
  138. rcpt = {
  139. "luasock2@localhost",
  140. "luasock3",
  141. "luasock1"
  142. },
  143. headers = {
  144. header1 = "header 1",
  145. header2 = "header 2",
  146. header3 = "header 3",
  147. header4 = "header 4",
  148. header5 = "header 5",
  149. header6 = "header 6",
  150. },
  151. body = stuffed_body,
  152. title = "complex message",
  153. })
  154. insert(sent, {
  155. from = from,
  156. rcpt = rcpt,
  157. server = server,
  158. body = "simple message body",
  159. title = "simple message"
  160. })
  161. insert(sent, {
  162. from = from,
  163. rcpt = rcpt,
  164. server = server,
  165. body = stuffed_body,
  166. title = "stuffed message body"
  167. })
  168. insert(sent, {
  169. from = from,
  170. rcpt = rcpt,
  171. headers = {
  172. header1 = "header 1",
  173. header2 = "header 2",
  174. header3 = "header 3",
  175. header4 = "header 4",
  176. header5 = "header 5",
  177. header6 = "header 6",
  178. },
  179. title = "multiple headers"
  180. })
  181. insert(sent, {
  182. from = from,
  183. rcpt = rcpt,
  184. title = "minimum message"
  185. })
  186. io.write("testing host not found: ")
  187. local c, e = socket.connect("wrong.host", 25)
  188. local ret, err = socket.smtp.mail{
  189. from = from,
  190. rcpt = rcpt,
  191. server = "wrong.host"
  192. }
  193. if ret or e ~= err then fail("wrong error message")
  194. else print("ok") end
  195. io.write("testing invalid from: ")
  196. local ret, err = socket.smtp.mail{
  197. from = ' " " (( _ * ',
  198. rcpt = rcpt,
  199. }
  200. if ret or not err then fail("wrong error message")
  201. else print(err) end
  202. io.write("testing no rcpt: ")
  203. local ret, err = socket.smtp.mail{
  204. from = from,
  205. }
  206. if ret or not err then fail("wrong error message")
  207. else print(err) end
  208. io.write("clearing mailbox: ")
  209. empty()
  210. print("ok")
  211. io.write("sending messages: ")
  212. for i = 1, #sent do
  213. ret, err = socket.smtp.mail(sent[i])
  214. if not ret then fail(err) end
  215. io.write("+")
  216. io.stdout:flush()
  217. end
  218. print("ok")
  219. wait(mark(), total())
  220. io.write("parsing mailbox: ")
  221. local mbox = parse(get())
  222. print(#mbox .. " messages found!")
  223. for i = 1, #mbox do
  224. check(sent, mbox[i])
  225. end
  226. print("passed all tests")
  227. print(string.format("done in %.2fs", socket.time() - t))