aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--networking/sendmail.c109
1 files changed, 58 insertions, 51 deletions
diff --git a/networking/sendmail.c b/networking/sendmail.c
index 653f2e60a..e6af3d40a 100644
--- a/networking/sendmail.c
+++ b/networking/sendmail.c
@@ -274,10 +274,14 @@ static char *parse_url(char *url, char **user, char **pass)
274 return url; 274 return url;
275} 275}
276 276
277static void rcptto(const char *s)
278{
279 smtp_checkp("RCPT TO:<%s>", s, 250);
280}
281
277int sendgetmail_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 282int sendgetmail_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
278int sendgetmail_main(int argc UNUSED_PARAM, char **argv) 283int sendgetmail_main(int argc UNUSED_PARAM, char **argv)
279{ 284{
280 llist_t *opt_recipients = NULL;
281 llist_t *opt_attachments = NULL; 285 llist_t *opt_attachments = NULL;
282 char *opt_from; 286 char *opt_from;
283 char *opt_user; 287 char *opt_user;
@@ -377,48 +381,12 @@ int sendgetmail_main(int argc UNUSED_PARAM, char **argv)
377 llist_t *l; 381 llist_t *l;
378 llist_t *headers = NULL; 382 llist_t *headers = NULL;
379 383
380 // recipients specified as arguments
381 while (*argv) {
382 // loose test on email address validity
383 if (strchr(sane(*argv), '@'))
384 llist_add_to_end(&opt_recipients, *argv);
385 argv++;
386 }
387
388 // if -t specified or no recipients specified -> enter all-included mode
389 // i.e. scan stdin for To: and Subject: lines ...
390 // ... and then use the rest of stdin as message body
391 // N.B. subject read from body has priority
392 // over that specified on command line.
393 // recipients are merged
394 // N.B. other headers are collected and will be dumped verbatim
395 if (opts & OPTS_t || !opt_recipients) {
396 // fetch recipients and (optionally) subject
397 char *s;
398 while ((s = xmalloc_reads(INITIAL_STDIN_FILENO, NULL, NULL)) != NULL) {
399 if (0 == strncasecmp("To: ", s, 4) || 0 == strncasecmp("Cc: ", s, 4)) {
400 llist_add_to_end(&opt_recipients, s+4);
401/* } else if (0 == strncmp("From: ", s, 6)) {
402 opt_from = s+6;
403 opts |= OPTS_f;
404*/ } else if (0 == strncmp("Subject: ", s, 9)) {
405 opt_subject = s+9;
406 opts |= OPTS_s;
407 } else if (s[0]) {
408 // misc header
409 llist_add_to_end(&headers, s);
410 } else {
411 free(s);
412 break; // empty line
413 }
414 }
415 }
416
417 // got no sender address? -> use username as a resort 384 // got no sender address? -> use username as a resort
418 if (!(opts & OPTS_f)) { 385 if (!(opts & OPTS_f)) {
419 char *domain = safe_getdomainname(); 386 char *domain = safe_getdomainname();
420 opt_from = xasprintf("%s@%s", opt_user, domain); 387 opt_from = xasprintf("%s@%s", opt_user, domain);
421 free(domain); 388 if (ENABLE_FEATURE_CLEAN_UP)
389 free(domain);
422 } 390 }
423 391
424 // introduce to server 392 // introduce to server
@@ -452,20 +420,64 @@ int sendgetmail_main(int argc UNUSED_PARAM, char **argv)
452 code = 250; 420 code = 250;
453 } 421 }
454 422
455 // set recipients 423 // recipients specified as arguments
456 for (l = opt_recipients; l; l = l->link) { 424 while (*argv) {
457 smtp_checkp("RCPT TO:<%s>", sane(l->data), 250); 425 // loose test on email address validity
426 if (strchr(sane(*argv), '@')) {
427 rcptto(sane(*argv));
428 llist_add_to_end(&headers, xasprintf("To: %s", *argv));
429 }
430 argv++;
431 }
432
433 // if -t specified or no recipients specified -> enter all-included mode
434 // i.e. scan stdin for To:, Cc:, Bcc:, and Subject: lines ...
435 // ... and then use the rest of stdin as message body
436 // N.B. subject read from body has priority
437 // over that specified on command line.
438 // recipients are merged
439 // N.B. other headers are collected and will be dumped verbatim
440 if (opts & OPTS_t || !headers) {
441 // fetch recipients and (optionally) subject
442 char *s;
443 while ((s = xmalloc_reads(INITIAL_STDIN_FILENO, NULL, NULL)) != NULL) {
444 if (0 == strncasecmp("To: ", s, 4) || 0 == strncasecmp("Cc: ", s, 4)) {
445 rcptto(sane(s+4));
446 llist_add_to_end(&headers, s);
447 } else if (0 == strncasecmp("Bcc: ", s, 5)) {
448 rcptto(sane(s+5));
449 if (ENABLE_FEATURE_CLEAN_UP)
450 free(s);
451 // N.B. Bcc vanishes from headers!
452/* } else if (0 == strncmp("From: ", s, 6)) {
453 opt_from = s+6;
454 opts |= OPTS_f;
455*/ } else if (0 == strncmp("Subject: ", s, 9)) {
456 opt_subject = s+9;
457 opts |= OPTS_s;
458 } else if (s[0]) {
459 // misc header
460 llist_add_to_end(&headers, s);
461 } else {
462 free(s);
463 break; // empty line
464 }
465 }
458 } 466 }
459 467
460 // enter "put message" mode 468 // enter "put message" mode
461 smtp_check("DATA", 354); 469 smtp_check("DATA", 354);
462 470
463 // put address headers 471 // put headers we could have preread with -t
464 printf("From: %s\r\n", opt_from); 472 for (l = headers; l; l = l->link) {
465 for (l = opt_recipients; l; l = l->link) { 473 printf("%s\r\n", l->data);
466 printf("To: %s\r\n", l->data); 474 if (ENABLE_FEATURE_CLEAN_UP)
475 free(l->data);
467 } 476 }
468 477
478 // put address header
479 printf("From: %s\r\n", opt_from);
480
469 // put encoded subject 481 // put encoded subject
470 if (opts & OPTS_c) 482 if (opts & OPTS_c)
471 sane((char *)opt_charset); 483 sane((char *)opt_charset);
@@ -479,11 +491,6 @@ int sendgetmail_main(int argc UNUSED_PARAM, char **argv)
479 if (opts & OPTS_N) 491 if (opts & OPTS_N)
480 printf("Disposition-Notification-To: %s\r\n", opt_from); 492 printf("Disposition-Notification-To: %s\r\n", opt_from);
481 493
482 // put headers we could have preread with -t
483 for (l = headers; l; l = l->link) {
484 printf("%s\r\n", l->data);
485 }
486
487 // make a random string -- it will delimit message parts 494 // make a random string -- it will delimit message parts
488 srand(monotonic_us()); 495 srand(monotonic_us());
489 boundary = xasprintf("%d-%d-%d", rand(), rand(), rand()); 496 boundary = xasprintf("%d-%d-%d", rand(), rand(), rand());