Monday, 10 August 2015

Sending email using mailx - Override Content-Type and Standardise Parameters

Background

Recently I needed to send an HTML email from a Ubuntu 14.04 x86 system with without any MTA installed and with very little disk space left. I didn't want to install more large packages (Perl, Java, Python, etc...) and I wanted a standard way of sending emails across many different distributions and architectures moving forwards.

Anyone who has messed with mailx on different platforms knows there are several different implementations (heirloom, mailutils, etc...), which use different parameters. This is an absolute pain when trying to support more than 1 platform. The mailx variant present on my target system did not support setting the custom Content-Type header and so HTML emails were always displayed as plain-text in E-mail clients. As a result I decided to use adopt 's-nail' from Arch Linux and add this functionality in.

Home page: https://wiki.archlinux.org/index.php/S-nail

Building

S-nail only needs a basic development environment and OpenSSL libs/headers installed i.e. a Ubuntu 14.04 x86_64 box with 'build-essential' package group installed and libssl1.0.0:i386

Once the build environment is in place:

  1. Get code: git clone https://gitlab.com/sdaoden/s-nail.git
  2. Save diff contents (as below) to "s-nail_v14.8.4a.diff"
  3. Change to 's-nail' source directory and run: patch -p1 < ../s-nail_v14.8.4a.diff
  4. Make s-nail (32bit): ADDCFLAGS="-m32" ADDLDFLAGS="-m32" make

If all goes well the output generates the ./s-nail 32bit executable (~560KB) which supports the -C parameter to set the Content-Type. The only libs required by this executable are libssl and libcrypto, which in my case were already present on the target system:
# ldd ./s-nail        linux-gate.so.1 =>  (0xb7732000)        libssl.so.1.0.0 => /lib/i386-linux-gnu/libssl.so.1.0.0 (0xb7641000)        libcrypto.so.1.0.0 => /lib/i386-linux-gnu/libcrypto.so.1.0.0 (0xb7494000)        libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xb72e4000)        libdl.so.2 => /lib/i386-linux-gnu/libdl.so.2 (0xb72df000)        /lib/ld-linux.so.2 (0xb7733000) Usage
Once copied to the target system I could send an email direct to a SMTP SSL/TLS enabled host via the following invocation:
env MAILRC=/dev/null from=${mailFrom} smtp=${smtpHost} smtp-auth-user=${smtpUser} smtp-auth-password=${smtpPass} smtp-auth=login /usr/bin/s-nail -S smtp-use-starttls -C "text/html" -v -n -s "${subject}" ${recipient} < "${emailBodyFile}"
The variables are:

mailFrom = Originating email address
smtpHost = SMTP server URI, e.g: smtp://smtp.gmail.com
smtpUser = SMTP user
smtpPass = SMTP password
subject = Email subject
recepient = Recepient email address
emailBodyFile = File containing HTML email to send

s-nail_v14.8.4a.diff contents is as follows:
diff -rupN -x .git s-nail/main.c s-nail.new/main.c
--- s-nail/main.c       2015-08-10 16:46:36.482039386 +0100
+++ s-nail.new/main.c   2015-08-10 16:42:10.134039386 +0100
@@ -613,7 +613,7 @@ _X_arg_eval(struct X_arg *xhp) /* TODO e
 int
 main(int argc, char *argv[])
 {
-   static char const optstr[] = "A:a:Bb:c:DdEeFfHhiL:NnO:q:Rr:S:s:tu:VvX:~#.",
+   static char const optstr[] = "A:a:Bb:c:C:DdEeFfHhiL:NnO:q:Rr:S:s:tu:VvX:~#.",
       usagestr[] = N_(
          " Synopsis:\n"
          "  %s -h | --help\n"
@@ -639,6 +639,7 @@ main(int argc, char *argv[])
    size_t oargs_size = 0, oargs_count = 0, smopts_size = 0;
    int i;
    NYD_ENTER;
+   ct_override = NULL;

    /*

     * Start our lengthy setup, finalize by setting PS_STARTED
@@ -679,6 +680,9 @@ main(int argc, char *argv[])
          options |= OPT_SENDMODE;
          bcc = cat(bcc, lextract(_oarg, GBCC | GFULL));
          break;
+      case 'C':
+         ct_override=_oarg;
+         break;
       case 'c':
          /* Get Carbon Copy Recipient list */
          options |= OPT_SENDMODE;
diff -rupN -x .git s-nail/nail.h s-nail.new/nail.h
--- s-nail/nail.h       2015-08-10 16:46:36.486039386 +0100
+++ s-nail.new/nail.h   2015-08-10 16:40:51.318039386 +0100
@@ -1898,6 +1898,8 @@ VL char const  *temporary_protocol_ext;

 /* The remaining variables need initialization */


+VL char *ct_override;

+
 #ifndef HAVE_AMALGAMATION
 VL char const  month_names[12 + 1][4];
 VL char const  weekday_names[7 + 1][4];
diff -rupN -x .git s-nail/sendout.c s-nail.new/sendout.c
--- s-nail/sendout.c    2015-08-10 16:46:36.486039386 +0100
+++ s-nail.new/sendout.c        2015-08-10 16:50:13.638039386 +0100
@@ -634,6 +634,9 @@ infix(struct header *hp, FILE *fi) /* TO
       goto jleave;

    contenttype = "text/plain"; /* XXX mail body - always text/plain, want XX? */

+   if (ct_override != NULL) {
+      contenttype=ct_override;
+   }
    convert = mime_type_file_classify(fi, &contenttype, &charset, &do_iconv);

 #ifdef HAVE_ICONV

diff -rupN -x .git s-nail/version.h s-nail.new/version.h
--- s-nail/version.h    2015-08-10 16:46:36.490039386 +0100
+++ s-nail.new/version.h        2015-08-10 16:45:26.674039386 +0100
@@ -1,4 +1,4 @@
-#define VERSION "v14.8.4"
+#define VERSION "v14.8.4a"
 #define VERSION_MAJOR "14"
 #define VERSION_MINOR "8"
-#define VERSION_UPDATE "4"
+#define VERSION_UPDATE "4a"
--
Steve

No comments:

Post a Comment