Send As SMS

Friday, August 25, 2006

Sending big files via SMTP, or, is there anything that socat cannot do?

I had a need to copy a large file from one place to another and it happened that an existing SMTP server at the destination was an ideal way to receive it, which left only the question of how to send it.

The file is huge (tens of MB) which more or less precludes using most mail clients to send it and, anyway, I had no desire to have it forwarded by an intermediate MTA which might choke on it, bounce it, or delay it. So, I started poking around at what APT knew about which might be of use.
  • Ssmtp and nullmailer are both candidates, but both require messing about with config files, and installing either of them will conflict-out any existing MTA.
  • Fetchmail appealed, as it uses SMTP as its primary delivery mechanism and allows you to specify the host to talk to but, as far as I can tell, offers no means to process a message file that you already have in your possession; it's raison d'etre is to fetch mail from elsewhere and, consequently, it requires a POP/IMAP/etc. server to provide it with the message.
  • Procmail (+formail) seemed like another approach but, as far as I can tell, it will only send via the /usr/lib/sendmail of the installed MTA, which is exactly what I did not want to do.
  • While peering at the formail documentation, I mused that this would be a cool addon to socat. On a whim, I checked the man page for the string SMTP and, naturally, it was there!
So (assuming Debian):

# apt-get install mpack socat

$ mpack -s "BigFile attached" -o message.txt BigFile
$ socat EXEC:"/usr/share/doc/socat/examples/ -f",fdin=3,fdout=4,crnl <message.txt

  • Mpack takes care of creating a valid RFC2822 message containing the file (split into chunks if required) to deliver via SMTP in the first place.
  • I've modified the manpage example to provide the full path and remove bind= and mss=; they are interesting options, but rarely required.
  • I've also modified the manpage example to add the undocumented '-f sender' option to, which matters if the SMTP server is validating sender addresses and $USER@$(hostname) happens not to be a valid email address.