diff options
author | EuAndreh <eu@euandre.org> | 2025-03-31 21:51:40 -0300 |
---|---|---|
committer | EuAndreh <eu@euandre.org> | 2025-03-31 21:51:40 -0300 |
commit | 570ec471d1605318aeefb030cd78682ae442235b (patch) | |
tree | 51e17eabe37c6689f8799b55e6875c3480329a2c /src/content/tils/2021/01 | |
parent | Makefile, mkdeps.sh: Derive index.html and feed.xml from more static "sortdat... (diff) | |
download | euandre.org-570ec471d1605318aeefb030cd78682ae442235b.tar.gz euandre.org-570ec471d1605318aeefb030cd78682ae442235b.tar.xz |
src/content/: Update all files left to asciidoc
Diffstat (limited to 'src/content/tils/2021/01')
-rw-r--r-- | src/content/tils/2021/01/12/curl-awk-emails.adoc | 100 | ||||
-rw-r--r-- | src/content/tils/2021/01/17/posix-shebang.adoc | 63 |
2 files changed, 86 insertions, 77 deletions
diff --git a/src/content/tils/2021/01/12/curl-awk-emails.adoc b/src/content/tils/2021/01/12/curl-awk-emails.adoc index 880ddf1..875c655 100644 --- a/src/content/tils/2021/01/12/curl-awk-emails.adoc +++ b/src/content/tils/2021/01/12/curl-awk-emails.adoc @@ -1,28 +1,25 @@ ---- += Awk snippet: send email to multiple recipients with cURL -title: 'Awk snippet: send email to multiple recipients with cURL' +:neomutt: https://neomutt.org/ +:found-out-article: https://blog.edmdesigner.com/send-email-from-linux-command-line/ +:curl: https://curl.se/ -date: 2021-01-12 - -layout: post - -lang: en - -ref: awk-snippet-send-email-to-multiple-recipients-with-curl - ---- - -As I experiment with [Neomutt][neomutt], I wanted to keep being able to enqueue emails for sending later like my previous setup, so that I didn't rely on having an internet connection. +As I experiment with {neomutt}[Neomutt], I wanted to keep being able to enqueue +emails for sending later like my previous setup, so that I didn't rely on having +an internet connection. My requirements for the `sendmail` command were: -1. store the email in a file, and send it later. -1. send from different addresses, using different SMTP servers; -I couldn't find an MTA that could accomplish that, but I was able to quickly write a solution. +. store the email in a file, and send it later; +. send from different addresses, using different SMTP servers. + +I couldn't find an MTA that could accomplish that, but I was able to quickly +write a solution. The first part was the easiest: store the email in a file: -```shell +[source,shell] +---- # ~/.config/mutt/muttrc: set sendmail=~/bin/enqueue-email.sh @@ -30,20 +27,24 @@ set sendmail=~/bin/enqueue-email.sh #!/bin/sh -eu cat - > "$HOME/mbsync/my-queued-emails/$(date -Is)" -``` +---- -Now that I had the email file store locally, I needed a program to send the email from the file, so that I could create a cronjob like: +Now that I had the email file store locally, I needed a program to send the +email from the file, so that I could create a cronjob like: -```shell +[source,shell] +---- for f in ~/mbsync/my-queued-emails/*; do ~/bin/dispatch-email.sh "$f" && rm "$f" done -``` +---- -The `dispatch-email.sh` would have to look at the `From: ` header and decide which SMTP server to use. -As I [found out][curl-email] that [curl][curl] supports SMTP and is able to send emails, this is what I ended up with: +The `dispatch-email.sh` would have to look at the `From:` header and decide +which SMTP server to use. As I {found-out-article}[found out] that {curl}[curl] +supports SMTP and is able to send emails, this is what I ended up with: -```shell +[source,shell] +---- #!/bin/sh -eu F="$1" @@ -79,24 +80,30 @@ else echo 'Bad "From: " address' exit 1 fi -``` +---- Most of curl flags used are self-explanatory, except for `$rcpt`. -curl connects to the SMTP server, but doesn't set the recipient address by looking at the message. -My solution was to generate the curl flags, store them in `$rcpt` and use it unquoted to leverage shell word splitting. +curl connects to the SMTP server, but doesn't set the recipient address by +looking at the message. My solution was to generate the curl flags, store them +in `$rcpt` and use it unquoted to leverage shell word splitting. -To me, the most interesting part was building the `$rcpt` flags. -My first instinct was to try grep, but it couldn't print only matches in a regex. -As I started to turn towards sed, I envisioned needing something else to loop over the sed output, and I then moved to Awk. +To me, the most interesting part was building the `$rcpt` flags. My first +instinct was to try grep, but it couldn't print only matches in a regex. As I +started to turn towards sed, I envisioned needing something else to loop over +the sed output, and I then moved to Awk. -In the short Awk snippet, 3 things were new to me: the `match(...)`, `split(...)` and `for () {}`. -The only other function I have ever used was `gsub(...)`, but these new ones felt similar enough that I could almost guess their behaviour and arguments. -`match(...)` stores the matches of a regex on the given array positionally, and `split(...)` stores the chunks in the given array. +In the short Awk snippet, 3 things were new to me: the `match(...)`, +`split(...)` and `for () {}`. The only other function I have ever used was +`gsub(...)`, but these new ones felt similar enough that I could almost guess +their behaviour and arguments. `match(...)` stores the matches of a regex on +the given array positionally, and `split(...)` stores the chunks in the given +array. I even did it incrementally: -```shell +[source,shell] +---- $ H='To: to@example.com, to2@example.com\nCc: cc@example.com, cc2@example.com\nBcc: bcc@example.com,bcc2@example.com\n' $ printf "$H" | awk '/^To: .*$/ { print $0 }' To: to@example.com, to2@example.com @@ -115,28 +122,27 @@ to@example.com, $ printf "$H" | awk 'match($0, /^To: (.*)$/, m) { split(m[1], tos, " "); print tos[2] }' to2@example.com $ printf "$H" | awk 'match($0, /^To: (.*)$/, m) { split(m[1], tos, " "); print tos[3] }' +---- -``` +(This isn't the verbatim interactive session, but a cleaned version to make it +more readable.) -(This isn't the verbatim interactive session, but a cleaned version to make it more readable.) +At this point, I realized I needed a for loop over the `tos` array, and I moved +the Awk snippet into the `~/bin/dispatch-email.sh`. I liked the final thing: -At this point, I realized I needed a for loop over the `tos` array, and I moved the Awk snippet into the `~/bin/dispatch-email.sh`. -I liked the final thing: - -```awk +[source,awk] +---- match($0, /^(To|Cc|Bcc): (.*)$/, m) { split(m[2], tos, ",") for (i in tos) { print "--mail-rcpt " tos[i] } } -``` +---- -As I learn more about Awk, I feel that it is too undervalued, as many people turn to Perl or other programming languages when Awk suffices. -The advantage is pretty clear: writing programs that run on any POSIX system, without extra dependencies required. +As I learn more about Awk, I feel that it is too undervalued, as many people +turn to Perl or other programming languages when Awk suffices. The advantage is +pretty clear: writing programs that run on any POSIX system, without extra +dependencies required. Coding to the standards is underrated. - -[neomutt]: https://neomutt.org/ -[curl-email]: https://blog.edmdesigner.com/send-email-from-linux-command-line/ -[curl]: https://curl.se/ diff --git a/src/content/tils/2021/01/17/posix-shebang.adoc b/src/content/tils/2021/01/17/posix-shebang.adoc index 5f5b897..4e2fbe8 100644 --- a/src/content/tils/2021/01/17/posix-shebang.adoc +++ b/src/content/tils/2021/01/17/posix-shebang.adoc @@ -1,55 +1,58 @@ = POSIX sh and shebangs -date: 2021-01-17 +:awk-1: link:../../../2020/12/15/shellcheck-repo.html +:awk-2: link:../12/curl-awk-emails.html -layout: post +As I {awk-1}[keep moving] {awk-2}[towards POSIX], I'm on the process of +migrating all my Bash scripts to POSIX sh. -lang: en - -ref: posix-sh-and-shebangs - ---- - -As I [keep moving][posix-awk-0] [towards POSIX][posix-awk-1], I'm on the process of migrating all my Bash scripts to POSIX sh. - -As I dropped `[[`, arrays and other Bashisms, I was left staring at the first line of every script, wondering what to do: what is the POSIX sh equivalent of `#!/usr/bin/env bash`? -I already knew that POSIX says nothing about shebangs, and that the portable way to call a POSIX sh script is `sh script.sh`, but I didn't know what to do with that first line. +As I dropped `[[`, arrays and other Bashisms, I was left staring at the first +line of every script, wondering what to do: what is the POSIX sh equivalent of +`#!/usr/bin/env bash`? I already knew that POSIX says nothing about shebangs, +and that the portable way to call a POSIX sh script is `sh script.sh`, but +I didn't know what to do with that first line. What I had previously was: -```shell + +[source,shell] +---- #!/usr/bin/env bash set -Eeuo pipefail cd "$(dirname "${BASH_SOURCE[0]}")" -``` +---- -Obviously, the `$BASH_SOURCE` would be gone, and I would have to adapt some of my scripts to not rely on the script location. -The `-E` and `-o pipefail` options were also gone, and would be replaced by nothing. +Obviously, the `$BASH_SOURCE` would be gone, and I would have to adapt some of +my scripts to not rely on the script location. The `-E` and `-o pipefail` +options were also gone, and would be replaced by nothing. I converted all of them to: -```shell + +[source,shell] +---- #!/bin/sh -eu -``` +---- I moved the `-eu` options to the shebang line itself, striving for conciseness. -But as I changed callers from `./script.sh` to `sh script.sh`, things started to fail. -Some tests that should fail reported errors, but didn't return 1. +But as I changed callers from `./script.sh` to `sh script.sh`, things started to +fail. Some tests that should fail reported errors, but didn't return 1. -My first reaction was to revert back to `./script.sh`, but the POSIX bug I caught is a strong strain, and when I went back to it, I figured that the callers were missing some flags. -Specifically, `sh -eu script.sh`. +My first reaction was to revert back to `./script.sh`, but the POSIX bug I +caught is a strong strain, and when I went back to it, I figured that the +callers were missing some flags. Specifically, `sh -eu script.sh`. -Then it clicked: when running with `sh script.sh`, the shebang line with the sh options is ignored, as it is a comment! +Then it clicked: when running with `sh script.sh`, the shebang line with the sh +options is ignored, as it is a comment! Which means that the shebang most friendly with POSIX is: -```shell +[source,shell] +---- #!/bin/sh set -eu -``` +---- -1. when running via `./script.sh`, if the system has an executable at `/bin/sh`, it will be used to run the script; -2. when running via `sh script.sh`, the sh options aren't ignored as previously. +. when running via `./script.sh`, if the system has an executable at `/bin/sh`, + it will be used to run the script; +. when running via `sh script.sh`, the sh options aren't ignored as previously. TIL. - -[posix-awk-0]: {% link _tils/2020-12-15-awk-snippet-shellcheck-all-scripts-in-a-repository.md %} -[posix-awk-1]: {% link _tils/2021-01-12-awk-snippet-send-email-to-multiple-recipients-with-curl.md %} |