Kenneth Finnegan Profile picture
Sep 10, 2020 18 tweets 6 min read Read on X
I've been technically assisting my father on a project where he needs to send an email to a few hundred people.

Previously, he was going it from the Gmail GUI 75 people at a time, copy-paste into bcc in the compose window, but now that I have SMTP infra, why not a for loop? 🧵
Relatively simple problem once you have the email infrastructure up, right?

cat mailinglist | while read EMAILADDR; do cat ./emailbody.txt | mail -s "Subject" -a "From: me@example" $EMAILADDR; done

So I was helping him understand the headers and how best to invoke the mail cmd
Quick and easy bash one-liner when we were ready to launch though, right?

Wrong. My father came back today with his 250 line bash script he wrote for sending this bulk email blast.

And *chef kiss* a work of art it is.
First, you've got your file header with canonical location, purpose, copyright notice, and revision history. Image
Then you start getting into the functional blocks of the code, each titled with a visual block so it's easy to find section breaks while scrolling ImageImageImage
Setup: This script functionally depends on the system environment it's running on.

Namely that it's specifically on the host with the postfix server configured...

So we check that we're on the host we expect to be running on and print an error and quit if not. Image
Function definitions: Just in case you forget the exact command syntax for this shell script, we have a function that prints the usage instructions for it, for when you run it with -h! Image
Next we're into the main functional part of the script, where we start by parsing the command line arguments.

Set them all to a default "", then loop through getopts to parse the arguments given by the user from the CLI Image
You notice how he has all this strange \e[1;31 line noise sprinkled in his echo statements?

Colors. They're ANSI/VT100 color commands.

The error messages for this script print in color. Image
Notable lines in the case statement include...
h) call the usage function, and exit 0, to indicate that the script completely successfully
\?) Puke on unparsable options, print usage, and exit 1 to indicate failure
:) Puke on options which require arguments, print usage, and exit Image
But we're not just going to trust the user. We absolutely need a minimum set of the arguments to run, so we're going to loop through them and check to make sure they're not the empty "" we set them to earlier. Image
And we're not just going to trust that the user gave us a correct filename for the distribution list. We're going to use the if -r flag to check to see that we're able to READ this file the user so dutifully provided us the name for. Image
But what if the user gave us a readable file, but it doth not contain email addresses?

Well then you can go exit 1 to hell too. We aren't going to tolerate that shit around here. Image
The English language has this annoying property where it uses different words for one or many of something.

And users have this annoying habit of speaking English or something, so we... better figure out how many emails we're sending here in "send_bulk_email.sh" 😐 Image
And this isn't for the actual bulk mailing. This is literally just so the interactive prompts and status messages while this script runs are syntactically correct.

Wouldn't want it asking if you wanted to actually launch these "emails" when there's only one email being sent! Image
I will admit... This is kind of at most the dozen lines of bash code I was actually planning on us writing for this project...

while read loop, send email.

He even checks the exit code from mail with the $? built-in so if it starts erroring half way through the loop it exits. Image
And you wouldn't want to leave your TMP files laying around. Who knows how many times you might run this script before you run out of disk space... Image
And that, ladies and gentlemen, is the 250 lines of robust industrial grade bash code my father wrote to send a few hundred emails.

And a look into what it was like growing up in my childhood, if we're really being honest here...

Expecting *everything* to go wrong.

• • •

Missing some Tweet in this thread? You can try to force a refresh
 

Keep Current with Kenneth Finnegan

Kenneth Finnegan Profile picture

Stay in touch and get notified when new unrolls are available from this author!

Read all threads

This Thread may be Removed Anytime!

PDF

Twitter may remove this content at anytime! Save it as PDF for later use!

Try unrolling a thread yourself!

how to unroll video
  1. Follow @ThreadReaderApp to mention us!

  2. From a Twitter thread mention us with a keyword "unroll"
@threadreaderapp unroll

Practice here first or read more on our help page!

More from @KWF

Oct 6, 2022
Are you a flooring installer and you can't be assed to get all your panels of 79¢ laminate to seat right?

It kind of looks like wood, so why not use wood putty to fill the gaps?
And yes, the astute will notice that this laminate is installed wrong anyways because you're supposed to stagger the seams much further apart than that.
Did you drop one of the boxes of panels on its end and badly damage them all?

Those panels are expen... not free! Use them anyways!
Read 4 tweets
Sep 15, 2022
There is standing water in my crawl space.
I found it, but it's now flooding my egress path.

This is my life now. I live under here. Image
Home Warranty claim opened. Speed running home ownership lets goooooo
Read 16 tweets
Dec 13, 2021
One of my nice friends at @henet gave me a dead 100G-LR4 optic to tear apart for your entertainment, so... let's get entertained! 🧵 ImageImage
100G-LR4 is a QSFP28 optic that runs over a duplex pair of single mode fiber, so it takes 4 lanes of 25G from the switch, modulates 4 different colors of light, and combines them together over a single strand to the other end up to 10km away. Image
First comes off the ejection bail.

I guess we're committed now... Image
Read 23 tweets
Nov 27, 2020
Me: "Huh... I wonder why this Ubuntu 20.04 image is still using the SysV networking service..."

Me, two hours later: *The internal screaming intensifies*
In case you can't figure it out, this is a really stupid trick I've seen on IPv4 to save address space where you assign a /32 to the public interface, then point default via a static on-link route to the router on any other address you want.

I have never seen this trick on v6.
"If it's stupid and it works..." does NOT fucking apply here.

It's stupid, and it working doesn't excuse that.
Read 4 tweets
Nov 27, 2020
I can't remember the last time I played a video game, but I bought shapez io for this weekend.

It's definitely enjoyable. All the puzzle solving of Factorio without the combat or resource management
Who doesn't love shapes?
And colors!
Read 4 tweets
Nov 27, 2020
Through a long series of unfortunate events, for our smallest Thanksgiving ever, my dad has ended up cooking a 19lb turkey.
Granted, we also usually do two turkeys and a ham, so I guess just a single turkey of any size is more reasonable.
It's important to remember that a mind boggling number of people are food insecure today, and that's a truly terrifying sensation that's hard to imagine.
Read 5 tweets

Did Thread Reader help you today?

Support us! We are indie developers!


This site is made by just two indie developers on a laptop doing marketing, support and development! Read more about the story.

Become a Premium Member ($3/month or $30/year) and get exclusive features!

Become Premium

Don't want to be a Premium member but still want to support us?

Make a small donation by buying us coffee ($5) or help with server cost ($10)

Donate via Paypal

Or Donate anonymously using crypto!

Ethereum

0xfe58350B80634f60Fa6Dc149a72b4DFbc17D341E copy

Bitcoin

3ATGMxNzCUFzxpMCHL5sWSt4DVtS8UqXpi copy

Thank you for your support!

Follow Us!

:(