summaryrefslogtreecommitdiff
path: root/src/content/tils/2021/01
diff options
context:
space:
mode:
authorEuAndreh <eu@euandre.org>2025-04-18 02:17:12 -0300
committerEuAndreh <eu@euandre.org>2025-04-18 02:48:42 -0300
commit020c1e77489b772f854bb3288b9c8d2818a6bf9d (patch)
tree142aec725a52162a446ea7d947cb4347c9d573c9 /src/content/tils/2021/01
parentMakefile: Remove security.txt.gz (diff)
downloadeuandre.org-020c1e77489b772f854bb3288b9c8d2818a6bf9d.tar.gz
euandre.org-020c1e77489b772f854bb3288b9c8d2818a6bf9d.tar.xz
git mv src/content/* src/content/en/
Diffstat (limited to 'src/content/tils/2021/01')
-rw-r--r--src/content/tils/2021/01/12/curl-awk-emails.adoc148
-rw-r--r--src/content/tils/2021/01/17/posix-shebang.adoc58
2 files changed, 0 insertions, 206 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
deleted file mode 100644
index d432da2..0000000
--- a/src/content/tils/2021/01/12/curl-awk-emails.adoc
+++ /dev/null
@@ -1,148 +0,0 @@
-= 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/
-
-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:
-
-. 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:
-
-[source,sh]
-----
-# ~/.config/mutt/muttrc:
-set sendmail=~/bin/enqueue-email.sh
-
-# ~/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:
-
-[source,sh]
-----
-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-article}[found out] that {curl}[curl]
-supports SMTP and is able to send emails, this is what I ended up with:
-
-[source,sh]
-----
-#!/bin/sh -eu
-
-F="$1"
-
-rcpt="$(awk '
- match($0, /^(To|Cc|Bcc): (.*)$/, m) {
- split(m[2], tos, ",")
- for (i in tos) {
- print "--mail-rcpt " tos[i]
- }
- }
-' "$F")"
-
-if grep -qE '^From: .*<addr@server1\.org>$' "$F"; then
- curl \
- -s \
- --url smtp://smtp.server1.org:587 \
- --ssl-reqd \
- --mail-from addr@server1.org \
- $rcpt \
- --user 'addr@server1.org:my-long-and-secure-passphrase' \
- --upload-file "$F"
-elif grep -qE '^From: .*<addr@server2\.org>$' "$F"; then
- curl \
- -s \
- --url smtp://smtp.server2.org:587 \
- --ssl-reqd \
- --mail-from addr@server2.org \
- $rcpt \
- --user 'addr@server2.org:my-long-and-secure-passphrase' \
- --upload-file "$F"
-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.
-
-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.
-
-I even did it incrementally:
-
-[source,sh]
-----
-$ 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
-$ printf "$H" | awk 'match($0, /^To: (.*)$/, m) { print m }'
-awk: ligne de commande:1: (FILENAME=- FNR=1) fatal : tentative d'utilisation du tableau « m » dans un contexte scalaire
-$ printf "$H" | awk 'match($0, /^To: (.*)$/, m) { print m[0] }'
-To: to@example.com, to2@example.com
-$ printf "$H" | awk 'match($0, /^To: (.*)$/, m) { print m[1] }'
-to@example.com, to2@example.com
-$ printf "$H" | awk 'match($0, /^To: (.*)$/, m) { split(m[1], tos, " "); print tos }'
-awk: ligne de commande:1: (FILENAME=- FNR=1) fatal : tentative d'utilisation du tableau « tos » dans un contexte scalaire
-$ printf "$H" | awk 'match($0, /^To: (.*)$/, m) { split(m[1], tos, " "); print tos[0] }'
-
-$ printf "$H" | awk 'match($0, /^To: (.*)$/, m) { split(m[1], tos, " "); print tos[1] }'
-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.)
-
-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:
-
-[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.
-
-Coding to the standards is underrated.
diff --git a/src/content/tils/2021/01/17/posix-shebang.adoc b/src/content/tils/2021/01/17/posix-shebang.adoc
deleted file mode 100644
index 5cf0695..0000000
--- a/src/content/tils/2021/01/17/posix-shebang.adoc
+++ /dev/null
@@ -1,58 +0,0 @@
-= POSIX sh and shebangs
-
-:awk-1: link:../../../2020/12/15/shellcheck-repo.html
-:awk-2: link:../12/curl-awk-emails.html
-
-As I {awk-1}[keep moving] {awk-2}[towards POSIX], 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.
-
-What I had previously was:
-
-[source,sh]
-----
-#!/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.
-
-I converted all of them to:
-
-[source,sh]
-----
-#!/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.
-
-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!
-
-Which means that the shebang most friendly with POSIX is:
-
-[source,sh]
-----
-#!/bin/sh
-set -eu
-----
-
-. 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.