diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2008-02-27 09:39:04 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2008-02-27 09:39:04 +0000 |
commit | 8195d20e36bfeeb30b3424e2635ba4757ec38137 (patch) | |
tree | 6226be7f2523f154546f5ad379efb343f57a1ee5 | |
parent | 17db1a9ac1064a4847fd6a381260c68ab3449951 (diff) | |
download | busybox-w32-8195d20e36bfeeb30b3424e2635ba4757ec38137.tar.gz busybox-w32-8195d20e36bfeeb30b3424e2635ba4757ec38137.tar.bz2 busybox-w32-8195d20e36bfeeb30b3424e2635ba4757ec38137.zip |
sendmail: yet another maintainer's update
-rw-r--r-- | include/usage.h | 6 | ||||
-rw-r--r-- | networking/Config.in | 30 | ||||
-rw-r--r-- | networking/sendmail.c | 181 |
3 files changed, 92 insertions, 125 deletions
diff --git a/include/usage.h b/include/usage.h index e9770cea9..95cb69c73 100644 --- a/include/usage.h +++ b/include/usage.h | |||
@@ -1035,10 +1035,8 @@ USE_FEATURE_BRCTL_FANCY("\n" \ | |||
1035 | " -P password Authenticate with specified password\n" \ | 1035 | " -P password Authenticate with specified password\n" \ |
1036 | " -X Use openssl connection helper for secured servers\n" \ | 1036 | " -X Use openssl connection helper for secured servers\n" \ |
1037 | " -t Get only headers\n" \ | 1037 | " -t Get only headers\n" \ |
1038 | " -z Delete messages on server" \ | 1038 | " -z Delete messages on server\n" \ |
1039 | USE_FEATURE_FETCHMAIL_FILTER("\n" \ | 1039 | " prog Run prog <message file> on message delivery" |
1040 | " prog Run prog <message file> on message delivery" \ | ||
1041 | ) | ||
1042 | 1040 | ||
1043 | #define findfs_trivial_usage \ | 1041 | #define findfs_trivial_usage \ |
1044 | "LABEL=label or UUID=uuid" | 1042 | "LABEL=label or UUID=uuid" |
diff --git a/networking/Config.in b/networking/Config.in index 202b65fce..3c53c1115 100644 --- a/networking/Config.in +++ b/networking/Config.in | |||
@@ -678,39 +678,11 @@ config SENDMAIL | |||
678 | help | 678 | help |
679 | Barebones sendmail. | 679 | Barebones sendmail. |
680 | 680 | ||
681 | config FEATURE_SENDMAIL_EHLO | ||
682 | bool "Support EHLO command" | ||
683 | default n | ||
684 | depends on SENDMAIL | ||
685 | help | ||
686 | Support ESMTP EHLO command. | ||
687 | |||
688 | config FEATURE_SENDMAIL_BLOATY | ||
689 | bool "Be more verbose" | ||
690 | default n | ||
691 | depends on SENDMAIL | ||
692 | help | ||
693 | Should be turned off. | ||
694 | |||
695 | config FETCHMAIL | 681 | config FETCHMAIL |
696 | bool "fetchmail" | 682 | bool "fetchmail" |
697 | default n | 683 | default n |
698 | help | 684 | help |
699 | Barebone fetchmail. | 685 | Barebones fetchmail. |
700 | |||
701 | config FEATURE_FETCHMAIL_APOP | ||
702 | bool "Support APOP authentication" | ||
703 | default y | ||
704 | depends on FETCHMAIL | ||
705 | help | ||
706 | Support secure APOP authentication. | ||
707 | |||
708 | config FEATURE_FETCHMAIL_FILTER | ||
709 | bool "Pipe through external filter" | ||
710 | default n | ||
711 | depends on FETCHMAIL | ||
712 | help | ||
713 | Support piping incoming messages through external filter. | ||
714 | 686 | ||
715 | config SLATTACH | 687 | config SLATTACH |
716 | bool "slattach" | 688 | bool "slattach" |
diff --git a/networking/sendmail.c b/networking/sendmail.c index adc6c7626..3a6078f79 100644 --- a/networking/sendmail.c +++ b/networking/sendmail.c | |||
@@ -63,20 +63,13 @@ static void uuencode(char *fname, const char *text) | |||
63 | close(fd); | 63 | close(fd); |
64 | } | 64 | } |
65 | 65 | ||
66 | static const char *const init_xargs[9] = { | ||
67 | "openssl", "s_client", "-quiet", "-connect", | ||
68 | NULL, "-tls1", "-starttls", "smtp" | ||
69 | }; | ||
70 | |||
71 | struct globals { | 66 | struct globals { |
72 | pid_t helper_pid; | 67 | pid_t helper_pid; |
73 | unsigned timeout; | 68 | unsigned timeout; |
74 | // arguments for SSL connection helper | 69 | // arguments for SSL connection helper |
75 | const char *xargs[9]; | 70 | const char *xargs[9]; |
76 | #if ENABLE_FEATURE_FETCHMAIL_FILTER | ||
77 | // arguments for postprocess helper | 71 | // arguments for postprocess helper |
78 | const char *fargs[3]; | 72 | const char *fargs[3]; |
79 | #endif | ||
80 | }; | 73 | }; |
81 | #define G (*ptr_to_globals) | 74 | #define G (*ptr_to_globals) |
82 | #define helper_pid (G.helper_pid) | 75 | #define helper_pid (G.helper_pid) |
@@ -85,16 +78,21 @@ struct globals { | |||
85 | #define fargs (G.fargs ) | 78 | #define fargs (G.fargs ) |
86 | #define INIT_G() do { \ | 79 | #define INIT_G() do { \ |
87 | PTR_TO_GLOBALS = xzalloc(sizeof(G)); \ | 80 | PTR_TO_GLOBALS = xzalloc(sizeof(G)); \ |
88 | memcpy(xargs, init_xargs, sizeof(init_xargs)); \ | 81 | xargs[0] = "openssl"; \ |
82 | xargs[1] = "s_client"; \ | ||
83 | xargs[2] = "-quiet"; \ | ||
84 | xargs[3] = "-connect"; \ | ||
85 | /*xargs[4] = "server[:port]";*/ \ | ||
86 | xargs[5] = "-tls1"; \ | ||
87 | xargs[6] = "-starttls"; \ | ||
88 | xargs[7] = "smtp"; \ | ||
89 | fargs[0] = "utf-8"; \ | 89 | fargs[0] = "utf-8"; \ |
90 | } while (0) | 90 | } while (0) |
91 | 91 | ||
92 | #define opt_connect (xargs[4]) | 92 | #define opt_connect (xargs[4]) |
93 | #define opt_after_connect (xargs[5]) | 93 | #define opt_after_connect (xargs[5]) |
94 | #if ENABLE_FEATURE_FETCHMAIL_FILTER | ||
95 | #define opt_charset (fargs[0]) | 94 | #define opt_charset (fargs[0]) |
96 | #define opt_subject (fargs[1]) | 95 | #define opt_subject (fargs[1]) |
97 | #endif | ||
98 | 96 | ||
99 | static void kill_helper(void) | 97 | static void kill_helper(void) |
100 | { | 98 | { |
@@ -116,11 +114,7 @@ static void signal_handler(int signo) | |||
116 | // SIGCHLD. reap zombies | 114 | // SIGCHLD. reap zombies |
117 | if (wait_any_nohang(&err) > 0) | 115 | if (wait_any_nohang(&err) > 0) |
118 | if (WIFEXITED(err) && WEXITSTATUS(err)) | 116 | if (WIFEXITED(err) && WEXITSTATUS(err)) |
119 | #if ENABLE_FEATURE_SENDMAIL_BLOATY | ||
120 | bb_error_msg_and_die("child exited (%d)", WEXITSTATUS(err)); | 117 | bb_error_msg_and_die("child exited (%d)", WEXITSTATUS(err)); |
121 | #else | ||
122 | bb_error_msg_and_die("child failed"); | ||
123 | #endif | ||
124 | } | 118 | } |
125 | 119 | ||
126 | static void launch_helper(const char **argv) | 120 | static void launch_helper(const char **argv) |
@@ -141,12 +135,11 @@ static void launch_helper(const char **argv) | |||
141 | if (pipes[i] > STDOUT_FILENO) | 135 | if (pipes[i] > STDOUT_FILENO) |
142 | close(pipes[i]); | 136 | close(pipes[i]); |
143 | if (!helper_pid) { | 137 | if (!helper_pid) { |
144 | // child - try to execute connection helper | 138 | // child: try to execute connection helper |
145 | // close(STDERR_FILENO); | ||
146 | BB_EXECVP(*argv, (char **)argv); | 139 | BB_EXECVP(*argv, (char **)argv); |
147 | _exit(127); | 140 | _exit(127); |
148 | } | 141 | } |
149 | // parent - check whether child is alive | 142 | // parent: check whether child is alive |
150 | bb_signals(0 | 143 | bb_signals(0 |
151 | + (1 << SIGCHLD) | 144 | + (1 << SIGCHLD) |
152 | + (1 << SIGALRM) | 145 | + (1 << SIGALRM) |
@@ -155,13 +148,12 @@ static void launch_helper(const char **argv) | |||
155 | // child seems OK -> parent goes on | 148 | // child seems OK -> parent goes on |
156 | } | 149 | } |
157 | 150 | ||
158 | static char *command(const char *fmt, const char *param) | 151 | static const char *command(const char *fmt, const char *param) |
159 | { | 152 | { |
160 | char *msg = (char *)fmt; | 153 | const char *msg = fmt; |
161 | alarm(timeout); | 154 | alarm(timeout); |
162 | if (msg) { | 155 | if (msg) { |
163 | // if (param) | 156 | msg = xasprintf(fmt, param); |
164 | msg = xasprintf(fmt, param); | ||
165 | printf("%s\r\n", msg); | 157 | printf("%s\r\n", msg); |
166 | } | 158 | } |
167 | fflush(stdout); | 159 | fflush(stdout); |
@@ -171,25 +163,20 @@ static char *command(const char *fmt, const char *param) | |||
171 | static int smtp_checkp(const char *fmt, const char *param, int code) | 163 | static int smtp_checkp(const char *fmt, const char *param, int code) |
172 | { | 164 | { |
173 | char *answer; | 165 | char *answer; |
174 | char *msg = command(fmt, param); | 166 | const char *msg = command(fmt, param); |
175 | // read stdin | 167 | // read stdin |
176 | // if the string has a form \d\d\d- -- read next string. E.g. EHLO response | 168 | // if the string has a form \d\d\d- -- read next string. E.g. EHLO response |
177 | // parse first bytes to a number | 169 | // parse first bytes to a number |
178 | // if code = -1 then just return this number | 170 | // if code = -1 then just return this number |
179 | // if code != -1 then checks whether the number equals the code | 171 | // if code != -1 then checks whether the number equals the code |
180 | // if not equal -> die saying msg | 172 | // if not equal -> die saying msg |
181 | #if ENABLE_FEATURE_SENDMAIL_EHLO | ||
182 | while ((answer = xmalloc_getline(stdin)) != NULL) | 173 | while ((answer = xmalloc_getline(stdin)) != NULL) |
183 | if (strlen(answer) <= 3 || '-' != answer[3]) | 174 | if (strlen(answer) <= 3 || '-' != answer[3]) |
184 | break; | 175 | break; |
185 | #else | ||
186 | answer = xmalloc_getline(stdin); | ||
187 | #endif | ||
188 | if (answer) { | 176 | if (answer) { |
189 | int n = atoi(answer); | 177 | int n = atoi(answer); |
190 | alarm(0); | 178 | alarm(0); |
191 | if (ENABLE_FEATURE_CLEAN_UP) { | 179 | if (ENABLE_FEATURE_CLEAN_UP) { |
192 | free(msg); | ||
193 | free(answer); | 180 | free(answer); |
194 | } | 181 | } |
195 | if (-1 == code || n == code) { | 182 | if (-1 == code || n == code) { |
@@ -200,7 +187,7 @@ static int smtp_checkp(const char *fmt, const char *param, int code) | |||
200 | bb_error_msg_and_die("%s failed", msg); | 187 | bb_error_msg_and_die("%s failed", msg); |
201 | } | 188 | } |
202 | 189 | ||
203 | static int smtp_check(const char *fmt, int code) | 190 | static int inline smtp_check(const char *fmt, int code) |
204 | { | 191 | { |
205 | return smtp_checkp(fmt, NULL, code); | 192 | return smtp_checkp(fmt, NULL, code); |
206 | } | 193 | } |
@@ -223,7 +210,7 @@ static char *sane(char *str) | |||
223 | #if ENABLE_FETCHMAIL | 210 | #if ENABLE_FETCHMAIL |
224 | static void pop3_checkr(const char *fmt, const char *param, char **ret) | 211 | static void pop3_checkr(const char *fmt, const char *param, char **ret) |
225 | { | 212 | { |
226 | char *msg = command(fmt, param); | 213 | const char *msg = command(fmt, param); |
227 | char *answer = xmalloc_getline(stdin); | 214 | char *answer = xmalloc_getline(stdin); |
228 | if (answer && '+' == *answer) { | 215 | if (answer && '+' == *answer) { |
229 | alarm(0); | 216 | alarm(0); |
@@ -237,7 +224,7 @@ static void pop3_checkr(const char *fmt, const char *param, char **ret) | |||
237 | bb_error_msg_and_die("%s failed", msg); | 224 | bb_error_msg_and_die("%s failed", msg); |
238 | } | 225 | } |
239 | 226 | ||
240 | static void pop3_check(const char *fmt, const char *param) | 227 | static void inline pop3_check(const char *fmt, const char *param) |
241 | { | 228 | { |
242 | pop3_checkr(fmt, param, NULL); | 229 | pop3_checkr(fmt, param, NULL); |
243 | } | 230 | } |
@@ -249,7 +236,7 @@ static void pop3_message(const char *filename) | |||
249 | // create and open file filename | 236 | // create and open file filename |
250 | // read stdin, copy to created file | 237 | // read stdin, copy to created file |
251 | fd = xopen(filename, O_CREAT | O_WRONLY | O_TRUNC | O_EXCL); | 238 | fd = xopen(filename, O_CREAT | O_WRONLY | O_TRUNC | O_EXCL); |
252 | while ((answer = xmalloc_fgets_str(stdin, "\r\n"))) { | 239 | while ((answer = xmalloc_fgets_str(stdin, "\r\n")) != NULL) { |
253 | char *s = answer; | 240 | char *s = answer; |
254 | if ('.' == *answer) { | 241 | if ('.' == *answer) { |
255 | if ('.' == answer[1]) | 242 | if ('.' == answer[1]) |
@@ -268,10 +255,6 @@ int sendgetmail_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | |||
268 | int sendgetmail_main(int argc, char **argv) | 255 | int sendgetmail_main(int argc, char **argv) |
269 | { | 256 | { |
270 | llist_t *opt_recipients = NULL; | 257 | llist_t *opt_recipients = NULL; |
271 | #if !ENABLE_FEATURE_FETCHMAIL_FILTER | ||
272 | char *opt_subject; | ||
273 | char *opt_charset = (char *)"utf-8"; | ||
274 | #endif | ||
275 | 258 | ||
276 | const char *opt_user; | 259 | const char *opt_user; |
277 | const char *opt_pass; | 260 | const char *opt_pass; |
@@ -295,8 +278,12 @@ int sendgetmail_main(int argc, char **argv) | |||
295 | const char *options; | 278 | const char *options; |
296 | unsigned opts; | 279 | unsigned opts; |
297 | 280 | ||
281 | // init global variables | ||
298 | INIT_G(); | 282 | INIT_G(); |
299 | 283 | ||
284 | // parse options, different option sets for sendmail and fetchmail | ||
285 | // N.B. opt_after_connect hereafter is NULL if we are called as fetchmail | ||
286 | // and is NOT NULL if we are called as sendmail | ||
300 | if (!ENABLE_FETCHMAIL || 's' == applet_name[0]) { | 287 | if (!ENABLE_FETCHMAIL || 's' == applet_name[0]) { |
301 | // SENDMAIL | 288 | // SENDMAIL |
302 | // save initial stdin (body or attachements can be piped!) | 289 | // save initial stdin (body or attachements can be piped!) |
@@ -313,7 +300,6 @@ int sendgetmail_main(int argc, char **argv) | |||
313 | &timeout, &opt_user, &opt_pass, | 300 | &timeout, &opt_user, &opt_pass, |
314 | &opt_subject, &opt_charset, &opt_recipients | 301 | &opt_subject, &opt_charset, &opt_recipients |
315 | ); | 302 | ); |
316 | |||
317 | //argc -= optind; | 303 | //argc -= optind; |
318 | argv += optind; | 304 | argv += optind; |
319 | 305 | ||
@@ -321,20 +307,29 @@ int sendgetmail_main(int argc, char **argv) | |||
321 | opt_connect = *argv++; | 307 | opt_connect = *argv++; |
322 | 308 | ||
323 | // connect to server | 309 | // connect to server |
310 | // SSL ordered? -> | ||
324 | if (opts & OPT_X) { | 311 | if (opts & OPT_X) { |
312 | // ... use openssl helper | ||
325 | launch_helper(xargs); | 313 | launch_helper(xargs); |
314 | // no SSL ordered? -> | ||
326 | } else { | 315 | } else { |
327 | // no connection helper provided -> make plain connect | 316 | // ... make plain connect |
328 | int fd = create_and_connect_stream_or_die(opt_connect, 0); | 317 | int fd = create_and_connect_stream_or_die(opt_connect, 25); |
318 | // make ourselves a simple IO filter | ||
319 | // from now we know nothing about network :) | ||
329 | xmove_fd(fd, STDIN_FILENO); | 320 | xmove_fd(fd, STDIN_FILENO); |
330 | xdup2(STDIN_FILENO, STDOUT_FILENO); | 321 | xdup2(STDIN_FILENO, STDOUT_FILENO); |
331 | } | 322 | } |
332 | 323 | ||
333 | #if ENABLE_FETCHMAIL | 324 | #if ENABLE_FETCHMAIL |
325 | // we are sendmail? | ||
334 | if (opt_after_connect) | 326 | if (opt_after_connect) |
335 | #endif | 327 | #endif |
336 | { | 328 | { |
337 | // SENDMAIL | 329 | /*************************************************** |
330 | * SENDMAIL | ||
331 | ***************************************************/ | ||
332 | |||
338 | char *opt_from; | 333 | char *opt_from; |
339 | int code; | 334 | int code; |
340 | char *boundary; | 335 | char *boundary; |
@@ -342,44 +337,45 @@ int sendgetmail_main(int argc, char **argv) | |||
342 | const char *p; | 337 | const char *p; |
343 | char *q; | 338 | char *q; |
344 | 339 | ||
345 | // wait for initial OK on plain connect | 340 | // we didn't use SSL helper? -> |
346 | if (!(opts & OPT_X)) | 341 | if (!(opts & OPT_X)) { |
342 | // ... wait for initial server OK | ||
347 | smtp_check(NULL, 220); | 343 | smtp_check(NULL, 220); |
344 | } | ||
348 | 345 | ||
349 | // get specified sender | 346 | // get the sender |
350 | opt_from = sane(*argv++); | 347 | opt_from = sane(*argv++); |
351 | 348 | ||
352 | // introduce to server | 349 | // introduce to server |
353 | // should we respect modern (but useless here) EHLO? | 350 | // we should start with modern EHLO |
354 | // or should they respect we wanna be tiny?! | 351 | if (250 != smtp_checkp("EHLO %s", opt_from, -1)) { |
355 | if (!ENABLE_FEATURE_SENDMAIL_EHLO || 250 != smtp_checkp("EHLO %s", opt_from, -1)) { | ||
356 | smtp_checkp("HELO %s", opt_from, 250); | 352 | smtp_checkp("HELO %s", opt_from, 250); |
357 | } | 353 | } |
358 | 354 | ||
359 | // set sender | 355 | // set sender |
360 | // NOTE: if password has not been specified -> | 356 | // NOTE: if password has not been specified |
361 | // no authentication is possible | 357 | // then no authentication is possible |
362 | code = (opts & OPT_P) ? -1 : 250; | 358 | code = (opts & OPT_P) ? -1 : 250; |
363 | // first try softly without authentication | 359 | // first try softly without authentication |
364 | while (250 != smtp_checkp("MAIL FROM:<%s>", opt_from, code)) { | 360 | while (250 != smtp_checkp("MAIL FROM:<%s>", opt_from, code)) { |
365 | // MAIL FROM failed -> authentication needed | 361 | // MAIL FROM failed -> authentication needed |
366 | // do we have username? | 362 | // have we got username? |
367 | if (!(opts & OPT_U)) { | 363 | if (!(opts & OPT_U)) { |
368 | // no! fetch it from "from" option | 364 | // no! fetch it from "from" option |
369 | //opts |= OPT_U; | 365 | //opts |= OPT_U; |
370 | opt_user = xstrdup(opt_from); | 366 | opt_user = xstrdup(opt_from); |
371 | *strchrnul(opt_user, '@') = '\0'; | 367 | *strchrnul(opt_user, '@') = '\0'; |
372 | } | 368 | } |
373 | // now it seems we have username | 369 | // now we've got username |
374 | // try to authenticate | 370 | // so try to authenticate |
375 | if (334 == smtp_check("AUTH LOGIN", -1)) { | 371 | if (334 == smtp_check("AUTH LOGIN", -1)) { |
376 | uuencode(NULL, opt_user); | 372 | uuencode(NULL, opt_user); |
377 | smtp_check("", 334); | 373 | smtp_check("", 334); |
378 | uuencode(NULL, opt_pass); | 374 | uuencode(NULL, opt_pass); |
379 | smtp_check("", 235); | 375 | smtp_check("", 235); |
380 | } | 376 | } |
381 | // authenticated -> retry set sender | 377 | // authenticated OK? -> retry to set sender |
382 | // but now die on failure | 378 | // but this time die on failure! |
383 | code = 250; | 379 | code = 250; |
384 | } | 380 | } |
385 | 381 | ||
@@ -388,13 +384,15 @@ int sendgetmail_main(int argc, char **argv) | |||
388 | smtp_checkp("RCPT TO:<%s>", sane(to->data), 250); | 384 | smtp_checkp("RCPT TO:<%s>", sane(to->data), 250); |
389 | } | 385 | } |
390 | 386 | ||
391 | // now put message | 387 | // enter "put message" mode |
392 | smtp_check("DATA", 354); | 388 | smtp_check("DATA", 354); |
389 | |||
393 | // put address headers | 390 | // put address headers |
394 | printf("From: %s\r\n", opt_from); | 391 | printf("From: %s\r\n", opt_from); |
395 | for (llist_t *to = opt_recipients; to; to = to->link) { | 392 | for (llist_t *to = opt_recipients; to; to = to->link) { |
396 | printf("To: %s\r\n", to->data); | 393 | printf("To: %s\r\n", to->data); |
397 | } | 394 | } |
395 | |||
398 | // put encoded subject | 396 | // put encoded subject |
399 | if (opts & OPTS_c) | 397 | if (opts & OPTS_c) |
400 | sane((char *)opt_charset); | 398 | sane((char *)opt_charset); |
@@ -403,17 +401,17 @@ int sendgetmail_main(int argc, char **argv) | |||
403 | uuencode(NULL, opt_subject); | 401 | uuencode(NULL, opt_subject); |
404 | printf("?=\r\n"); | 402 | printf("?=\r\n"); |
405 | } | 403 | } |
404 | |||
406 | // put notification | 405 | // put notification |
407 | if (opts & OPTS_n) | 406 | if (opts & OPTS_n) |
408 | printf("Disposition-Notification-To: %s\r\n", opt_from); | 407 | printf("Disposition-Notification-To: %s\r\n", opt_from); |
408 | |||
409 | // make a random string -- it will delimit message parts | ||
410 | srand(monotonic_us()); | ||
411 | boundary = xasprintf("%d-%d-%d", rand(), rand(), rand()); | ||
412 | |||
409 | // put common headers and body start | 413 | // put common headers and body start |
410 | // randomize | ||
411 | #if ENABLE_FEATURE_SENDMAIL_BLOATY | ||
412 | srand(time(NULL)); | ||
413 | #endif | ||
414 | boundary = xasprintf("%d-%d-%d", rand(), rand(), rand()); | ||
415 | printf( | 414 | printf( |
416 | USE_FEATURE_SENDMAIL_BLOATY("X-Mailer: busybox " BB_VER " sendmail\r\n") | ||
417 | "Message-ID: <%s>\r\n" | 415 | "Message-ID: <%s>\r\n" |
418 | "Mime-Version: 1.0\r\n" | 416 | "Mime-Version: 1.0\r\n" |
419 | "%smultipart/mixed; boundary=\"%s\"\r\n" | 417 | "%smultipart/mixed; boundary=\"%s\"\r\n" |
@@ -421,8 +419,10 @@ int sendgetmail_main(int argc, char **argv) | |||
421 | , "Content-Type: " | 419 | , "Content-Type: " |
422 | , boundary | 420 | , boundary |
423 | ); | 421 | ); |
424 | // put body + attachment(s) | ||
425 | 422 | ||
423 | // put body + attachment(s) | ||
424 | // N.B. all these weird things just to be tiny | ||
425 | // by reusing string patterns! | ||
426 | fmt = | 426 | fmt = |
427 | "\r\n--%s\r\n" | 427 | "\r\n--%s\r\n" |
428 | "%stext/plain; charset=%s\r\n" | 428 | "%stext/plain; charset=%s\r\n" |
@@ -453,44 +453,50 @@ int sendgetmail_main(int argc, char **argv) | |||
453 | q = bb_get_last_path_component_strip(*argv); | 453 | q = bb_get_last_path_component_strip(*argv); |
454 | } | 454 | } |
455 | 455 | ||
456 | // put terminator | 456 | // put message terminator |
457 | printf("\r\n--%s--\r\n" "\r\n", boundary); | 457 | printf("\r\n--%s--\r\n" "\r\n", boundary); |
458 | if (ENABLE_FEATURE_CLEAN_UP) | ||
459 | free(boundary); | ||
460 | 458 | ||
461 | // end message and say goodbye | 459 | // leave "put message" mode |
462 | smtp_check(".", 250); | 460 | smtp_check(".", 250); |
461 | // ... and say goodbye | ||
463 | smtp_check("QUIT", 221); | 462 | smtp_check("QUIT", 221); |
464 | 463 | ||
465 | #if ENABLE_FETCHMAIL | 464 | #if ENABLE_FETCHMAIL |
466 | } else { | 465 | } else { |
467 | // FETCHMAIL | 466 | /*************************************************** |
467 | * FETCHMAIL | ||
468 | ***************************************************/ | ||
469 | |||
468 | char *buf; | 470 | char *buf; |
469 | unsigned nmsg; | 471 | unsigned nmsg; |
470 | char *hostname; | 472 | char *hostname; |
471 | pid_t pid; | 473 | pid_t pid; |
472 | // cache fetch command | 474 | |
475 | // cache fetch command: | ||
476 | // TOP will return only the headers | ||
477 | // RETR will dump the whole message | ||
473 | const char *retr = (opts & OPTF_t) ? "TOP %u 0" : "RETR %u"; | 478 | const char *retr = (opts & OPTF_t) ? "TOP %u 0" : "RETR %u"; |
474 | 479 | ||
475 | // goto maildir | 480 | // goto maildir |
476 | xchdir(*argv++); | 481 | xchdir(*argv++); |
477 | 482 | ||
478 | #if ENABLE_FEATURE_FETCHMAIL_FILTER | ||
479 | // cache postprocess program | 483 | // cache postprocess program |
480 | *fargs = *argv; | 484 | *fargs = *argv; |
481 | #endif | ||
482 | 485 | ||
483 | // authenticate | 486 | // authenticate |
484 | if (!(opts & OPT_U)) { | 487 | if (!(opts & OPT_U)) { |
485 | //opts |= OPT_U; | 488 | //opts |= OPT_U; |
486 | opt_user = getenv("USER"); | 489 | // N.B. IMHO getenv("USER") can be way easily spoofed! |
490 | opt_user = bb_getpwuid(NULL, -1, getuid()); | ||
487 | } | 491 | } |
488 | #if ENABLE_FEATURE_FETCHMAIL_APOP | 492 | |
493 | // get server greeting | ||
489 | pop3_checkr(NULL, NULL, &buf); | 494 | pop3_checkr(NULL, NULL, &buf); |
495 | |||
490 | // server supports APOP? | 496 | // server supports APOP? |
491 | if ('<' == *buf) { | 497 | if ('<' == *buf) { |
492 | md5_ctx_t md5; | 498 | md5_ctx_t md5; |
493 | // yes. compose <stamp><password> | 499 | // yes! compose <stamp><password> |
494 | char *s = strchr(buf, '>'); | 500 | char *s = strchr(buf, '>'); |
495 | if (s) | 501 | if (s) |
496 | strcpy(s+1, opt_pass); | 502 | strcpy(s+1, opt_pass); |
@@ -512,26 +518,22 @@ int sendgetmail_main(int argc, char **argv) | |||
512 | free(s); | 518 | free(s); |
513 | free(buf-4); // buf is "+OK " away from malloc'ed string | 519 | free(buf-4); // buf is "+OK " away from malloc'ed string |
514 | } | 520 | } |
521 | // server ignores APOP -> use simple text authentication | ||
515 | } else { | 522 | } else { |
516 | #else | ||
517 | { | ||
518 | pop3_check(NULL, NULL); | ||
519 | #endif | ||
520 | // USER | 523 | // USER |
521 | pop3_check("USER %s", opt_user); | 524 | pop3_check("USER %s", opt_user); |
522 | // PASS | 525 | // PASS |
523 | pop3_check("PASS %s", opt_pass); | 526 | pop3_check("PASS %s", opt_pass); |
524 | } | 527 | } |
525 | 528 | ||
526 | // get statistics | 529 | // get mailbox statistics |
527 | pop3_checkr("STAT", NULL, &buf); | 530 | pop3_checkr("STAT", NULL, &buf); |
528 | 531 | ||
529 | // prepare message filename suffix | 532 | // prepare message filename suffix |
530 | hostname = xzalloc(MAXHOSTNAMELEN+1); | 533 | hostname = safe_gethostname(); |
531 | gethostname(hostname, MAXHOSTNAMELEN); | ||
532 | pid = getpid(); | 534 | pid = getpid(); |
533 | 535 | ||
534 | // get number of messages | 536 | // get messages counter |
535 | // NOTE: we don't use xatou(buf) since buf is "nmsg nbytes" | 537 | // NOTE: we don't use xatou(buf) since buf is "nmsg nbytes" |
536 | // we only need nmsg and atoi is just exactly what we need | 538 | // we only need nmsg and atoi is just exactly what we need |
537 | // if atoi fails to convert buf into number it returns 0 | 539 | // if atoi fails to convert buf into number it returns 0 |
@@ -542,19 +544,19 @@ int sendgetmail_main(int argc, char **argv) | |||
542 | 544 | ||
543 | // loop through messages | 545 | // loop through messages |
544 | for (; nmsg; nmsg--) { | 546 | for (; nmsg; nmsg--) { |
547 | |||
548 | // generate unique filename | ||
545 | char *filename = xasprintf("tmp/%llu.%u.%s", monotonic_us(), pid, hostname); | 549 | char *filename = xasprintf("tmp/%llu.%u.%s", monotonic_us(), pid, hostname); |
546 | char *target; | 550 | char *target; |
547 | #if ENABLE_FEATURE_FETCHMAIL_FILTER | 551 | int rc; |
548 | int rc; | 552 | |
549 | #endif | 553 | // retrieve message in ./tmp/ |
550 | // retrieve message in ./tmp | ||
551 | pop3_check(retr, (const char *)nmsg); | 554 | pop3_check(retr, (const char *)nmsg); |
552 | pop3_message(filename); | 555 | pop3_message(filename); |
553 | // delete message from server | 556 | // delete message from server |
554 | if (opts & OPTF_z) | 557 | if (opts & OPTF_z) |
555 | pop3_check("DELE %u", (const char*)nmsg); | 558 | pop3_check("DELE %u", (const char*)nmsg); |
556 | 559 | ||
557 | #if ENABLE_FEATURE_FETCHMAIL_FILTER | ||
558 | // run postprocessing program | 560 | // run postprocessing program |
559 | if (*fargs) { | 561 | if (*fargs) { |
560 | fargs[1] = filename; | 562 | fargs[1] = filename; |
@@ -564,23 +566,18 @@ int sendgetmail_main(int argc, char **argv) | |||
564 | if (1 == rc) | 566 | if (1 == rc) |
565 | goto skip; | 567 | goto skip; |
566 | } | 568 | } |
567 | #endif | 569 | |
568 | // atomically move message to ./new | 570 | // atomically move message to ./new/ |
569 | target = xstrdup(filename); | 571 | target = xstrdup(filename); |
570 | strncpy(target, "new", 3); | 572 | strncpy(target, "new", 3); |
571 | // ... or just stop receiving on error | 573 | // ... or just stop receiving on error |
572 | if (rename_or_warn(filename, target)) | 574 | if (rename_or_warn(filename, target)) |
573 | break; | 575 | break; |
574 | free(target); | 576 | free(target); |
575 | #if ENABLE_FEATURE_FETCHMAIL_FILTER | ||
576 | skip: | 577 | skip: |
577 | #endif | ||
578 | free(filename); | 578 | free(filename); |
579 | } | 579 | } |
580 | 580 | ||
581 | if (ENABLE_FEATURE_CLEAN_UP) | ||
582 | free(hostname); | ||
583 | |||
584 | // Bye | 581 | // Bye |
585 | pop3_check("QUIT", NULL); | 582 | pop3_check("QUIT", NULL); |
586 | #endif // ENABLE_FETCHMAIL | 583 | #endif // ENABLE_FETCHMAIL |