root/src/modules-lua/noit/module/smtp.lua

Revision b8e4ac4354d8201d78c1a9166c597998bcb3167c, 4.0 kB (checked in by Theo Schlossnagle <jesus@omniti.com>, 6 years ago)

more docs, fixups.. Better smtp options and docs. refs #21

  • Property mode set to 100644
Line 
1 module(..., package.seeall)
2
3 function onload(image)
4   image.xml_description([=[
5 <module>
6   <name>smtp</name>
7   <description><para>Send an email via an SMTP server.</para></description>
8   <loader>lua</loader>
9   <object>noit.module.smtp</object>
10   <moduleconfig />
11   <checkconfig>
12     <parameter name="port" required="optional" default="25"
13                allowed="\d+">Specifies the TCP port to connect to.</parameter>
14     <parameter name="ehlo" required="optional" default="noit.local"
15                allowed="\d+">Specifies the EHLO parameter.</parameter>
16     <parameter name="from" required="optional" default=""
17                allowed="\d+">Specifies the envelope sender.</parameter>
18     <parameter name="to" required="required"
19                allowed="\d+">Specifies the envelope recipient.</parameter>
20     <parameter name="payload" required="optional" default="Subject: Testing"
21                allowed="\d+">Specifies the payload sent (on the wire). CR LF DOT CR LF is appended automatically.</parameter>
22   </checkconfig>
23   <examples>
24     <example>
25       <title>Send an email to test SMTP service.</title>
26       <para>The following example sends an email via 10.80.117.6 from test@omniti.com to devnull@omniti.com</para>
27       <programlisting><![CDATA[
28       <noit>
29         <modules>
30           <loader image="lua" name="lua">
31             <config><directory>/opt/reconnoiter/libexec/modules-lua/?.lua</directory></config>
32           </loader>
33           <module loader="lua" name="smtp" object="noit.module.smtp"/>
34         </modules>
35         <checks>
36           <check uuid="2d42adbc-7c7a-11dd-a48f-4f59e0b654d3" module="smtp" target="10.80.117.6">
37             <config>
38               <from>test@omniti.com</from>
39               <to>devnull@omniti.com</to>
40             </config>
41           </check>
42         </checks>
43       </noit>
44       ]]></programlisting>
45     </example>
46   </examples>
47 </module>
48 ]=]);
49   return 0
50 end
51
52 function init(module)
53   return 0
54 end
55
56 function config(module, options)
57   return 0
58 end
59
60 local function read_cmd(e)
61   local final_status, out
62   final_status, out = 0, ""
63   repeat
64     local str = e.read("\r\n")
65     local status, c, message = string.match(str, "^(%d+)([-%s])(.+)$")
66     if not status then
67       return 421, "[internal error]"
68     end
69     final_status = status
70     if string.len(out) > 0 then
71       out = string.format( "%s %s", out, message)
72     else
73       out = message
74     end
75   until c ~= "-"
76   return (final_status+0), out
77 end
78
79 local function write_cmd(e, cmd)
80   e.write(cmd);
81   e.write("\r\n");
82 end
83
84 local function mkaction(e, check)
85   return function (phase, tosend, expected_code)
86     local start_time = noit.timeval.now()
87     local success = true
88     if tosend then
89       write_cmd(e, tosend)
90     end
91     local actual_code, message = read_cmd(e)
92     if expected_code ~= actual_code then
93       check.status(string.format("%d/%d %s", expected_code, actual_code, message))
94       check.bad()
95       success = false
96     else
97       check.available()
98     end
99     local elapsed = noit.timeval.now() - start_time
100     local elapsed_ms = math.floor(tostring(elapsed) * 1000)
101     check.metric(phase .. "_time",  elapsed_ms)
102     return success
103   end
104 end
105
106 function initiate(module, check)
107   local e = noit.socket()
108   local rv, err = e.connect(check.target, check.config.port or 25)
109   check.unavailable()
110
111   if rv ~= 0 then
112     check.bad()
113     check.status(err or message or "no connection")
114     return
115   end
116
117   local ehlo = string.format("EHLO %s", check.config.ehlo or "noit.local")
118   local mailfrom = string.format("MAIL FROM:<%s>", check.config.from or "")
119   local rcptto = string.format("RCPT TO:<%s>", check.config.to)
120   local payload = check.config.payload or "Subject: Test\n\nHello."
121   payload = payload:gsub("\n", "\r\n")
122   local action = mkaction(e, check)
123   if     action("banner", nil, 220)
124      and action("ehlo", ehlo, 250)
125      and action("mailfrom", mailfrom, 250)
126      and action("rcptto", rcptto, 250)
127      and action("data", "DATA", 354)
128      and action("body", payload .. "\r\n.", 250)
129      and action("quit", "QUIT", 221)
130   then
131     check.status("mail sent")
132     check.good()
133   end
134 end
135
Note: See TracBrowser for help on using the browser.