diff --git a/include/usage.src.h b/include/usage.src.h index cd37a892d..4640338e6 100644 --- a/include/usage.src.h +++ b/include/usage.src.h @@ -3211,36 +3211,6 @@ INSERT #define selinuxenabled_trivial_usage NOUSAGE_STR #define selinuxenabled_full_usage "" -#define sendmail_trivial_usage \ - "[OPTIONS] [RECIPIENT_EMAIL]..." -#define sendmail_full_usage "\n\n" \ - "Read email from stdin and send it\n" \ - "\nStandard options:" \ - "\n -t Read additional recipients from message body" \ - "\n -f sender Sender (required)" \ - "\n -o options Various options. -oi implied, others are ignored" \ - "\n -i -oi synonym. implied and ignored" \ - "\n" \ - "\nBusybox specific options:" \ - "\n -w seconds Network timeout" \ - "\n -H 'PROG ARGS' Run connection helper" \ - "\n Examples:" \ - "\n -H 'exec openssl s_client -quiet -tls1 -starttls smtp" \ - "\n -connect smtp.gmail.com:25' -ap]" \ - "\n -H 'exec openssl s_client -quiet -tls1" \ - "\n -connect smtp.gmail.com:465' -ap]" \ - "\n -S server[:port] Server" \ - "\n -au Username for AUTH LOGIN" \ - "\n -ap Password for AUTH LOGIN" \ - "\n -am Authentication method. Ignored. LOGIN is implied" \ - "\n" \ - "\nOther options are silently ignored; -oi -t is implied" \ - IF_MAKEMIME( \ - "\nUse makemime applet to create message with attachments" \ - ) - #define seq_trivial_usage \ "[-w] [-s SEP] [FIRST [INC]] LAST" #define seq_full_usage "\n\n" \ diff --git a/mailutils/mail.c b/mailutils/mail.c index 9b4bebce5..44957016f 100644 --- a/mailutils/mail.c +++ b/mailutils/mail.c @@ -75,13 +75,16 @@ void FAST_FUNC launch_helper(const char **argv) atexit(kill_helper); } -const FAST_FUNC char *command(const char *fmt, const char *param) +char* FAST_FUNC send_mail_command(const char *fmt, const char *param) { - const char *msg = fmt; + char *msg; if (timeout) alarm(timeout); - if (msg) { + msg = (char*)fmt; + if (fmt) { msg = xasprintf(fmt, param); + if (verbose) + bb_error_msg("send:'%s'", msg); printf("%s\r\n", msg); } fflush_all(); @@ -90,7 +93,7 @@ const FAST_FUNC char *command(const char *fmt, const char *param) // NB: parse_url can modify url[] (despite const), but only if '@' is there /* -static char FAST_FUNC *parse_url(char *url, char **user, char **pass) +static char* FAST_FUNC parse_url(char *url, char **user, char **pass) { // parse [user[:pass]@]host // return host diff --git a/mailutils/mail.h b/mailutils/mail.h index e0048fbfa..d1d783055 100644 --- a/mailutils/mail.h +++ b/mailutils/mail.h @@ -1,7 +1,16 @@ +/* vi: set sw=4 ts=4: */ +/* + * helper routines + * + * Copyright (C) 2008 by Vladimir Dronnikov + * + * Licensed under GPLv2, see file LICENSE in this source tree. + */ struct globals { pid_t helper_pid; unsigned timeout; + unsigned verbose; unsigned opts; char *user; char *pass; @@ -12,6 +21,7 @@ struct globals { #define G (*ptr_to_globals) #define timeout (G.timeout ) +#define verbose (G.verbose ) #define opts (G.opts ) //#define user (G.user ) //#define pass (G.pass ) @@ -26,9 +36,9 @@ struct globals { //char FAST_FUNC *parse_url(char *url, char **user, char **pass); -void FAST_FUNC launch_helper(const char **argv); -void FAST_FUNC get_cred_or_die(int fd); +void launch_helper(const char **argv) FAST_FUNC; +void get_cred_or_die(int fd) FAST_FUNC; -const FAST_FUNC char *command(const char *fmt, const char *param); +char *send_mail_command(const char *fmt, const char *param) FAST_FUNC; -void FAST_FUNC encode_base64(char *fname, const char *text, const char *eol); +void encode_base64(char *fname, const char *text, const char *eol) FAST_FUNC; diff --git a/mailutils/mime.c b/mailutils/mime.c index 682cf4536..1e393ed31 100644 --- a/mailutils/mime.c +++ b/mailutils/mime.c @@ -99,6 +99,28 @@ Content-Transfer-Encoding: 7bit ...random junk added by mailing list robots and such... */ +/* man makemime: + + * -c TYPE: create a (non-multipart) MIME section with Content-Type: TYPE + * makemime -c TYPE [-e ENCODING] [-o OUTFILE] [-C CHARSET] [-N NAME] [-a HEADER...] FILE + * The -C option sets the MIME charset attribute for text/plain content. + * The -N option sets the name attribute for Content-Type: + * Encoding must be one of the following: 7bit, 8bit, quoted-printable, or base64. + + * -m multipart/TYPE: create a multipart MIME collection with Content-Type: multipart/TYPE + * makemime -m multipart/TYPE [-e ENCODING] [-o OUTFILE] [-a HEADER...] FILE + * Type must be either "multipart/mixed", "multipart/alternative", or some other MIME multipart content type. + * Additionally, encoding can only be "7bit" or "8bit", and will default to "8bit" if not specified. + * Finally, filename must be a MIME-formatted section, NOT a regular file. + * The -m option creates an initial multipart MIME collection, that contains only one MIME section, taken from filename. + * The collection is written to standard output, or the pipe or to outputfile. + + * -j FILE1: add a section to a multipart MIME collection + * makemime -j FILE1 [-o OUTFILE] FILE2 + * FILE1 must be a MIME collection that was previously created by the -m option. + * FILE2 must be a MIME section that was previously created by the -c option. + * The -j options adds the MIME section in FILE2 to the MIME collection in FILE1. + */ int makemime_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int makemime_main(int argc UNUSED_PARAM, char **argv) { @@ -107,14 +129,14 @@ int makemime_main(int argc UNUSED_PARAM, char **argv) #define boundary opt_output enum { - OPT_c = 1 << 0, // Content-Type: + OPT_c = 1 << 0, // create (non-multipart) section OPT_e = 1 << 1, // Content-Transfer-Encoding. Ignored. Assumed base64 OPT_o = 1 << 2, // output to OPT_C = 1 << 3, // charset OPT_N = 1 << 4, // COMPAT OPT_a = 1 << 5, // additional headers - OPT_m = 1 << 6, // COMPAT - OPT_j = 1 << 7, // COMPAT + //OPT_m = 1 << 6, // create mutipart section + //OPT_j = 1 << 7, // join section to multipart section }; INIT_G(); @@ -122,8 +144,8 @@ int makemime_main(int argc UNUSED_PARAM, char **argv) // parse options opt_complementary = "a::"; opts = getopt32(argv, - "c:e:o:C:N:a:m:j:", - &G.content_type, NULL, &opt_output, &G.opt_charset, NULL, &opt_headers, NULL, NULL + "c:e:o:C:N:a", //:m:j:", + &G.content_type, NULL, &opt_output, &G.opt_charset, NULL, &opt_headers //, NULL, NULL ); //argc -= optind; argv += optind; diff --git a/mailutils/popmaildir.c b/mailutils/popmaildir.c index 77ec71129..6b733441f 100644 --- a/mailutils/popmaildir.c +++ b/mailutils/popmaildir.c @@ -14,9 +14,10 @@ static void pop3_checkr(const char *fmt, const char *param, char **ret) { - const char *msg = command(fmt, param); + char *msg = send_mail_command(fmt, param); char *answer = xmalloc_fgetline(stdin); if (answer && '+' == answer[0]) { + free(msg); if (timeout) alarm(0); if (ret) { @@ -27,7 +28,7 @@ static void pop3_checkr(const char *fmt, const char *param, char **ret) free(answer); return; } - bb_error_msg_and_die("%s failed: %s", msg, answer); + bb_error_msg_and_die("%s failed, reply was: %s", msg, answer); } static void pop3_check(const char *fmt, const char *param) diff --git a/mailutils/sendmail.c b/mailutils/sendmail.c index ec97cf8af..a2eda6937 100644 --- a/mailutils/sendmail.c +++ b/mailutils/sendmail.c @@ -6,6 +6,38 @@ * * Licensed under GPLv2, see file LICENSE in this source tree. */ + +//usage:#define sendmail_trivial_usage +//usage: "[OPTIONS] [RECIPIENT_EMAIL]..." +//usage:#define sendmail_full_usage "\n\n" +//usage: "Read email from stdin and send it\n" +//usage: "\nStandard options:" +//usage: "\n -t Read additional recipients from message body" +//usage: "\n -f SENDER Sender (required)" +//usage: "\n -o OPTIONS Various options. -oi implied, others are ignored" +//usage: "\n -i -oi synonym. implied and ignored" +//usage: "\n" +//usage: "\nBusybox specific options:" +//usage: "\n -v Verbose" +//usage: "\n -w SECS Network timeout" +//usage: "\n -H 'PROG ARGS' Run connection helper" +//usage: "\n Examples:" +//usage: "\n -H 'exec openssl s_client -quiet -tls1 -starttls smtp" +//usage: "\n -connect smtp.gmail.com:25' -ap]" +//usage: "\n -H 'exec openssl s_client -quiet -tls1" +//usage: "\n -connect smtp.gmail.com:465' -ap]" +//usage: "\n -S HOST[:PORT] Server" +//usage: "\n -au Username for AUTH LOGIN" +//usage: "\n -ap Password for AUTH LOGIN" +//usage: "\n -am Authentication method. Ignored. LOGIN is implied" +//usage: "\n" +//usage: "\nOther options are silently ignored; -oi -t is implied" +//usage: IF_MAKEMIME( +//usage: "\nUse makemime applet to create message with attachments" +//usage: ) + #include "libbb.h" #include "mail.h" @@ -13,23 +45,35 @@ // set to 0 to not limit #define MAX_HEADERS 256 +static void send_r_n(const char *s) +{ + if (verbose) + bb_error_msg("send:'%s'", s); + printf("%s\r\n", s); +} + static int smtp_checkp(const char *fmt, const char *param, int code) { char *answer; - const char *msg = command(fmt, param); + char *msg = send_mail_command(fmt, param); // read stdin - // if the string has a form \d\d\d- -- read next string. E.g. EHLO response + // if the string has a form NNN- -- read next string. E.g. EHLO response // parse first bytes to a number // if code = -1 then just return this number // if code != -1 then checks whether the number equals the code // if not equal -> die saying msg - while ((answer = xmalloc_fgetline(stdin)) != NULL) + while ((answer = xmalloc_fgetline(stdin)) != NULL) { +// if (verbose) + bb_error_msg("recv:'%.*s' %d", (int)(strchrnul(answer, '\r') - answer), answer, verbose); if (strlen(answer) <= 3 || '-' != answer[3]) break; + free(answer); + } if (answer) { int n = atoi(answer); if (timeout) alarm(0); + free(msg); free(answer); if (-1 == code || n == code) return n; @@ -86,6 +130,7 @@ int sendmail_main(int argc UNUSED_PARAM, char **argv) OPT_H = 1 << 5, // use external connection helper OPT_S = 1 << 6, // specify connection string OPT_a = 1 << 7, // authentication tokens + OPT_v = 1 << 8, // verbosity }; // init global variables @@ -96,12 +141,13 @@ int sendmail_main(int argc UNUSED_PARAM, char **argv) G.fp0 = xfdopen_for_read(3); // parse options - // -f is required. -H and -S are mutually exclusive - opt_complementary = "f:w+:H--S:S--H:a::"; + // -v is a counter, -f is required. -H and -S are mutually exclusive, -a is a list + opt_complementary = "vv:f:w+:H--S:S--H:a::"; // N.B. since -H and -S are mutually exclusive they do not interfere in opt_connect // -a is for ssmtp (http://downloads.openwrt.org/people/nico/man/man8/ssmtp.8.html) compatibility, // it is still under development. - opts = getopt32(argv, "tf:o:iw:H:S:a::", &opt_from, NULL, &timeout, &opt_connect, &opt_connect, &list); + opts = getopt32(argv, "tf:o:iw:H:S:a::v", &opt_from, NULL, + &timeout, &opt_connect, &opt_connect, &list, &verbose); //argc -= optind; argv += optind; @@ -214,7 +260,7 @@ int sendmail_main(int argc UNUSED_PARAM, char **argv) if ('.' == s[0] /*&& '\0' == s[1] */) printf("."); // dump read line - printf("%s\r\n", s); + send_r_n(s); free(s); continue; } @@ -261,14 +307,14 @@ int sendmail_main(int argc UNUSED_PARAM, char **argv) goto bail; // dump the headers while (list) { - printf("%s\r\n", (char *) llist_pop(&list)); + send_r_n((char *) llist_pop(&list)); } // stop analyzing headers code++; // N.B. !s means: we read nothing, and nothing to be read in the future. // just dump empty line and break the loop if (!s) { - puts("\r"); + send_r_n(""); break; } // go dump message body