源战役客户端
25'ten fazla konu seçemezsiniz Konular bir harf veya rakamla başlamalı, kısa çizgiler ('-') içerebilir ve en fazla 35 karakter uzunluğunda olabilir.

255 satır
8.6 KiB

  1. -- -----------------------------------------------------------------------------
  2. -- -- SMTP client support for the Lua language.
  3. -- -- LuaSocket toolkit.
  4. -- -- Author: Diego Nehab
  5. -- -----------------------------------------------------------------------------
  6. -- -----------------------------------------------------------------------------
  7. -- -- Declare module and import dependencies
  8. -- -----------------------------------------------------------------------------
  9. -- local base = _G
  10. -- local coroutine = require("coroutine")
  11. -- local string = require("string")
  12. -- local math = require("math")
  13. -- local os = require("os")
  14. -- local socket = require("socket")
  15. -- local tp = require("socket.tp")
  16. -- local ltn12 = require("ltn12")
  17. -- local headers = require("socket.headers")
  18. -- local mime = require("mime")
  19. -- socket.smtp = {}
  20. -- local _M = socket.smtp
  21. -- -----------------------------------------------------------------------------
  22. -- -- Program constants
  23. -- -----------------------------------------------------------------------------
  24. -- -- timeout for connection
  25. -- _M.TIMEOUT = 60
  26. -- -- default server used to send e-mails
  27. -- _M.SERVER = "localhost"
  28. -- -- default port
  29. -- _M.PORT = 25
  30. -- -- domain used in HELO command and default sendmail
  31. -- -- If we are under a CGI, try to get from environment
  32. -- _M.DOMAIN = os.getenv("SERVER_NAME") or "localhost"
  33. -- -- default time zone (means we don't know)
  34. -- _M.ZONE = "-0000"
  35. -- ---------------------------------------------------------------------------
  36. -- -- Low level SMTP API
  37. -- -----------------------------------------------------------------------------
  38. -- local metat = { __index = {} }
  39. -- function metat.__index:greet(domain)
  40. -- self.try(self.tp:check("2.."))
  41. -- self.try(self.tp:command("EHLO", domain or _M.DOMAIN))
  42. -- return socket.skip(1, self.try(self.tp:check("2..")))
  43. -- end
  44. -- function metat.__index:mail(from)
  45. -- self.try(self.tp:command("MAIL", "FROM:" .. from))
  46. -- return self.try(self.tp:check("2.."))
  47. -- end
  48. -- function metat.__index:rcpt(to)
  49. -- self.try(self.tp:command("RCPT", "TO:" .. to))
  50. -- return self.try(self.tp:check("2.."))
  51. -- end
  52. -- function metat.__index:data(src, step)
  53. -- self.try(self.tp:command("DATA"))
  54. -- self.try(self.tp:check("3.."))
  55. -- self.try(self.tp:source(src, step))
  56. -- self.try(self.tp:send("\r\n.\r\n"))
  57. -- return self.try(self.tp:check("2.."))
  58. -- end
  59. -- function metat.__index:quit()
  60. -- self.try(self.tp:command("QUIT"))
  61. -- return self.try(self.tp:check("2.."))
  62. -- end
  63. -- function metat.__index:close()
  64. -- return self.tp:close()
  65. -- end
  66. -- function metat.__index:login(user, password)
  67. -- self.try(self.tp:command("AUTH", "LOGIN"))
  68. -- self.try(self.tp:check("3.."))
  69. -- self.try(self.tp:send(mime.b64(user) .. "\r\n"))
  70. -- self.try(self.tp:check("3.."))
  71. -- self.try(self.tp:send(mime.b64(password) .. "\r\n"))
  72. -- return self.try(self.tp:check("2.."))
  73. -- end
  74. -- function metat.__index:plain(user, password)
  75. -- local auth = "PLAIN " .. mime.b64("\0" .. user .. "\0" .. password)
  76. -- self.try(self.tp:command("AUTH", auth))
  77. -- return self.try(self.tp:check("2.."))
  78. -- end
  79. -- function metat.__index:auth(user, password, ext)
  80. -- if not user or not password then return 1 end
  81. -- if string.find(ext, "AUTH[^\n]+LOGIN") then
  82. -- return self:login(user, password)
  83. -- elseif string.find(ext, "AUTH[^\n]+PLAIN") then
  84. -- return self:plain(user, password)
  85. -- else
  86. -- self.try(nil, "authentication not supported")
  87. -- end
  88. -- end
  89. -- -- send message or throw an exception
  90. -- function metat.__index:send(mailt)
  91. -- self:mail(mailt.from)
  92. -- if base.type(mailt.rcpt) == "table" then
  93. -- for i,v in base.ipairs(mailt.rcpt) do
  94. -- self:rcpt(v)
  95. -- end
  96. -- else
  97. -- self:rcpt(mailt.rcpt)
  98. -- end
  99. -- self:data(ltn12.source.chain(mailt.source, mime.stuff()), mailt.step)
  100. -- end
  101. -- function _M.open(server, port, create)
  102. -- local tp = socket.try(tp.connect(server or _M.SERVER, port or _M.PORT,
  103. -- _M.TIMEOUT, create))
  104. -- local s = base.setmetatable({tp = tp}, metat)
  105. -- -- make sure tp is closed if we get an exception
  106. -- s.try = socket.newtry(function()
  107. -- s:close()
  108. -- end)
  109. -- return s
  110. -- end
  111. -- -- convert headers to lowercase
  112. -- local function lower_headers(headers)
  113. -- local lower = {}
  114. -- for i,v in base.pairs(headers or lower) do
  115. -- lower[string.lower(i)] = v
  116. -- end
  117. -- return lower
  118. -- end
  119. -- ---------------------------------------------------------------------------
  120. -- -- Multipart message source
  121. -- -----------------------------------------------------------------------------
  122. -- -- returns a hopefully unique mime boundary
  123. -- local seqno = 0
  124. -- local function newboundary()
  125. -- seqno = seqno + 1
  126. -- return string.format('%s%05d==%05u', os.date('%d%m%Y%H%M%S'),
  127. -- math.random(0, 99999), seqno)
  128. -- end
  129. -- -- send_message forward declaration
  130. -- local send_message
  131. -- -- yield the headers all at once, it's faster
  132. -- local function send_headers(tosend)
  133. -- local canonic = headers.canonic
  134. -- local h = "\r\n"
  135. -- for f,v in base.pairs(tosend) do
  136. -- h = (canonic[f] or f) .. ': ' .. v .. "\r\n" .. h
  137. -- end
  138. -- coroutine.yield(h)
  139. -- end
  140. -- -- yield multipart message body from a multipart message table
  141. -- local function send_multipart(mesgt)
  142. -- -- make sure we have our boundary and send headers
  143. -- local bd = newboundary()
  144. -- local headers = lower_headers(mesgt.headers or {})
  145. -- headers['content-type'] = headers['content-type'] or 'multipart/mixed'
  146. -- headers['content-type'] = headers['content-type'] ..
  147. -- '; boundary="' .. bd .. '"'
  148. -- send_headers(headers)
  149. -- -- send preamble
  150. -- if mesgt.body.preamble then
  151. -- coroutine.yield(mesgt.body.preamble)
  152. -- coroutine.yield("\r\n")
  153. -- end
  154. -- -- send each part separated by a boundary
  155. -- for i, m in base.ipairs(mesgt.body) do
  156. -- coroutine.yield("\r\n--" .. bd .. "\r\n")
  157. -- send_message(m)
  158. -- end
  159. -- -- send last boundary
  160. -- coroutine.yield("\r\n--" .. bd .. "--\r\n\r\n")
  161. -- -- send epilogue
  162. -- if mesgt.body.epilogue then
  163. -- coroutine.yield(mesgt.body.epilogue)
  164. -- coroutine.yield("\r\n")
  165. -- end
  166. -- end
  167. -- -- yield message body from a source
  168. -- local function send_source(mesgt)
  169. -- -- make sure we have a content-type
  170. -- local headers = lower_headers(mesgt.headers or {})
  171. -- headers['content-type'] = headers['content-type'] or
  172. -- 'text/plain; charset="iso-8859-1"'
  173. -- send_headers(headers)
  174. -- -- send body from source
  175. -- while true do
  176. -- local chunk, err = mesgt.body()
  177. -- if err then coroutine.yield(nil, err)
  178. -- elseif chunk then coroutine.yield(chunk)
  179. -- else break end
  180. -- end
  181. -- end
  182. -- -- yield message body from a string
  183. -- local function send_string(mesgt)
  184. -- -- make sure we have a content-type
  185. -- local headers = lower_headers(mesgt.headers or {})
  186. -- headers['content-type'] = headers['content-type'] or
  187. -- 'text/plain; charset="iso-8859-1"'
  188. -- send_headers(headers)
  189. -- -- send body from string
  190. -- coroutine.yield(mesgt.body)
  191. -- end
  192. -- -- message source
  193. -- function send_message(mesgt)
  194. -- if base.type(mesgt.body) == "table" then send_multipart(mesgt)
  195. -- elseif base.type(mesgt.body) == "function" then send_source(mesgt)
  196. -- else send_string(mesgt) end
  197. -- end
  198. -- -- set defaul headers
  199. -- local function adjust_headers(mesgt)
  200. -- local lower = lower_headers(mesgt.headers)
  201. -- lower["date"] = lower["date"] or
  202. -- os.date("!%a, %d %b %Y %H:%M:%S ") .. (mesgt.zone or _M.ZONE)
  203. -- lower["x-mailer"] = lower["x-mailer"] or socket._VERSION
  204. -- -- this can't be overriden
  205. -- lower["mime-version"] = "1.0"
  206. -- return lower
  207. -- end
  208. -- function _M.message(mesgt)
  209. -- mesgt.headers = adjust_headers(mesgt)
  210. -- -- create and return message source
  211. -- local co = coroutine.create(function() send_message(mesgt) end)
  212. -- return function()
  213. -- local ret, a, b = coroutine.resume(co)
  214. -- if ret then return a, b
  215. -- else return nil, a end
  216. -- end
  217. -- end
  218. -- ---------------------------------------------------------------------------
  219. -- -- High level SMTP API
  220. -- -----------------------------------------------------------------------------
  221. -- _M.send = socket.protect(function(mailt)
  222. -- local s = _M.open(mailt.server, mailt.port, mailt.create)
  223. -- local ext = s:greet(mailt.domain)
  224. -- s:auth(mailt.user, mailt.password, ext)
  225. -- s:send(mailt)
  226. -- s:quit()
  227. -- return s:close()
  228. -- end)
  229. -- return _M