I was recently working on a Python script which scrapes a few things from the GitHub API to generate reports. The final result is emailed to a Google Group – old school, I know, perhaps this should just be a Slack webhook. :-)
I've been using Alpine Linux in my containers for several years now. As you may know, it's a lightweight and performant runtime environment perfectly suited to things like CI/CD pipelines which constantly spin up ephemeral tasks.
Deciding to email a report was not a particularly inspired idea... More like creative borrowing (read: plagiarism). Some other scripts I used for reference had simple
cat output | mailx type stuff. Of course those were infrequently-ran, non-containerized scripts where the choice made more sense. Still, initially my uninspired mind went to a dark place – bloat up my sleek Alpine container with a bunch of mail utilities.
Let's see here, I can add in the
mailx CLI (well, on Alpine it's the
mailx package which provides a
As it turns out, your shiny new Alpine container already has everything you need to send email... The answer is BusyBox. No, it's not the latest platform for political arguments (get it, a soapbox with lots of busybody members? Oh wait, we have Facebook and Reddit for that!).
If you've been under a rock for the past decade or two, BusyBox is a venerable Swiss Army Knife of the UNIX world. I didn't make that up, they say so themselves. BusyBox bundles stripped down versions of common UNIX utilities, including sendmail, into a single CLI. Let's see what that provides:
This gives you everything you need to establish TLS connections (for that you will need to
apk add openssl), authenticate, send attachments, etc. My case is simpler, we have an internal Postfix relay which allows internal connections from our VPC CIDR ranges and does the heavy lifting of routing mail via Sendgrid. I simply shove a heredoc into
busybox sendmail with a few arguments:
This generates an email by diffing the current and last reports (summarizing useful things like additions and removals of organization admins), and routes it through the configured mail relay. While it seems repetitive, the
-f "$FROM" is required to avoid some spurious errors from defaulting to the UID/GID running the command. The
From: header is also required, since not including it in this way will result in bounces from Google Groups. The two spaces between the email headers and body is standard message formatting. You can tweak these as needed, and in particular might not want
-v which will include the full SMTP session in output (including connection negotiation and data).
With these, we can generate
spam er I mean useful reports with the best of them... Taking it one step further, we don't have to call
busybox. Alpine has a number of symlinks for common utilities. In this case we can just call
sendmail directly, and the name of the symlink is used by BusyBox to invoke the desired functionality: