mailutils/*: add verbose option to sendmail; remove -m and -j from makemime
authorDenys Vlasenko <vda.linux@googlemail.com>
Mon, 20 Dec 2010 04:12:39 +0000 (05:12 +0100)
committerDenys Vlasenko <vda.linux@googlemail.com>
Mon, 20 Dec 2010 04:12:39 +0000 (05:12 +0100)
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
include/usage.src.h
mailutils/mail.c
mailutils/mail.h
mailutils/mime.c
mailutils/popmaildir.c
mailutils/sendmail.c

index cd37a892dc6c65e6b36ec93dfc8bbeedddd20106..4640338e6657332da0b2d044a34066b9f2715c86 100644 (file)
@@ -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' <email.txt" \
-     "\n                               [4<username_and_passwd.txt | -au<username> -ap<password>]" \
-     "\n                       -H 'exec openssl s_client -quiet -tls1" \
-     "\n                               -connect smtp.gmail.com:465' <email.txt" \
-     "\n                               [4<username_and_passwd.txt | -au<username> -ap<password>]" \
-     "\n       -S server[:port] Server" \
-     "\n       -au<username>   Username for AUTH LOGIN" \
-     "\n       -ap<password>   Password for AUTH LOGIN" \
-     "\n       -am<method>     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" \
index 9b4bebce53c0bde7cae74a2c900d9b62b407d158..44957016feb94d979d4fdb0257b1092112cef46e 100644 (file)
@@ -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
index e0048fbfae04c50c56ae6add0e83d97d977a0a84..d1d783055a3b703b84d6e7fdacfc19ec14c190b4 100644 (file)
@@ -1,7 +1,16 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * helper routines
+ *
+ * Copyright (C) 2008 by Vladimir Dronnikov <dronnikov@gmail.com>
+ *
+ * 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;
index 682cf4536795c70f7a41a89db0c11a50474006e6..1e393ed31eec5971b630727e557c0d00a6e43668 100644 (file)
@@ -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;
index 77ec71129a8e96088571384c7fb12fb78f480a16..6b733441f7939fccd094315ad62dcbc4c6d9b7c1 100644 (file)
 
 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)
index ec97cf8afceeff16e9355d36ff85ed0f657b6af0..a2eda693755a608c4d8705e18d803f6cace1f1a7 100644 (file)
@@ -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' <email.txt"
+//usage:     "\n                               [4<username_and_passwd.txt | -au<username> -ap<password>]"
+//usage:     "\n                       -H 'exec openssl s_client -quiet -tls1"
+//usage:     "\n                               -connect smtp.gmail.com:465' <email.txt"
+//usage:     "\n                               [4<username_and_passwd.txt | -au<username> -ap<password>]"
+//usage:     "\n       -S HOST[:PORT]  Server"
+//usage:     "\n       -au<username>   Username for AUTH LOGIN"
+//usage:     "\n       -ap<password>   Password for AUTH LOGIN"
+//usage:     "\n       -am<method>     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"
 
 // 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