diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2008-09-27 14:01:22 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2008-09-27 14:01:22 +0000 |
commit | bed22a01fb19de6e4b4c2c7d8c5953bc7aa2580e (patch) | |
tree | b10a0bd2e8a115f679cd0b955fc6661cea3e2d8a /networking | |
parent | 682ad3045c11f6d8961306b1a364289c2aae35ef (diff) | |
download | busybox-w32-bed22a01fb19de6e4b4c2c7d8c5953bc7aa2580e.tar.gz busybox-w32-bed22a01fb19de6e4b4c2c7d8c5953bc7aa2580e.tar.bz2 busybox-w32-bed22a01fb19de6e4b4c2c7d8c5953bc7aa2580e.zip |
sendmail: compat update by Vladimir
function old new delta
sendgetmail_main 1889 2091 +202
putchar_unlocked - 43 +43
putchar - 43 +43
packed_usage 24868 24910 +42
smtp_checkp 102 111 +9
uuencode 235 227 -8
------------------------------------------------------------------------------
(add/remove: 2/0 grow/shrink: 3/1 up/down: 339/-8) Total: 331 bytes
Diffstat (limited to 'networking')
-rw-r--r-- | networking/Config.in | 21 | ||||
-rw-r--r-- | networking/sendmail.c | 315 |
2 files changed, 202 insertions, 134 deletions
diff --git a/networking/Config.in b/networking/Config.in index f23ca47c0..1984297a6 100644 --- a/networking/Config.in +++ b/networking/Config.in | |||
@@ -687,6 +687,27 @@ config SENDMAIL | |||
687 | help | 687 | help |
688 | Barebones sendmail. | 688 | Barebones sendmail. |
689 | 689 | ||
690 | config FEATURE_SENDMAIL_MAILX | ||
691 | bool "Allow to specify subject, attachments and their charset" | ||
692 | default y | ||
693 | depends on SENDMAIL | ||
694 | help | ||
695 | Allow to specify subject, attachments and their charset. | ||
696 | |||
697 | config FEATURE_SENDMAIL_SSL | ||
698 | bool "Allow to communicate via SSL/TLS" | ||
699 | default y | ||
700 | depends on SENDMAIL | ||
701 | help | ||
702 | Allow to use secure connections provided by openssl. E.g. @gmail.com. | ||
703 | |||
704 | config FEATURE_SENDMAIL_CHARSET | ||
705 | string "Default charset" | ||
706 | default "utf-8" | ||
707 | depends on SENDMAIL | ||
708 | help | ||
709 | Default charset of the message. | ||
710 | |||
690 | config FETCHMAIL | 711 | config FETCHMAIL |
691 | bool "fetchmail" | 712 | bool "fetchmail" |
692 | default n | 713 | default n |
diff --git a/networking/sendmail.c b/networking/sendmail.c index c605d7c1b..6d00026e2 100644 --- a/networking/sendmail.c +++ b/networking/sendmail.c | |||
@@ -8,7 +8,38 @@ | |||
8 | */ | 8 | */ |
9 | #include "libbb.h" | 9 | #include "libbb.h" |
10 | 10 | ||
11 | #define INITIAL_STDIN_FILENO 3 | 11 | struct globals { |
12 | pid_t helper_pid; | ||
13 | unsigned timeout; | ||
14 | FILE *fp0; // initial stdin | ||
15 | // arguments for SSL connection helper | ||
16 | const char *xargs[9]; | ||
17 | // arguments for postprocess helper | ||
18 | const char *fargs[3]; | ||
19 | }; | ||
20 | #define G (*ptr_to_globals) | ||
21 | #define helper_pid (G.helper_pid) | ||
22 | #define timeout (G.timeout ) | ||
23 | #define fp0 (G.fp0 ) | ||
24 | #define xargs (G.xargs ) | ||
25 | #define fargs (G.fargs ) | ||
26 | #define INIT_G() do { \ | ||
27 | SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \ | ||
28 | xargs[0] = "openssl"; \ | ||
29 | xargs[1] = "s_client"; \ | ||
30 | xargs[2] = "-quiet"; \ | ||
31 | xargs[3] = "-connect"; \ | ||
32 | /*xargs[4] = "localhost";*/ \ | ||
33 | xargs[5] = "-tls1"; \ | ||
34 | xargs[6] = "-starttls"; \ | ||
35 | xargs[7] = "smtp"; \ | ||
36 | fargs[0] = CONFIG_FEATURE_SENDMAIL_CHARSET; \ | ||
37 | } while (0) | ||
38 | |||
39 | #define opt_connect (xargs[4]) | ||
40 | #define opt_after_connect (xargs[5]) | ||
41 | #define opt_charset (fargs[0]) | ||
42 | #define opt_subject (fargs[1]) | ||
12 | 43 | ||
13 | static void uuencode(char *fname, const char *text) | 44 | static void uuencode(char *fname, const char *text) |
14 | { | 45 | { |
@@ -18,14 +49,12 @@ static void uuencode(char *fname, const char *text) | |||
18 | }; | 49 | }; |
19 | 50 | ||
20 | #define src_buf text | 51 | #define src_buf text |
21 | int fd; | 52 | FILE *fp = fp; |
22 | #define len fd | 53 | ssize_t len = len; |
23 | char dst_buf[DST_BUF_SIZE + 1]; | 54 | char dst_buf[DST_BUF_SIZE + 1]; |
24 | 55 | ||
25 | if (fname) { | 56 | if (fname) { |
26 | fd = INITIAL_STDIN_FILENO; | 57 | fp = (NOT_LONE_DASH(fname)) ? xfopen_for_read(fname) : fp0; |
27 | if (NOT_LONE_DASH(fname)) | ||
28 | fd = xopen(fname, O_RDONLY); | ||
29 | src_buf = bb_common_bufsiz1; | 58 | src_buf = bb_common_bufsiz1; |
30 | // N.B. strlen(NULL) segfaults! | 59 | // N.B. strlen(NULL) segfaults! |
31 | } else if (text) { | 60 | } else if (text) { |
@@ -35,11 +64,10 @@ static void uuencode(char *fname, const char *text) | |||
35 | } else | 64 | } else |
36 | return; | 65 | return; |
37 | 66 | ||
38 | fflush(stdout); // sync stdio and unistd output | ||
39 | while (1) { | 67 | while (1) { |
40 | size_t size; | 68 | size_t size; |
41 | if (fname) { | 69 | if (fname) { |
42 | size = full_read(fd, (char *)src_buf, SRC_BUF_SIZE); | 70 | size = fread((char *)src_buf, 1, SRC_BUF_SIZE, fp); |
43 | if ((ssize_t)size < 0) | 71 | if ((ssize_t)size < 0) |
44 | bb_perror_msg_and_die(bb_msg_read_error); | 72 | bb_perror_msg_and_die(bb_msg_read_error); |
45 | } else { | 73 | } else { |
@@ -52,50 +80,20 @@ static void uuencode(char *fname, const char *text) | |||
52 | // encode the buffer we just read in | 80 | // encode the buffer we just read in |
53 | bb_uuencode(dst_buf, src_buf, size, bb_uuenc_tbl_base64); | 81 | bb_uuencode(dst_buf, src_buf, size, bb_uuenc_tbl_base64); |
54 | if (fname) { | 82 | if (fname) { |
55 | xwrite(STDOUT_FILENO, "\r\n", 2); | 83 | printf("\r\n"); |
56 | } else { | 84 | } else { |
57 | src_buf += size; | 85 | src_buf += size; |
58 | len -= size; | 86 | len -= size; |
59 | } | 87 | } |
60 | xwrite(STDOUT_FILENO, dst_buf, 4 * ((size + 2) / 3)); | 88 | fwrite(dst_buf, 1, 4 * ((size + 2) / 3), stdout); |
61 | } | 89 | } |
62 | if (fname) | 90 | if (fname) |
63 | close(fd); | 91 | fclose(fp); |
64 | #undef src_buf | 92 | #undef src_buf |
65 | #undef len | ||
66 | } | 93 | } |
67 | 94 | ||
68 | struct globals { | ||
69 | pid_t helper_pid; | ||
70 | unsigned timeout; | ||
71 | // arguments for SSL connection helper | ||
72 | const char *xargs[9]; | ||
73 | // arguments for postprocess helper | ||
74 | const char *fargs[3]; | ||
75 | }; | ||
76 | #define G (*ptr_to_globals) | ||
77 | #define helper_pid (G.helper_pid) | ||
78 | #define timeout (G.timeout ) | ||
79 | #define xargs (G.xargs ) | ||
80 | #define fargs (G.fargs ) | ||
81 | #define INIT_G() do { \ | ||
82 | SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \ | ||
83 | xargs[0] = "openssl"; \ | ||
84 | xargs[1] = "s_client"; \ | ||
85 | xargs[2] = "-quiet"; \ | ||
86 | xargs[3] = "-connect"; \ | ||
87 | /*xargs[4] = "localhost";*/ \ | ||
88 | xargs[5] = "-tls1"; \ | ||
89 | xargs[6] = "-starttls"; \ | ||
90 | xargs[7] = "smtp"; \ | ||
91 | fargs[0] = "utf-8"; \ | ||
92 | } while (0) | ||
93 | |||
94 | #define opt_connect (xargs[4]) | ||
95 | #define opt_after_connect (xargs[5]) | ||
96 | #define opt_charset (fargs[0]) | ||
97 | #define opt_subject (fargs[1]) | ||
98 | 95 | ||
96 | #if ENABLE_FEATURE_SENDMAIL_SSL | ||
99 | static void kill_helper(void) | 97 | static void kill_helper(void) |
100 | { | 98 | { |
101 | // TODO!!!: is there more elegant way to terminate child on program failure? | 99 | // TODO!!!: is there more elegant way to terminate child on program failure? |
@@ -107,7 +105,6 @@ static void kill_helper(void) | |||
107 | static void signal_handler(int signo) | 105 | static void signal_handler(int signo) |
108 | { | 106 | { |
109 | #define err signo | 107 | #define err signo |
110 | |||
111 | if (SIGALRM == signo) { | 108 | if (SIGALRM == signo) { |
112 | kill_helper(); | 109 | kill_helper(); |
113 | bb_error_msg_and_die("timed out"); | 110 | bb_error_msg_and_die("timed out"); |
@@ -151,6 +148,10 @@ static void launch_helper(const char **argv) | |||
151 | signal_handler(SIGCHLD); | 148 | signal_handler(SIGCHLD); |
152 | // child seems OK -> parent goes on | 149 | // child seems OK -> parent goes on |
153 | } | 150 | } |
151 | #else | ||
152 | #define kill_helper() ((void)0) | ||
153 | #define launch_helper(x) bb_error_msg_and_die("no SSL support") | ||
154 | #endif | ||
154 | 155 | ||
155 | static const char *command(const char *fmt, const char *param) | 156 | static const char *command(const char *fmt, const char *param) |
156 | { | 157 | { |
@@ -177,15 +178,14 @@ static int smtp_checkp(const char *fmt, const char *param, int code) | |||
177 | while ((answer = xmalloc_fgetline(stdin)) != NULL) | 178 | while ((answer = xmalloc_fgetline(stdin)) != NULL) |
178 | if (strlen(answer) <= 3 || '-' != answer[3]) | 179 | if (strlen(answer) <= 3 || '-' != answer[3]) |
179 | break; | 180 | break; |
181 | //bb_error_msg("FMT[%s]ANS[%s]", fmt, answer); | ||
180 | if (answer) { | 182 | if (answer) { |
181 | int n = atoi(answer); | 183 | int n = atoi(answer); |
184 | //bb_error_msg("FMT[%s]COD[%d][%d]", fmt, n, code); | ||
182 | alarm(0); | 185 | alarm(0); |
183 | if (ENABLE_FEATURE_CLEAN_UP) { | 186 | free(answer); |
184 | free(answer); | 187 | if (-1 == code || n == code) |
185 | } | ||
186 | if (-1 == code || n == code) { | ||
187 | return n; | 188 | return n; |
188 | } | ||
189 | } | 189 | } |
190 | kill_helper(); | 190 | kill_helper(); |
191 | bb_error_msg_and_die("%s failed", msg); | 191 | bb_error_msg_and_die("%s failed", msg); |
@@ -283,30 +283,34 @@ static void rcptto(const char *s) | |||
283 | int sendgetmail_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 283 | int sendgetmail_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
284 | int sendgetmail_main(int argc UNUSED_PARAM, char **argv) | 284 | int sendgetmail_main(int argc UNUSED_PARAM, char **argv) |
285 | { | 285 | { |
286 | #if ENABLE_FEATURE_SENDMAIL_MAILX | ||
286 | llist_t *opt_attachments = NULL; | 287 | llist_t *opt_attachments = NULL; |
287 | char *opt_from; | 288 | #endif |
289 | char *opt_from, *opt_fullname; | ||
288 | const char *opt_user; | 290 | const char *opt_user; |
289 | const char *opt_pass; | 291 | const char *opt_pass; |
292 | |||
290 | enum { | 293 | enum { |
291 | OPT_w = 1 << 0, // network timeout | 294 | OPT_w = 1 << 0, // network timeout |
295 | |||
292 | OPT_H = 1 << 1, // [user:password@]server[:port] | 296 | OPT_H = 1 << 1, // [user:password@]server[:port] |
293 | OPT_S = 1 << 2, // connect using openssl s_client helper | 297 | OPT_S = 1 << 2, // connect using openssl s_client helper |
294 | 298 | ||
295 | OPTS_t = 1 << 3, // sendmail: read addresses from body | 299 | OPTS_t = 1 << 3, // sendmail: read message for recipients |
296 | OPTF_t = 1 << 3, // fetchmail: use "TOP" not "RETR" | 300 | OPTF_t = 1 << 3, // fetchmail: use "TOP" not "RETR" |
297 | 301 | ||
298 | OPTS_s = 1 << 4, // sendmail: subject | 302 | OPTS_N = 1 << 4, // sendmail: request notification |
299 | OPTF_z = 1 << 4, // fetchmail: delete from server | 303 | OPTF_z = 1 << 4, // fetchmail: delete from server |
300 | 304 | ||
301 | OPTS_c = 1 << 5, // sendmail: assumed charset | 305 | OPTS_f = 1 << 5, // sendmail: sender address |
302 | OPTS_a = 1 << 6, // sendmail: attachment(s) | 306 | OPTS_F = 1 << 6, // sendmail: sender name, overrides $NAME |
303 | OPTS_i = 1 << 7, // sendmail: ignore lone dots in message body (implied) | ||
304 | 307 | ||
305 | OPTS_N = 1 << 8, // sendmail: request notification | 308 | OPTS_s = 1 << 7, // sendmail: subject |
306 | OPTS_f = 1 << 9, // sendmail: sender address | 309 | OPTS_c = 1 << 8, // sendmail: assumed charset |
310 | OPTS_a = 1 << 9, // sendmail: attachment(s) | ||
307 | }; | 311 | }; |
308 | const char *options; | 312 | const char *options; |
309 | int opts; | 313 | unsigned opts; |
310 | 314 | ||
311 | // init global variables | 315 | // init global variables |
312 | INIT_G(); | 316 | INIT_G(); |
@@ -317,11 +321,11 @@ int sendgetmail_main(int argc UNUSED_PARAM, char **argv) | |||
317 | if (!ENABLE_FETCHMAIL || 's' == applet_name[0]) { | 321 | if (!ENABLE_FETCHMAIL || 's' == applet_name[0]) { |
318 | // SENDMAIL | 322 | // SENDMAIL |
319 | // save initial stdin since body is piped! | 323 | // save initial stdin since body is piped! |
320 | xdup2(STDIN_FILENO, INITIAL_STDIN_FILENO); | 324 | xdup2(STDIN_FILENO, 3); |
325 | fp0 = fdopen(3, "r"); | ||
321 | opt_complementary = "w+:a::"; | 326 | opt_complementary = "w+:a::"; |
322 | options = "w:H:St" "s:c:a:iN:f:"; | 327 | options = "w:H:St" "N:f:F:" USE_FEATURE_SENDMAIL_MAILX("s:c:a:") |
323 | // body is pseudo attachment read from stdin | 328 | "X:V:vq:R:O:o:nmL:Iih:GC:B:b:A:"; // postfix compat only, ignored |
324 | llist_add_to_end(&opt_attachments, (char *)"-"); | ||
325 | } else { | 329 | } else { |
326 | // FETCHMAIL | 330 | // FETCHMAIL |
327 | opt_after_connect = NULL; | 331 | opt_after_connect = NULL; |
@@ -330,15 +334,19 @@ int sendgetmail_main(int argc UNUSED_PARAM, char **argv) | |||
330 | } | 334 | } |
331 | opts = getopt32(argv, options, | 335 | opts = getopt32(argv, options, |
332 | &timeout /* -w */, &opt_connect /* -H */, | 336 | &timeout /* -w */, &opt_connect /* -H */, |
333 | &opt_subject, &opt_charset, &opt_attachments, NULL, &opt_from | 337 | NULL, &opt_from, &opt_fullname, |
338 | #if ENABLE_FEATURE_SENDMAIL_MAILX | ||
339 | &opt_subject, &opt_charset, &opt_attachments, | ||
340 | #endif | ||
341 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL | ||
334 | ); | 342 | ); |
335 | //argc -= optind; | 343 | //argc -= optind; |
336 | argv += optind; | 344 | argv += optind; |
337 | 345 | ||
338 | // connect to server | 346 | // connect to server |
339 | // host[:port] not specified ? -> use $HOSTNAME. no $HOSTNAME ? -> use localhost | 347 | // host[:port] not specified ? -> use $SMTPHOST. no $SMTPHOST ? -> use localhost |
340 | if (!(opts & OPT_H)) { | 348 | if (!(opts & OPT_H)) { |
341 | opt_connect = getenv("HOSTNAME"); | 349 | opt_connect = getenv("SMTPHOST"); |
342 | if (!opt_connect) | 350 | if (!opt_connect) |
343 | opt_connect = "127.0.0.1"; | 351 | opt_connect = "127.0.0.1"; |
344 | } | 352 | } |
@@ -376,18 +384,13 @@ int sendgetmail_main(int argc UNUSED_PARAM, char **argv) | |||
376 | { | 384 | { |
377 | int code; | 385 | int code; |
378 | char *boundary; | 386 | char *boundary; |
379 | const char *fmt; | ||
380 | const char *p; | ||
381 | char *q; | ||
382 | llist_t *l; | 387 | llist_t *l; |
383 | llist_t *headers = NULL; | 388 | llist_t *headers = NULL; |
389 | char *domain = sane(safe_getdomainname()); | ||
384 | 390 | ||
385 | // got no sender address? -> use username as a resort | 391 | // got no sender address? -> use username as a resort |
386 | if (!(opts & OPTS_f)) { | 392 | if (!(opts & OPTS_f)) { |
387 | char *domain = safe_getdomainname(); | ||
388 | opt_from = xasprintf("%s@%s", opt_user, domain); | 393 | opt_from = xasprintf("%s@%s", opt_user, domain); |
389 | if (ENABLE_FEATURE_CLEAN_UP) | ||
390 | free(domain); | ||
391 | } | 394 | } |
392 | 395 | ||
393 | // introduce to server | 396 | // introduce to server |
@@ -399,9 +402,11 @@ int sendgetmail_main(int argc UNUSED_PARAM, char **argv) | |||
399 | } | 402 | } |
400 | 403 | ||
401 | // we should start with modern EHLO | 404 | // we should start with modern EHLO |
402 | if (250 != smtp_checkp("EHLO %s", sane(opt_from), -1)) { | 405 | if (250 != smtp_checkp("EHLO %s", domain, -1)) { |
403 | smtp_checkp("HELO %s", opt_from, 250); | 406 | smtp_checkp("HELO %s", domain, 250); |
404 | } | 407 | } |
408 | if (ENABLE_FEATURE_CLEAN_UP) | ||
409 | free(domain); | ||
405 | 410 | ||
406 | // set sender | 411 | // set sender |
407 | // NOTE: if password has not been specified | 412 | // NOTE: if password has not been specified |
@@ -431,37 +436,36 @@ int sendgetmail_main(int argc UNUSED_PARAM, char **argv) | |||
431 | argv++; | 436 | argv++; |
432 | } | 437 | } |
433 | 438 | ||
434 | // if -t specified or no recipients specified -> enter all-included mode | 439 | // if -t specified or no recipients specified -> read recipients from message |
435 | // i.e. scan stdin for To:, Cc:, Bcc:, and Subject: lines ... | 440 | // i.e. scan stdin for To:, Cc:, Bcc: lines ... |
436 | // ... and then use the rest of stdin as message body | 441 | // ... and then use the rest of stdin as message body |
437 | // N.B. subject read from body has priority | 442 | // N.B. subject read from body can be further overrided with one specified on command line. |
438 | // over that specified on command line. | 443 | // recipients are merged. Bcc: lines are deleted |
439 | // recipients are merged | ||
440 | // N.B. other headers are collected and will be dumped verbatim | 444 | // N.B. other headers are collected and will be dumped verbatim |
441 | if (opts & OPTS_t || !headers) { | 445 | if (opts & OPTS_t || !headers) { |
442 | // fetch recipients and (optionally) subject | 446 | // fetch recipients and (optionally) subject |
443 | char *s; | 447 | char *s; |
444 | while ((s = xmalloc_reads(INITIAL_STDIN_FILENO, NULL, NULL)) != NULL) { | 448 | while ((s = xmalloc_fgetline(fp0)) != NULL) { |
445 | if (0 == strncasecmp("To: ", s, 4) || 0 == strncasecmp("Cc: ", s, 4)) { | 449 | if (0 == strncasecmp("To: ", s, 4) || 0 == strncasecmp("Cc: ", s, 4)) { |
446 | rcptto(sane(s+4)); | 450 | rcptto(sane(s+4)); |
447 | llist_add_to_end(&headers, s); | 451 | llist_add_to_end(&headers, s); |
448 | } else if (0 == strncasecmp("Bcc: ", s, 5)) { | 452 | } else if (0 == strncasecmp("Bcc: ", s, 5)) { |
449 | rcptto(sane(s+5)); | 453 | rcptto(sane(s+5)); |
450 | if (ENABLE_FEATURE_CLEAN_UP) | 454 | free(s); |
451 | free(s); | ||
452 | // N.B. Bcc vanishes from headers! | 455 | // N.B. Bcc vanishes from headers! |
453 | /* } else if (0 == strncmp("From: ", s, 6)) { | 456 | } else if (0 == strncmp("Subject: ", s, 9)) { |
454 | opt_from = s+6; | 457 | // we read subject -> use it verbatim unless it is specified |
455 | opts |= OPTS_f; | 458 | // on command line |
456 | */ } else if (0 == strncmp("Subject: ", s, 9)) { | 459 | if (!(opts & OPTS_s)) |
457 | opt_subject = s+9; | 460 | llist_add_to_end(&headers, s); |
458 | opts |= OPTS_s; | 461 | else |
462 | free(s); | ||
459 | } else if (s[0]) { | 463 | } else if (s[0]) { |
460 | // misc header | 464 | // misc header |
461 | llist_add_to_end(&headers, s); | 465 | llist_add_to_end(&headers, s); |
462 | } else { | 466 | } else { |
463 | free(s); | 467 | free(s); |
464 | break; // empty line | 468 | break; // stop on the first empty line |
465 | } | 469 | } |
466 | } | 470 | } |
467 | } | 471 | } |
@@ -476,18 +480,27 @@ int sendgetmail_main(int argc UNUSED_PARAM, char **argv) | |||
476 | free(l->data); | 480 | free(l->data); |
477 | } | 481 | } |
478 | 482 | ||
479 | // put address header | 483 | // put (possibly encoded) subject |
480 | printf("From: %s\r\n", opt_from); | ||
481 | |||
482 | // put encoded subject | ||
483 | if (opts & OPTS_c) | 484 | if (opts & OPTS_c) |
484 | sane((char *)opt_charset); | 485 | sane((char *)opt_charset); |
485 | if (opts & OPTS_s) { | 486 | if (opts & OPTS_s) { |
486 | printf("Subject: =?%s?B?", opt_charset); | 487 | printf("Subject: "); |
487 | uuencode(NULL, opt_subject); | 488 | if (opts & OPTS_c) { |
488 | printf("?=\r\n"); | 489 | printf("=?%s?B?", opt_charset); |
490 | uuencode(NULL, opt_subject); | ||
491 | printf("?="); | ||
492 | } else { | ||
493 | printf("%s", opt_subject); | ||
494 | } | ||
495 | printf("\r\n"); | ||
489 | } | 496 | } |
490 | 497 | ||
498 | // put sender name, $NAME is the default | ||
499 | if (!(opts & OPTS_F)) | ||
500 | opt_fullname = getenv("NAME"); | ||
501 | if (opt_fullname) | ||
502 | printf("From: \"%s\" <%s>\r\n", opt_fullname, opt_from); | ||
503 | |||
491 | // put notification | 504 | // put notification |
492 | if (opts & OPTS_N) | 505 | if (opts & OPTS_N) |
493 | printf("Disposition-Notification-To: %s\r\n", opt_from); | 506 | printf("Disposition-Notification-To: %s\r\n", opt_from); |
@@ -496,58 +509,92 @@ int sendgetmail_main(int argc UNUSED_PARAM, char **argv) | |||
496 | srand(monotonic_us()); | 509 | srand(monotonic_us()); |
497 | boundary = xasprintf("%d-%d-%d", rand(), rand(), rand()); | 510 | boundary = xasprintf("%d-%d-%d", rand(), rand(), rand()); |
498 | 511 | ||
499 | // put common headers and body start | 512 | // put common headers |
500 | printf( | 513 | // TODO: do we really need this? |
501 | "Message-ID: <%s>\r\n" | 514 | // printf("Message-ID: <%s>\r\n", boundary); |
502 | "Mime-Version: 1.0\r\n" | 515 | |
503 | "%smultipart/mixed; boundary=\"%s\"\r\n" | 516 | #if ENABLE_FEATURE_SENDMAIL_MAILX |
504 | , boundary | 517 | // have attachments? -> compose multipart MIME |
505 | , "Content-Type: " | 518 | if (opt_attachments) { |
506 | , boundary | 519 | const char *fmt; |
507 | ); | 520 | const char *p; |
508 | 521 | char *q; | |
509 | // put body + attachment(s) | 522 | |
510 | // N.B. all these weird things just to be tiny | ||
511 | // by reusing string patterns! | ||
512 | fmt = | ||
513 | "\r\n--%s\r\n" | ||
514 | "%stext/plain; charset=%s\r\n" | ||
515 | "%s%s\r\n" | ||
516 | "%s" | ||
517 | ; | ||
518 | p = opt_charset; | ||
519 | q = (char *)""; | ||
520 | l = opt_attachments; | ||
521 | while (l) { | ||
522 | printf( | 523 | printf( |
523 | fmt | 524 | "Mime-Version: 1.0\r\n" |
524 | , boundary | 525 | "%smultipart/mixed; boundary=\"%s\"\r\n" |
525 | , "Content-Type: " | 526 | , "Content-Type: " |
526 | , p | 527 | , boundary |
527 | , "Content-Disposition: inline" | ||
528 | , q | ||
529 | , "Content-Transfer-Encoding: base64\r\n" | ||
530 | ); | 528 | ); |
531 | p = ""; | 529 | |
530 | // body is pseudo attachment read from stdin in first turn | ||
531 | llist_add_to(&opt_attachments, (char *)"-"); | ||
532 | |||
533 | // put body + attachment(s) | ||
534 | // N.B. all these weird things just to be tiny | ||
535 | // by reusing string patterns! | ||
532 | fmt = | 536 | fmt = |
533 | "\r\n--%s\r\n" | 537 | "\r\n--%s\r\n" |
534 | "%sapplication/octet-stream%s\r\n" | 538 | "%stext/plain; charset=%s\r\n" |
535 | "%s; filename=\"%s\"\r\n" | 539 | "%s%s\r\n" |
536 | "%s" | 540 | "%s" |
537 | ; | 541 | ; |
538 | uuencode(l->data, NULL); | 542 | p = opt_charset; |
539 | l = l->link; | 543 | q = (char *)""; |
540 | if (l) | 544 | l = opt_attachments; |
541 | q = bb_get_last_path_component_strip(l->data); | 545 | while (l) { |
542 | } | 546 | printf( |
547 | fmt | ||
548 | , boundary | ||
549 | , "Content-Type: " | ||
550 | , p | ||
551 | , "Content-Disposition: inline" | ||
552 | , q | ||
553 | , "Content-Transfer-Encoding: base64\r\n" | ||
554 | ); | ||
555 | p = ""; | ||
556 | fmt = | ||
557 | "\r\n--%s\r\n" | ||
558 | "%sapplication/octet-stream%s\r\n" | ||
559 | "%s; filename=\"%s\"\r\n" | ||
560 | "%s" | ||
561 | ; | ||
562 | uuencode(l->data, NULL); | ||
563 | l = l->link; | ||
564 | if (l) | ||
565 | q = bb_get_last_path_component_strip(l->data); | ||
566 | } | ||
567 | |||
568 | // put message terminator | ||
569 | printf("\r\n--%s--\r\n" "\r\n", boundary); | ||
543 | 570 | ||
544 | // put message terminator | 571 | // no attachments? -> just dump message |
545 | printf("\r\n--%s--\r\n" "\r\n", boundary); | 572 | } else |
573 | #endif | ||
574 | { | ||
575 | char *s; | ||
576 | // terminate headers | ||
577 | printf("\r\n"); | ||
578 | // put plain text respecting leading dots | ||
579 | while ((s = xmalloc_fgetline(fp0)) != NULL) { | ||
580 | // escape leading dots | ||
581 | // N.B. this feature is implied even if no -i switch given | ||
582 | // N.B. we need to escape the leading dot regardless of | ||
583 | // whether it is single or not character on the line | ||
584 | if (/*(opts & OPTS_i) && */ '.' == s[0] /*&& '\0' == s[1] */) | ||
585 | printf("."); | ||
586 | // dump read line | ||
587 | printf("%s\r\n", s); | ||
588 | } | ||
589 | } | ||
546 | 590 | ||
547 | // leave "put message" mode | 591 | // leave "put message" mode |
548 | smtp_check(".", 250); | 592 | smtp_check(".", 250); |
549 | // ... and say goodbye | 593 | // ... and say goodbye |
550 | smtp_check("QUIT", 221); | 594 | smtp_check("QUIT", 221); |
595 | // cleanup | ||
596 | if (ENABLE_FEATURE_CLEAN_UP) | ||
597 | fclose(fp0); | ||
551 | } | 598 | } |
552 | #if ENABLE_FETCHMAIL | 599 | #if ENABLE_FETCHMAIL |
553 | /*************************************************** | 600 | /*************************************************** |
@@ -671,5 +718,5 @@ int sendgetmail_main(int argc UNUSED_PARAM, char **argv) | |||
671 | } | 718 | } |
672 | #endif // ENABLE_FETCHMAIL | 719 | #endif // ENABLE_FETCHMAIL |
673 | 720 | ||
674 | return 0; | 721 | return EXIT_SUCCESS; |
675 | } | 722 | } |