util-soc.lua /size: 4558 b    last modification: 2020-07-01 14:35
1if not modules then modules = { } end modules ['util-soc'] = {
2    version   = 1.001,
3    comment   = "support for sockets / protocols",
4    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
5    copyright = "PRAGMA ADE / ConTeXt Development Team",
6    license   = "see context related readme files"
7}
8
9--[[--
10
11In LuaTeX we provide the socket library that is more or less the standard one for
12Lua. It has been around for a while and seems to be pretty stable. The binary
13module is copmpiled into LuaTeX and the accompanying .lua files are preloaded.
14These files are mostly written by Diego Nehab, Andre Carregal, Javier Guerra, and
15Fabio Mascarenhas with contributions from Diego Nehab, Mike Pall, David Burgess,
16Leonardo Godinho, Thomas Harning Jr., and Gary NG. The originals are part of and
17copyrighted by the Kepler project.
18
19Here we reload a slightly reworked version of these .lua files. We keep the same
20(documented) interface but streamlined some fo the code. No more modules, no more
21pre 5.2 Lua, etc. Also, as it loads into the ConTeXt ecosystem, we plug in some
22logging. (and maybe tracing in the future). As we don't support serial ports in
23LuaTeX, related code has been dropped.
24
25The files are reformatted so that we can more easilly add additional features
26and/or tracing options. Any error introduced there is our fault! The url module
27might be replaced by the one in ConTeXt. When we need mbox a suitable variant
28will be provided.
29
30--]]--
31
32local format = string.format
33
34local smtp  = require("socket.smtp")
35local ltn12 = require("ltn12")
36local mime  = require("mime")
37
38local mail     = utilities.mail or { }
39utilities.mail = mail
40
41local report_mail = logs.reporter("mail")
42
43function mail.send(specification)
44    local presets = specification.presets
45    if presets then
46        table.setmetatableindex(specification,presets)
47    end
48    local server = specification.server or ""
49    if not server then
50        report_mail("no server specified")
51        return false, "invalid server"
52    end
53    local to = specification.to or specification.recepient or ""
54    if to == "" then
55        report_mail("no recipient specified")
56        return false, "invalid recipient"
57    end
58    local from = specification.from or specification.sender or ""
59    if from == "" then
60        report_mail("no sender specified")
61        return false, "invalid sender"
62    end
63    local message = { }
64    local body = specification.body
65    if body then
66        message[#message+1] = {
67            body = body
68        }
69    end
70    local files = specification.files
71    if files then
72        for i=1,#files do
73            local filename = files[i]
74            local handle = io.open(filename, "rb")
75            if handle then
76                report_mail("attaching file %a",filename)
77                message[#message+1] = {
78                    headers = {
79                        ["content-type"]              = format('application/pdf; name="%s"',filename),
80                        ["content-disposition"]       = format('attachment; filename="%s"',filename),
81                        ["content-description"]       = format('file: %s',filename),
82                        ["content-transfer-encoding"] = "BASE64"
83                    },
84                    body = ltn12.source.chain(
85                        ltn12.source.file(handle),
86                        ltn12.filter.chain(mime.encode("base64"),mime.wrap())
87                    )
88                }
89            else
90                report_mail("file %a not found",filename)
91            end
92        end
93    end
94    local user     = specification.user
95    local password = specification.password
96    local result, detail = smtp.send {
97        server   = specification.server,
98        port     = specification.port,
99        user     = user ~= "" and user or nil,
100        password = password ~= "" and password or nil,
101        from     = from,
102        rcpt     = to,
103        source   = smtp.message {
104            headers = {
105                to      = to,
106                from    = from,
107                cc      = specification.cc,
108                subject = specification.subject or "no subject",
109            },
110            body = message
111        },
112    }
113    if detail then
114        report_mail("error: %s",detail)
115        return false, detail
116    else
117        report_mail("message sent")
118        return true
119    end
120end
121
122-- for now we have this here:
123
124if socket then
125
126    math.initialseed = tonumber(string.sub(string.reverse(tostring(math.ceil(socket.gettime()*10000))),1,6))
127    math.randomseed(math.initialseed)
128
129end
130