--- doc/nullmailer-send.8~ Sat Mar 5 10:13:38 2005 +++ doc/nullmailer-send.8 Sat Mar 5 10:16:51 2005 @@ -57,10 +57,11 @@ The protocol name defaults to .IR smtp , and may be followed by command-line arguments for that module. -For example, to connect to port 2525 on your SMTP smart host, use: +For example, to connect to port 2525 on your SMTP smart host, +which also requires SMTP authentication, use: .EX - smarthost.dom smtp --port=2525 + smarthost.dom smtp --port=2525 --auth=user,pass .EE Blank lines and lines starting with a pound are ignored. --- protocols/protocol.cc~ Sat Mar 5 09:38:23 2005 +++ protocols/protocol.cc Sat Mar 5 09:39:42 2005 @@ -30,10 +30,12 @@ const char* cli_help_suffix = ""; const char* cli_args_usage = "remote-address < mail-file"; const int cli_args_min = 1; -const int cli_args_max = 1; +const int cli_args_max = 2; cli_option cli_options[] = { { 'p', "port", cli_option::integer, 0, &port, "Set the port number on the remote host to connect to", 0 }, + { 'a', "auth", cli_option::string, 0, &auth, + "Set the user and password for authentication (user,pass)", 0 }, {0, 0, cli_option::flag, 0, 0, 0, 0} }; --- protocols/protocol.h~ Sat Mar 5 09:40:15 2005 +++ protocols/protocol.h Sat Mar 5 09:40:46 2005 @@ -8,6 +8,7 @@ // This must be provided by the protocol, but will be set by the lib. extern int port; +extern char* auth; extern void protocol_prep(fdibuf* in); extern void protocol_send(fdibuf* in, int fd); --- protocols/qmqp.cc~ Sat Mar 5 09:40:59 2005 +++ protocols/qmqp.cc Sat Mar 5 09:41:21 2005 @@ -31,6 +31,7 @@ #include "protocol.h" int port = 628; +char* auth = ""; const char* cli_program = "qmqp"; const char* cli_help_prefix = "Send an emal message via QMQP\n"; --- protocols/smtp.cc~ Sat Mar 5 09:41:31 2005 +++ protocols/smtp.cc Sat Mar 5 09:44:58 2005 @@ -30,6 +30,7 @@ #include "protocol.h" int port = 25; +char* auth = ""; const char* cli_program = "smtp"; const char* cli_help_prefix = "Send an email message via SMTP\n"; @@ -136,6 +137,11 @@ { } +void to64(char* infile, char* outfile); +void to64(const mystring& infile, mystring& outfile); +void output64chunk(int c1, int c2, int c3, int pads, char** outfile); +void output64chunk(int c1, int c2, int c3, int pads, mystring& outfile); + void protocol_send(fdibuf* in, int fd) { mystring hh = getenv("HELOHOST"); @@ -143,5 +149,68 @@ smtp conn(fd); conn.docmd("", 200); conn.docmd("HELO " + hh, 200); + + if ( strlen(auth) > 0 ) + { + mystring authstr = auth; + mystring uname = authstr.left(authstr.find_first(',')); + mystring pass = authstr.sub(authstr.find_first(',')+1,authstr.length()); + mystring plain = uname + "\1" + uname + "\1" + pass; + mystring encoded = "AUTH PLAIN "; + to64(plain,encoded); + conn.docmd(encoded,200); + } + conn.send(in); } + +static char basis_64[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +void to64(const mystring& infile, mystring& outfile) +{ + int c1, c2, c3; + size_t inpos = 0; + while ((c1 = infile[inpos++])) { + c2 = infile[inpos++]; + if (!c2) { + output64chunk(c1, 0, 0, 2, outfile); + } else { + c3 = infile[inpos++]; + if (!c3) { + output64chunk(c1, c2, 0, 1, outfile); + } else { + output64chunk(c1, c2, c3, 0, outfile); + } + } + } +} + +void output64chunk(int c1, int c2, int c3, int pads, mystring& outfile) +{ + if (c1==1) c1 = 0; + if (c2==1) c2 = 0; + if (c3==1) c3 = 0; + + char out[5]; + out[0] = basis_64[c1>>2]; + out[1] = basis_64[((c1 & 0x3)<< 4) | ((c2 & 0xF0) >> 4)]; + switch (pads) + { + case 0: + out[2] = basis_64[((c2 & 0xF) << 2) | ((c3 & 0xC0) >>6)]; + out[3] = basis_64[c3 & 0x3F]; + break; + case 1: + out[2] = basis_64[((c2 & 0xF) << 2) | ((c3 & 0xC0) >>6)]; + out[3] = '='; + break; + case 2: + out[2] = '='; + out[3] = '='; + break; + }; + out[4] = 0; + outfile += out; +} +