Blame


1 ce1bfad9 2024-03-30 thomas /*
2 ce1bfad9 2024-03-30 thomas * Copyright (c) 2024 Stefan Sperling <stsp@openbsd.org>
3 ce1bfad9 2024-03-30 thomas *
4 ce1bfad9 2024-03-30 thomas * Permission to use, copy, modify, and distribute this software for any
5 ce1bfad9 2024-03-30 thomas * purpose with or without fee is hereby granted, provided that the above
6 ce1bfad9 2024-03-30 thomas * copyright notice and this permission notice appear in all copies.
7 ce1bfad9 2024-03-30 thomas *
8 ce1bfad9 2024-03-30 thomas * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 ce1bfad9 2024-03-30 thomas * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 ce1bfad9 2024-03-30 thomas * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 ce1bfad9 2024-03-30 thomas * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 ce1bfad9 2024-03-30 thomas * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 ce1bfad9 2024-03-30 thomas * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 ce1bfad9 2024-03-30 thomas * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 ce1bfad9 2024-03-30 thomas */
16 ce1bfad9 2024-03-30 thomas
17 b2ce1dae 2024-03-30 thomas #include "got_compat.h"
18 b2ce1dae 2024-03-30 thomas
19 ce1bfad9 2024-03-30 thomas #include <sys/types.h>
20 ce1bfad9 2024-03-30 thomas #include <sys/socket.h>
21 ce1bfad9 2024-03-30 thomas
22 efc5c202 2024-03-30 thomas #include <errno.h>
23 5e7fdc36 2024-03-30 thomas #include <poll.h>
24 ce1bfad9 2024-03-30 thomas #include <stdio.h>
25 ce1bfad9 2024-03-30 thomas #include <stdlib.h>
26 ce1bfad9 2024-03-30 thomas #include <string.h>
27 ce1bfad9 2024-03-30 thomas #include <stdarg.h>
28 ce1bfad9 2024-03-30 thomas #include <err.h>
29 ce1bfad9 2024-03-30 thomas #include <pwd.h>
30 ce1bfad9 2024-03-30 thomas #include <netdb.h>
31 ce1bfad9 2024-03-30 thomas #include <time.h>
32 ce1bfad9 2024-03-30 thomas #include <unistd.h>
33 ce1bfad9 2024-03-30 thomas
34 ce1bfad9 2024-03-30 thomas #include "got_error.h"
35 ce1bfad9 2024-03-30 thomas
36 ce1bfad9 2024-03-30 thomas #include "got_lib_poll.h"
37 ce1bfad9 2024-03-30 thomas
38 5e7fdc36 2024-03-30 thomas #define SMTP_LINE_MAX 65535
39 5e7fdc36 2024-03-30 thomas
40 a806a883 2024-03-30 thomas static int smtp_timeout = 60; /* in seconds */
41 5e7fdc36 2024-03-30 thomas static char smtp_buf[SMTP_LINE_MAX];
42 5e7fdc36 2024-03-30 thomas static size_t smtp_buflen;
43 ce1bfad9 2024-03-30 thomas
44 ce1bfad9 2024-03-30 thomas __dead static void
45 ce1bfad9 2024-03-30 thomas usage(void)
46 ce1bfad9 2024-03-30 thomas {
47 16b8fb35 2024-03-30 thomas fprintf(stderr, "usage: %s [-f sender] [-r responder] "
48 ce1bfad9 2024-03-30 thomas "[-s subject] [-h hostname] [-p port] recipient\n", getprogname());
49 ce1bfad9 2024-03-30 thomas exit(1);
50 ce1bfad9 2024-03-30 thomas }
51 ce1bfad9 2024-03-30 thomas
52 efc5c202 2024-03-30 thomas static int
53 efc5c202 2024-03-30 thomas dial(const char *host, const char *port)
54 efc5c202 2024-03-30 thomas {
55 efc5c202 2024-03-30 thomas struct addrinfo hints, *res, *res0;
56 efc5c202 2024-03-30 thomas const char *cause = NULL;
57 efc5c202 2024-03-30 thomas int s, error, save_errno;
58 efc5c202 2024-03-30 thomas
59 efc5c202 2024-03-30 thomas memset(&hints, 0, sizeof(hints));
60 efc5c202 2024-03-30 thomas hints.ai_family = AF_UNSPEC;
61 efc5c202 2024-03-30 thomas hints.ai_socktype = SOCK_STREAM;
62 efc5c202 2024-03-30 thomas error = getaddrinfo(host, port, &hints, &res0);
63 efc5c202 2024-03-30 thomas if (error)
64 efc5c202 2024-03-30 thomas errx(1, "failed to resolve %s:%s: %s", host, port,
65 efc5c202 2024-03-30 thomas gai_strerror(error));
66 efc5c202 2024-03-30 thomas
67 efc5c202 2024-03-30 thomas s = -1;
68 efc5c202 2024-03-30 thomas for (res = res0; res; res = res->ai_next) {
69 efc5c202 2024-03-30 thomas s = socket(res->ai_family, res->ai_socktype,
70 efc5c202 2024-03-30 thomas res->ai_protocol);
71 efc5c202 2024-03-30 thomas if (s == -1) {
72 efc5c202 2024-03-30 thomas cause = "socket";
73 efc5c202 2024-03-30 thomas continue;
74 efc5c202 2024-03-30 thomas }
75 efc5c202 2024-03-30 thomas
76 efc5c202 2024-03-30 thomas if (connect(s, res->ai_addr, res->ai_addrlen) == -1) {
77 efc5c202 2024-03-30 thomas cause = "connect";
78 efc5c202 2024-03-30 thomas save_errno = errno;
79 efc5c202 2024-03-30 thomas close(s);
80 efc5c202 2024-03-30 thomas errno = save_errno;
81 efc5c202 2024-03-30 thomas s = -1;
82 efc5c202 2024-03-30 thomas continue;
83 efc5c202 2024-03-30 thomas }
84 efc5c202 2024-03-30 thomas
85 efc5c202 2024-03-30 thomas break;
86 efc5c202 2024-03-30 thomas }
87 efc5c202 2024-03-30 thomas
88 efc5c202 2024-03-30 thomas freeaddrinfo(res0);
89 efc5c202 2024-03-30 thomas if (s == -1)
90 efc5c202 2024-03-30 thomas err(1, "%s", cause);
91 efc5c202 2024-03-30 thomas return s;
92 efc5c202 2024-03-30 thomas }
93 efc5c202 2024-03-30 thomas
94 ce1bfad9 2024-03-30 thomas static char *
95 ce1bfad9 2024-03-30 thomas set_default_fromaddr(void)
96 ce1bfad9 2024-03-30 thomas {
97 ce1bfad9 2024-03-30 thomas struct passwd *pw = NULL;
98 ce1bfad9 2024-03-30 thomas char *s;
99 ce1bfad9 2024-03-30 thomas char hostname[255];
100 ce1bfad9 2024-03-30 thomas
101 ce1bfad9 2024-03-30 thomas pw = getpwuid(getuid());
102 ce1bfad9 2024-03-30 thomas if (pw == NULL) {
103 ce1bfad9 2024-03-30 thomas errx(1, "my UID %d was not found in password database",
104 ce1bfad9 2024-03-30 thomas getuid());
105 ce1bfad9 2024-03-30 thomas }
106 ce1bfad9 2024-03-30 thomas
107 ce1bfad9 2024-03-30 thomas if (gethostname(hostname, sizeof(hostname)) == -1)
108 ce1bfad9 2024-03-30 thomas err(1, "gethostname");
109 ce1bfad9 2024-03-30 thomas
110 ce1bfad9 2024-03-30 thomas if (asprintf(&s, "%s@%s", pw->pw_name, hostname) == -1)
111 ce1bfad9 2024-03-30 thomas err(1, "asprintf");
112 ce1bfad9 2024-03-30 thomas
113 ce1bfad9 2024-03-30 thomas return s;
114 ce1bfad9 2024-03-30 thomas }
115 ce1bfad9 2024-03-30 thomas
116 ce1bfad9 2024-03-30 thomas static int
117 ce1bfad9 2024-03-30 thomas read_smtp_code(int s, const char *code)
118 ce1bfad9 2024-03-30 thomas {
119 ce1bfad9 2024-03-30 thomas const struct got_error *error;
120 5e7fdc36 2024-03-30 thomas char *endl;
121 5e7fdc36 2024-03-30 thomas size_t linelen;
122 5e7fdc36 2024-03-30 thomas ssize_t r;
123 ce1bfad9 2024-03-30 thomas
124 5e7fdc36 2024-03-30 thomas for (;;) {
125 5e7fdc36 2024-03-30 thomas endl = memmem(smtp_buf, smtp_buflen, "\r\n", 2);
126 5e7fdc36 2024-03-30 thomas if (endl != NULL)
127 5e7fdc36 2024-03-30 thomas break;
128 ce1bfad9 2024-03-30 thomas
129 5e7fdc36 2024-03-30 thomas if (smtp_buflen == sizeof(smtp_buf))
130 5e7fdc36 2024-03-30 thomas errx(1, "line too long");
131 ce1bfad9 2024-03-30 thomas
132 5e7fdc36 2024-03-30 thomas error = got_poll_fd(s, POLLIN, smtp_timeout);
133 ce1bfad9 2024-03-30 thomas if (error)
134 5e7fdc36 2024-03-30 thomas errx(1, "poll: %s", error->msg);
135 5e7fdc36 2024-03-30 thomas
136 5e7fdc36 2024-03-30 thomas r = read(s, smtp_buf + smtp_buflen,
137 5e7fdc36 2024-03-30 thomas sizeof(smtp_buf) - smtp_buflen);
138 5e7fdc36 2024-03-30 thomas if (r == -1)
139 5e7fdc36 2024-03-30 thomas err(1, "read");
140 5e7fdc36 2024-03-30 thomas if (r == 0)
141 5e7fdc36 2024-03-30 thomas errx(1, "unexpected EOF");
142 5e7fdc36 2024-03-30 thomas smtp_buflen += r;
143 ce1bfad9 2024-03-30 thomas }
144 ce1bfad9 2024-03-30 thomas
145 5e7fdc36 2024-03-30 thomas linelen = endl - smtp_buf;
146 5e7fdc36 2024-03-30 thomas if (linelen < 3)
147 5e7fdc36 2024-03-30 thomas errx(1, "invalid SMTP response");
148 5e7fdc36 2024-03-30 thomas
149 5e7fdc36 2024-03-30 thomas if (strncmp(code, smtp_buf, 3) != 0) {
150 5e7fdc36 2024-03-30 thomas smtp_buf[3] = '\0';
151 5e7fdc36 2024-03-30 thomas warnx("unexpected SMTP message code: %s", smtp_buf);
152 5e7fdc36 2024-03-30 thomas return -1;
153 5e7fdc36 2024-03-30 thomas }
154 5e7fdc36 2024-03-30 thomas
155 5e7fdc36 2024-03-30 thomas /*
156 5e7fdc36 2024-03-30 thomas * Normally we would get just one reply, but the regress doesn't
157 5e7fdc36 2024-03-30 thomas * use a real SMTP server and queues all the replies upfront.
158 5e7fdc36 2024-03-30 thomas */
159 5e7fdc36 2024-03-30 thomas linelen += 2;
160 5e7fdc36 2024-03-30 thomas memmove(smtp_buf, smtp_buf + linelen, smtp_buflen - linelen);
161 5e7fdc36 2024-03-30 thomas smtp_buflen -= linelen;
162 5e7fdc36 2024-03-30 thomas
163 5e7fdc36 2024-03-30 thomas return 0;
164 ce1bfad9 2024-03-30 thomas }
165 ce1bfad9 2024-03-30 thomas
166 ce1bfad9 2024-03-30 thomas static int
167 ce1bfad9 2024-03-30 thomas send_smtp_msg(int s, const char *fmt, ...)
168 ce1bfad9 2024-03-30 thomas {
169 ce1bfad9 2024-03-30 thomas const struct got_error *error;
170 ce1bfad9 2024-03-30 thomas char buf[512];
171 ce1bfad9 2024-03-30 thomas int len;
172 ce1bfad9 2024-03-30 thomas va_list ap;
173 ce1bfad9 2024-03-30 thomas
174 ce1bfad9 2024-03-30 thomas va_start(ap, fmt);
175 ce1bfad9 2024-03-30 thomas len = vsnprintf(buf, sizeof(buf), fmt, ap);
176 ce1bfad9 2024-03-30 thomas va_end(ap);
177 ce1bfad9 2024-03-30 thomas if (len < 0) {
178 ce1bfad9 2024-03-30 thomas warn("vsnprintf");
179 ce1bfad9 2024-03-30 thomas return -1;
180 ce1bfad9 2024-03-30 thomas }
181 ce1bfad9 2024-03-30 thomas if (len >= sizeof(buf)) {
182 ce1bfad9 2024-03-30 thomas warnx("%s: buffer too small for message '%s...'",
183 ce1bfad9 2024-03-30 thomas __func__, buf);
184 ce1bfad9 2024-03-30 thomas return -1;
185 ce1bfad9 2024-03-30 thomas }
186 ce1bfad9 2024-03-30 thomas
187 ce1bfad9 2024-03-30 thomas error = got_poll_write_full(s, buf, len);
188 ce1bfad9 2024-03-30 thomas if (error) {
189 ce1bfad9 2024-03-30 thomas warnx("write: %s", error->msg);
190 ce1bfad9 2024-03-30 thomas return -1;
191 ce1bfad9 2024-03-30 thomas }
192 ce1bfad9 2024-03-30 thomas
193 ce1bfad9 2024-03-30 thomas return 0;
194 ce1bfad9 2024-03-30 thomas }
195 ce1bfad9 2024-03-30 thomas
196 ce1bfad9 2024-03-30 thomas static char *
197 ce1bfad9 2024-03-30 thomas get_datestr(time_t *time, char *datebuf)
198 ce1bfad9 2024-03-30 thomas {
199 ce1bfad9 2024-03-30 thomas struct tm mytm, *tm;
200 ce1bfad9 2024-03-30 thomas char *p, *s;
201 ce1bfad9 2024-03-30 thomas
202 ce1bfad9 2024-03-30 thomas tm = gmtime_r(time, &mytm);
203 ce1bfad9 2024-03-30 thomas if (tm == NULL)
204 ce1bfad9 2024-03-30 thomas return NULL;
205 ce1bfad9 2024-03-30 thomas s = asctime_r(tm, datebuf);
206 ce1bfad9 2024-03-30 thomas if (s == NULL)
207 ce1bfad9 2024-03-30 thomas return NULL;
208 ce1bfad9 2024-03-30 thomas p = strchr(s, '\n');
209 ce1bfad9 2024-03-30 thomas if (p)
210 ce1bfad9 2024-03-30 thomas *p = '\0';
211 ce1bfad9 2024-03-30 thomas return s;
212 ce1bfad9 2024-03-30 thomas }
213 ce1bfad9 2024-03-30 thomas
214 ce1bfad9 2024-03-30 thomas static void
215 efc5c202 2024-03-30 thomas send_email(int s, const char *myfromaddr, const char *fromaddr,
216 ce1bfad9 2024-03-30 thomas const char *recipient, const char *replytoaddr,
217 efc5c202 2024-03-30 thomas const char *subject)
218 ce1bfad9 2024-03-30 thomas {
219 ce1bfad9 2024-03-30 thomas const struct got_error *error;
220 ce1bfad9 2024-03-30 thomas char *line = NULL;
221 ce1bfad9 2024-03-30 thomas size_t linesize = 0;
222 ce1bfad9 2024-03-30 thomas ssize_t linelen;
223 ce1bfad9 2024-03-30 thomas time_t now;
224 ce1bfad9 2024-03-30 thomas char datebuf[26];
225 ce1bfad9 2024-03-30 thomas char *datestr;
226 ce1bfad9 2024-03-30 thomas
227 ce1bfad9 2024-03-30 thomas now = time(NULL);
228 ce1bfad9 2024-03-30 thomas datestr = get_datestr(&now, datebuf);
229 ce1bfad9 2024-03-30 thomas
230 ce1bfad9 2024-03-30 thomas if (read_smtp_code(s, "220"))
231 ce1bfad9 2024-03-30 thomas errx(1, "unexpected SMTP greeting received");
232 ce1bfad9 2024-03-30 thomas
233 ce1bfad9 2024-03-30 thomas if (send_smtp_msg(s, "HELO localhost\r\n"))
234 ce1bfad9 2024-03-30 thomas errx(1, "could not send HELO");
235 ce1bfad9 2024-03-30 thomas if (read_smtp_code(s, "250"))
236 ce1bfad9 2024-03-30 thomas errx(1, "unexpected SMTP response received");
237 ce1bfad9 2024-03-30 thomas
238 ce1bfad9 2024-03-30 thomas if (send_smtp_msg(s, "MAIL FROM:<%s>\r\n", myfromaddr))
239 ce1bfad9 2024-03-30 thomas errx(1, "could not send MAIL FROM");
240 ce1bfad9 2024-03-30 thomas if (read_smtp_code(s, "250"))
241 ce1bfad9 2024-03-30 thomas errx(1, "unexpected SMTP response received");
242 ce1bfad9 2024-03-30 thomas
243 ce1bfad9 2024-03-30 thomas if (send_smtp_msg(s, "RCPT TO:<%s>\r\n", recipient))
244 ce1bfad9 2024-03-30 thomas errx(1, "could not send MAIL FROM");
245 ce1bfad9 2024-03-30 thomas if (read_smtp_code(s, "250"))
246 ce1bfad9 2024-03-30 thomas errx(1, "unexpected SMTP response received");
247 ce1bfad9 2024-03-30 thomas
248 ce1bfad9 2024-03-30 thomas if (send_smtp_msg(s, "DATA\r\n"))
249 ce1bfad9 2024-03-30 thomas errx(1, "could not send MAIL FROM");
250 ce1bfad9 2024-03-30 thomas if (read_smtp_code(s, "354"))
251 ce1bfad9 2024-03-30 thomas errx(1, "unexpected SMTP response received");
252 ce1bfad9 2024-03-30 thomas
253 ce1bfad9 2024-03-30 thomas if (send_smtp_msg(s, "From: %s\r\n", fromaddr))
254 ce1bfad9 2024-03-30 thomas errx(1, "could not send From header");
255 ce1bfad9 2024-03-30 thomas if (send_smtp_msg(s, "To: %s\r\n", recipient))
256 ce1bfad9 2024-03-30 thomas errx(1, "could not send To header");
257 ce1bfad9 2024-03-30 thomas if (replytoaddr) {
258 ce1bfad9 2024-03-30 thomas if (send_smtp_msg(s, "Reply-To: %s\r\n", replytoaddr))
259 ce1bfad9 2024-03-30 thomas errx(1, "could not send Reply-To header");
260 ce1bfad9 2024-03-30 thomas }
261 ce1bfad9 2024-03-30 thomas if (send_smtp_msg(s, "Date: %s +0000 (UTC)\r\n", datestr))
262 ce1bfad9 2024-03-30 thomas errx(1, "could not send Date header");
263 ce1bfad9 2024-03-30 thomas
264 ce1bfad9 2024-03-30 thomas if (send_smtp_msg(s, "Subject: %s\r\n", subject))
265 ce1bfad9 2024-03-30 thomas errx(1, "could not send Subject header");
266 ce1bfad9 2024-03-30 thomas
267 ce1bfad9 2024-03-30 thomas if (send_smtp_msg(s, "\r\n"))
268 ce1bfad9 2024-03-30 thomas errx(1, "could not send body delimiter");
269 ce1bfad9 2024-03-30 thomas
270 ce1bfad9 2024-03-30 thomas while ((linelen = getline(&line, &linesize, stdin)) != -1) {
271 ce1bfad9 2024-03-30 thomas if (line[0] == '.') { /* dot stuffing */
272 ce1bfad9 2024-03-30 thomas error = got_poll_write_full(s, ".", 1);
273 ce1bfad9 2024-03-30 thomas if (error)
274 ce1bfad9 2024-03-30 thomas errx(1, "write: %s", error->msg);
275 ce1bfad9 2024-03-30 thomas }
276 ce1bfad9 2024-03-30 thomas error = got_poll_write_full(s, line, linelen);
277 ce1bfad9 2024-03-30 thomas if (error)
278 ce1bfad9 2024-03-30 thomas errx(1, "write: %s", error->msg);
279 ce1bfad9 2024-03-30 thomas }
280 ce1bfad9 2024-03-30 thomas
281 ce1bfad9 2024-03-30 thomas if (send_smtp_msg(s, "\r\n.\r\n"))
282 ce1bfad9 2024-03-30 thomas errx(1, "could not send data terminator");
283 ce1bfad9 2024-03-30 thomas if (read_smtp_code(s, "250"))
284 ce1bfad9 2024-03-30 thomas errx(1, "unexpected SMTP response received");
285 ce1bfad9 2024-03-30 thomas
286 ce1bfad9 2024-03-30 thomas if (send_smtp_msg(s, "QUIT\r\n"))
287 ce1bfad9 2024-03-30 thomas errx(1, "could not send QUIT");
288 ce1bfad9 2024-03-30 thomas
289 ce1bfad9 2024-03-30 thomas if (read_smtp_code(s, "221"))
290 ce1bfad9 2024-03-30 thomas errx(1, "unexpected SMTP response received");
291 ce1bfad9 2024-03-30 thomas
292 ce1bfad9 2024-03-30 thomas close(s);
293 ce1bfad9 2024-03-30 thomas free(line);
294 ce1bfad9 2024-03-30 thomas }
295 ce1bfad9 2024-03-30 thomas
296 ce1bfad9 2024-03-30 thomas int
297 ce1bfad9 2024-03-30 thomas main(int argc, char *argv[])
298 ce1bfad9 2024-03-30 thomas {
299 ce1bfad9 2024-03-30 thomas char *default_fromaddr = NULL;
300 ce1bfad9 2024-03-30 thomas const char *fromaddr = NULL, *recipient = NULL, *replytoaddr = NULL;
301 ce1bfad9 2024-03-30 thomas const char *subject = "gotd notification";
302 ce1bfad9 2024-03-30 thomas const char *hostname = "127.0.0.1";
303 ce1bfad9 2024-03-30 thomas const char *port = "25";
304 ce1bfad9 2024-03-30 thomas const char *errstr;
305 ce1bfad9 2024-03-30 thomas char *timeoutstr;
306 efc5c202 2024-03-30 thomas int ch, s;
307 ce1bfad9 2024-03-30 thomas
308 ce1bfad9 2024-03-30 thomas while ((ch = getopt(argc, argv, "f:r:s:h:p:")) != -1) {
309 ce1bfad9 2024-03-30 thomas switch (ch) {
310 ce1bfad9 2024-03-30 thomas case 'h':
311 ce1bfad9 2024-03-30 thomas hostname = optarg;
312 ce1bfad9 2024-03-30 thomas break;
313 ce1bfad9 2024-03-30 thomas case 'f':
314 ce1bfad9 2024-03-30 thomas fromaddr = optarg;
315 ce1bfad9 2024-03-30 thomas break;
316 ce1bfad9 2024-03-30 thomas case 'p':
317 ce1bfad9 2024-03-30 thomas port = optarg;
318 ce1bfad9 2024-03-30 thomas break;
319 ce1bfad9 2024-03-30 thomas case 'r':
320 ce1bfad9 2024-03-30 thomas replytoaddr = optarg;
321 ce1bfad9 2024-03-30 thomas break;
322 ce1bfad9 2024-03-30 thomas case 's':
323 ce1bfad9 2024-03-30 thomas subject = optarg;
324 ce1bfad9 2024-03-30 thomas break;
325 ce1bfad9 2024-03-30 thomas default:
326 ce1bfad9 2024-03-30 thomas usage();
327 ce1bfad9 2024-03-30 thomas /* NOTREACHED */
328 ce1bfad9 2024-03-30 thomas break;
329 ce1bfad9 2024-03-30 thomas }
330 ce1bfad9 2024-03-30 thomas }
331 ce1bfad9 2024-03-30 thomas
332 ce1bfad9 2024-03-30 thomas argc -= optind;
333 ce1bfad9 2024-03-30 thomas argv += optind;
334 ce1bfad9 2024-03-30 thomas
335 ce1bfad9 2024-03-30 thomas if (argc != 1)
336 ce1bfad9 2024-03-30 thomas usage();
337 ce1bfad9 2024-03-30 thomas
338 ce1bfad9 2024-03-30 thomas /* used by the regression test suite */
339 ce1bfad9 2024-03-30 thomas timeoutstr = getenv("GOT_NOTIFY_EMAIL_TIMEOUT");
340 ce1bfad9 2024-03-30 thomas if (timeoutstr) {
341 ce1bfad9 2024-03-30 thomas smtp_timeout = strtonum(timeoutstr, 0, 600, &errstr);
342 ce1bfad9 2024-03-30 thomas if (errstr != NULL)
343 ce1bfad9 2024-03-30 thomas errx(1, "timeout in seconds is %s: %s",
344 ce1bfad9 2024-03-30 thomas errstr, timeoutstr);
345 ce1bfad9 2024-03-30 thomas }
346 ce1bfad9 2024-03-30 thomas
347 ce1bfad9 2024-03-30 thomas #ifndef PROFILE
348 ce1bfad9 2024-03-30 thomas if (pledge("stdio dns inet getpw", NULL) == -1)
349 ce1bfad9 2024-03-30 thomas err(1, "pledge");
350 ce1bfad9 2024-03-30 thomas #endif
351 ce1bfad9 2024-03-30 thomas default_fromaddr = set_default_fromaddr();
352 ce1bfad9 2024-03-30 thomas
353 ce1bfad9 2024-03-30 thomas #ifndef PROFILE
354 ce1bfad9 2024-03-30 thomas if (pledge("stdio dns inet", NULL) == -1)
355 ce1bfad9 2024-03-30 thomas err(1, "pledge");
356 ce1bfad9 2024-03-30 thomas #endif
357 ce1bfad9 2024-03-30 thomas
358 ce1bfad9 2024-03-30 thomas recipient = argv[0];
359 ce1bfad9 2024-03-30 thomas if (fromaddr == NULL)
360 ce1bfad9 2024-03-30 thomas fromaddr = default_fromaddr;
361 ce1bfad9 2024-03-30 thomas
362 efc5c202 2024-03-30 thomas s = dial(hostname, port);
363 ce1bfad9 2024-03-30 thomas
364 efc5c202 2024-03-30 thomas #ifndef PROFILE
365 efc5c202 2024-03-30 thomas if (pledge("stdio", NULL) == -1)
366 efc5c202 2024-03-30 thomas err(1, "pledge");
367 efc5c202 2024-03-30 thomas #endif
368 efc5c202 2024-03-30 thomas
369 efc5c202 2024-03-30 thomas send_email(s, default_fromaddr, fromaddr, recipient, replytoaddr,
370 efc5c202 2024-03-30 thomas subject);
371 efc5c202 2024-03-30 thomas
372 ce1bfad9 2024-03-30 thomas free(default_fromaddr);
373 ce1bfad9 2024-03-30 thomas return 0;
374 ce1bfad9 2024-03-30 thomas }