aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--_tils/2021-01-12-awk-snippet-send-email-to-multiple-recipients-with-curl.md142
-rw-r--r--locale/eo/LC_MESSAGES/_tils/2021-01-12-awk-snippet-send-email-to-multiple-recipients-with-curl.po243
-rw-r--r--locale/fr/LC_MESSAGES/_tils/2021-01-12-awk-snippet-send-email-to-multiple-recipients-with-curl.po243
-rw-r--r--locale/pt/LC_MESSAGES/_tils/2021-01-12-awk-snippet-send-email-to-multiple-recipients-with-curl.po243
-rw-r--r--scripts/spelling/international.txt8
5 files changed, 879 insertions, 0 deletions
diff --git a/_tils/2021-01-12-awk-snippet-send-email-to-multiple-recipients-with-curl.md b/_tils/2021-01-12-awk-snippet-send-email-to-multiple-recipients-with-curl.md
new file mode 100644
index 0000000..3ac5b97
--- /dev/null
+++ b/_tils/2021-01-12-awk-snippet-send-email-to-multiple-recipients-with-curl.md
@@ -0,0 +1,142 @@
+---
+
+title: 'Awk snippet: send email to multiple recipients with cURL'
+
+date: 2021-01-12
+
+layout: post
+
+lang: en
+
+ref: awk-snippet-send-email-to-multiple-recipients-with-curl
+
+---
+
+As I experimented 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.
+
+The first part was the easiest: store the email in a file:
+
+```shell
+# ~/.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:
+
+```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:
+
+```shell
+#!/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:
+
+```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
+$ 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:
+
+```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.
+
+[neomutt]: https://neomutt.org/
+[curl-email]: https://blog.edmdesigner.com/send-email-from-linux-command-line/
+[curl]: https://curl.se/
diff --git a/locale/eo/LC_MESSAGES/_tils/2021-01-12-awk-snippet-send-email-to-multiple-recipients-with-curl.po b/locale/eo/LC_MESSAGES/_tils/2021-01-12-awk-snippet-send-email-to-multiple-recipients-with-curl.po
new file mode 100644
index 0000000..7561292
--- /dev/null
+++ b/locale/eo/LC_MESSAGES/_tils/2021-01-12-awk-snippet-send-email-to-multiple-recipients-with-curl.po
@@ -0,0 +1,243 @@
+#
+msgid ""
+msgstr ""
+
+msgid "title: 'Awk snippet: send email to multiple recipients with cURL'"
+msgstr ""
+
+msgid "date: 2021-01-12"
+msgstr ""
+
+msgid "layout: post"
+msgstr ""
+
+msgid "lang: en"
+msgstr ""
+
+msgid "ref: awk-snippet-send-email-to-multiple-recipients-with-curl"
+msgstr ""
+
+msgid "My requirements for the `sendmail` command were:"
+msgstr ""
+
+msgid "store the email in a file, and send it later."
+msgstr ""
+
+msgid "send from different addresses, using different SMTP servers;"
+msgstr ""
+
+msgid ""
+"I couldn't find an MTA that could accomplish that, but I was able to quickly"
+" write a solution."
+msgstr ""
+
+msgid "The first part was the easiest: store the email in a file:"
+msgstr ""
+
+msgid ""
+"# ~/.config/mutt/muttrc:\n"
+"set sendmail=~/bin/enqueue-email.sh\n"
+"\n"
+"# ~/bin/enqueue-email.sh:\n"
+"#!/bin/sh -eu\n"
+"\n"
+"cat - > \"$HOME/mbsync/my-queued-emails/$(date -Is)\"\n"
+msgstr ""
+
+msgid ""
+"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:"
+msgstr ""
+
+msgid ""
+"for f in ~/mbsync/my-queued-emails/*; do\n"
+" ~/bin/dispatch-email.sh \"$f\" && rm \"$f\"\n"
+"done\n"
+msgstr ""
+
+msgid ""
+"The `dispatch-email.sh` would have to look at the `From: ` header and decide"
+" which SMTP server to use. As I [found "
+"out](https://blog.edmdesigner.com/send-email-from-linux-command-line/) that "
+"[curl](https://curl.se/) supports SMTP and is able to send emails, this is "
+"what I ended up with:"
+msgstr ""
+
+msgid "Most of curl flags used are self-explanatory, except for `$rcpt`."
+msgstr ""
+
+msgid ""
+"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."
+msgstr ""
+
+msgid ""
+"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."
+msgstr ""
+
+msgid ""
+"$ H='To: to@example.com, to2@example.com\\nCc: cc@example.com, cc2@example.com\\nBcc: bcc@example.com,bcc2@example.com\\n'\n"
+"$ printf \"$H\" | awk '/^To: .*$/ { print $0 }'\n"
+"To: to@example.com, to2@example.com\n"
+"$ printf \"$H\" | awk 'match($0, /^To: (.*)$/, m) { print m }'\n"
+"awk: ligne de commande:1: (FILENAME=- FNR=1) fatal : tentative d'utilisation du tableau « m » dans un contexte scalaire\n"
+"$ printf \"$H\" | awk 'match($0, /^To: (.*)$/, m) { print m[0] }'\n"
+"To: to@example.com, to2@example.com\n"
+"$ printf \"$H\" | awk 'match($0, /^To: (.*)$/, m) { print m[1] }'\n"
+"to@example.com, to2@example.com\n"
+"$ printf \"$H\" | awk 'match($0, /^To: (.*)$/, m) { split(m[1], tos, \" \"); print tos }'\n"
+"awk: ligne de commande:1: (FILENAME=- FNR=1) fatal : tentative d'utilisation du tableau « tos » dans un contexte scalaire\n"
+"$ printf \"$H\" | awk 'match($0, /^To: (.*)$/, m) { split(m[1], tos, \" \"); print tos[0] }'\n"
+"\n"
+"$ printf \"$H\" | awk 'match($0, /^To: (.*)$/, m) { split(m[1], tos, \" \"); print tos[1] }'\n"
+"to@example.com,\n"
+"$ printf \"$H\" | awk 'match($0, /^To: (.*)$/, m) { split(m[1], tos, \" \"); print tos[2] }'\n"
+"to2@example.com\n"
+"$ printf \"$H\" | awk 'match($0, /^To: (.*)$/, m) { split(m[1], tos, \" \"); print tos[3] }'\n"
+"\n"
+msgstr ""
+
+msgid ""
+"(This isn't the verbatim interactive session, but a cleaned version to make "
+"it more readable.)"
+msgstr ""
+
+msgid ""
+"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:"
+msgstr ""
+
+msgid ""
+"match($0, /^(To|Cc|Bcc): (.*)$/, m) {\n"
+" split(m[2], tos, \",\")\n"
+" for (i in tos) {\n"
+" print \"--mail-rcpt \" tos[i]\n"
+" }\n"
+"}\n"
+msgstr ""
+
+msgid ""
+"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."
+msgstr ""
+
+msgid "Coding to the standards is underrated."
+msgstr ""
+
+msgid ""
+"#!/bin/sh -eu\n"
+"\n"
+"F=\"$1\"\n"
+"\n"
+"rcpt=\"$(awk '\n"
+" match($0, /^(To|Cc|Bcc): (.*)$/, m) {\n"
+" split(m[2], tos, \",\")\n"
+" for (i in tos) {\n"
+" print \"--mail-rcpt \" tos[i]\n"
+" }\n"
+" }\n"
+"' \"$F\")\"\n"
+"\n"
+"if grep -qE '^From: .*<addr@server1\\.org>$' \"$F\"; then\n"
+" curl \\\n"
+" -s \\\n"
+" --url smtp://smtp.server1.org:587 \\\n"
+" --ssl-reqd \\\n"
+" --mail-from addr@server1.org \\\n"
+" $rcpt \\\n"
+" --user 'addr@server1.org:my-long-and-secure-passphrase' \\\n"
+" --upload-file \"$F\"\n"
+"elif grep -qE '^From: .*<addr@server2\\.org>$' \"$F\"; then\n"
+" curl \\\n"
+" -s \\\n"
+" --url smtp://smtp.server2.org:587 \\\n"
+" --ssl-reqd \\\n"
+" --mail-from addr@server2.org \\\n"
+" $rcpt \\\n"
+" --user 'addr@server2.org:my-long-and-secure-passphrase' \\\n"
+" --upload-file \"$F\"\n"
+"else\n"
+" echo 'Bad \"From: \" address'\n"
+" exit 1\n"
+"fi\n"
+msgstr ""
+
+msgid ""
+"As I experimented with [Neomutt](https://neomutt.org/), 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."
+msgstr ""
+
+msgid ""
+"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."
+msgstr ""
+
+msgid "I even did it incrementally:"
+msgstr ""
+
+#~ msgid "I even did this incrementally:"
+#~ msgstr ""
+
+#~ msgid ""
+#~ "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 felt similar enough that I could almost guess "
+#~ "their behaviour. `match(...)` stores the matches of a regex on the given "
+#~ "array positionally, and `split(...)` stores the chunks in the given array."
+#~ msgstr ""
+
+#~ msgid ""
+#~ "As I experimented with [Neomutt](https://neomutt.org/), I wanted to keep "
+#~ "being able to enqueue emails for sending later, so that I didn't rely on "
+#~ "having an internet connection."
+#~ msgstr ""
+
+#~ msgid ""
+#~ "#!/bin/sh -eu\n"
+#~ "\n"
+#~ "F=\"$1\"\n"
+#~ "\n"
+#~ "rcpt=\"$(awk '\n"
+#~ " match($0, /^(To|Cc|Bcc): (.*)$/, m) {\n"
+#~ " split(m[2], tos, \",\")\n"
+#~ " for (i in tos) {\n"
+#~ " print \"--mail-rcpt \" tos[i]\n"
+#~ " }\n"
+#~ " }\n"
+#~ "' \"$F\")\"\n"
+#~ "\n"
+#~ "if grep -qE '^From: .*<addr@server1\\.org>$' \"$F\"; then\n"
+#~ " curl \\\n"
+#~ " -s \\\n"
+#~ " --url smtp://smtp.server1.org:587 \\\n"
+#~ " --ssl-reqd \\\n"
+#~ " --mail-from addr@server1.org \\\n"
+#~ " $rcpt \\\n"
+#~ " --user 'addr@server1.org:my-long-and-secure-passphrase' \\\n"
+#~ " --upload-file \"$F\"\n"
+#~ "eliif grep -qE '^From: .*<addr@server2\\.org>$' \"$F\"; then\n"
+#~ " curl \\\n"
+#~ " -s \\\n"
+#~ " --url smtp://smtp.server2.org:587 \\\n"
+#~ " --ssl-reqd \\\n"
+#~ " --mail-from addr@server2.org \\\n"
+#~ " $rcpt \\\n"
+#~ " --user 'addr@server2.org:my-long-and-secure-passphrase' \\\n"
+#~ " --upload-file \"$F\"\n"
+#~ "else\n"
+#~ " echo 'Bad \"From: \" address'\n"
+#~ " exit 1\n"
+#~ "fi\n"
+#~ msgstr ""
diff --git a/locale/fr/LC_MESSAGES/_tils/2021-01-12-awk-snippet-send-email-to-multiple-recipients-with-curl.po b/locale/fr/LC_MESSAGES/_tils/2021-01-12-awk-snippet-send-email-to-multiple-recipients-with-curl.po
new file mode 100644
index 0000000..7561292
--- /dev/null
+++ b/locale/fr/LC_MESSAGES/_tils/2021-01-12-awk-snippet-send-email-to-multiple-recipients-with-curl.po
@@ -0,0 +1,243 @@
+#
+msgid ""
+msgstr ""
+
+msgid "title: 'Awk snippet: send email to multiple recipients with cURL'"
+msgstr ""
+
+msgid "date: 2021-01-12"
+msgstr ""
+
+msgid "layout: post"
+msgstr ""
+
+msgid "lang: en"
+msgstr ""
+
+msgid "ref: awk-snippet-send-email-to-multiple-recipients-with-curl"
+msgstr ""
+
+msgid "My requirements for the `sendmail` command were:"
+msgstr ""
+
+msgid "store the email in a file, and send it later."
+msgstr ""
+
+msgid "send from different addresses, using different SMTP servers;"
+msgstr ""
+
+msgid ""
+"I couldn't find an MTA that could accomplish that, but I was able to quickly"
+" write a solution."
+msgstr ""
+
+msgid "The first part was the easiest: store the email in a file:"
+msgstr ""
+
+msgid ""
+"# ~/.config/mutt/muttrc:\n"
+"set sendmail=~/bin/enqueue-email.sh\n"
+"\n"
+"# ~/bin/enqueue-email.sh:\n"
+"#!/bin/sh -eu\n"
+"\n"
+"cat - > \"$HOME/mbsync/my-queued-emails/$(date -Is)\"\n"
+msgstr ""
+
+msgid ""
+"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:"
+msgstr ""
+
+msgid ""
+"for f in ~/mbsync/my-queued-emails/*; do\n"
+" ~/bin/dispatch-email.sh \"$f\" && rm \"$f\"\n"
+"done\n"
+msgstr ""
+
+msgid ""
+"The `dispatch-email.sh` would have to look at the `From: ` header and decide"
+" which SMTP server to use. As I [found "
+"out](https://blog.edmdesigner.com/send-email-from-linux-command-line/) that "
+"[curl](https://curl.se/) supports SMTP and is able to send emails, this is "
+"what I ended up with:"
+msgstr ""
+
+msgid "Most of curl flags used are self-explanatory, except for `$rcpt`."
+msgstr ""
+
+msgid ""
+"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."
+msgstr ""
+
+msgid ""
+"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."
+msgstr ""
+
+msgid ""
+"$ H='To: to@example.com, to2@example.com\\nCc: cc@example.com, cc2@example.com\\nBcc: bcc@example.com,bcc2@example.com\\n'\n"
+"$ printf \"$H\" | awk '/^To: .*$/ { print $0 }'\n"
+"To: to@example.com, to2@example.com\n"
+"$ printf \"$H\" | awk 'match($0, /^To: (.*)$/, m) { print m }'\n"
+"awk: ligne de commande:1: (FILENAME=- FNR=1) fatal : tentative d'utilisation du tableau « m » dans un contexte scalaire\n"
+"$ printf \"$H\" | awk 'match($0, /^To: (.*)$/, m) { print m[0] }'\n"
+"To: to@example.com, to2@example.com\n"
+"$ printf \"$H\" | awk 'match($0, /^To: (.*)$/, m) { print m[1] }'\n"
+"to@example.com, to2@example.com\n"
+"$ printf \"$H\" | awk 'match($0, /^To: (.*)$/, m) { split(m[1], tos, \" \"); print tos }'\n"
+"awk: ligne de commande:1: (FILENAME=- FNR=1) fatal : tentative d'utilisation du tableau « tos » dans un contexte scalaire\n"
+"$ printf \"$H\" | awk 'match($0, /^To: (.*)$/, m) { split(m[1], tos, \" \"); print tos[0] }'\n"
+"\n"
+"$ printf \"$H\" | awk 'match($0, /^To: (.*)$/, m) { split(m[1], tos, \" \"); print tos[1] }'\n"
+"to@example.com,\n"
+"$ printf \"$H\" | awk 'match($0, /^To: (.*)$/, m) { split(m[1], tos, \" \"); print tos[2] }'\n"
+"to2@example.com\n"
+"$ printf \"$H\" | awk 'match($0, /^To: (.*)$/, m) { split(m[1], tos, \" \"); print tos[3] }'\n"
+"\n"
+msgstr ""
+
+msgid ""
+"(This isn't the verbatim interactive session, but a cleaned version to make "
+"it more readable.)"
+msgstr ""
+
+msgid ""
+"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:"
+msgstr ""
+
+msgid ""
+"match($0, /^(To|Cc|Bcc): (.*)$/, m) {\n"
+" split(m[2], tos, \",\")\n"
+" for (i in tos) {\n"
+" print \"--mail-rcpt \" tos[i]\n"
+" }\n"
+"}\n"
+msgstr ""
+
+msgid ""
+"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."
+msgstr ""
+
+msgid "Coding to the standards is underrated."
+msgstr ""
+
+msgid ""
+"#!/bin/sh -eu\n"
+"\n"
+"F=\"$1\"\n"
+"\n"
+"rcpt=\"$(awk '\n"
+" match($0, /^(To|Cc|Bcc): (.*)$/, m) {\n"
+" split(m[2], tos, \",\")\n"
+" for (i in tos) {\n"
+" print \"--mail-rcpt \" tos[i]\n"
+" }\n"
+" }\n"
+"' \"$F\")\"\n"
+"\n"
+"if grep -qE '^From: .*<addr@server1\\.org>$' \"$F\"; then\n"
+" curl \\\n"
+" -s \\\n"
+" --url smtp://smtp.server1.org:587 \\\n"
+" --ssl-reqd \\\n"
+" --mail-from addr@server1.org \\\n"
+" $rcpt \\\n"
+" --user 'addr@server1.org:my-long-and-secure-passphrase' \\\n"
+" --upload-file \"$F\"\n"
+"elif grep -qE '^From: .*<addr@server2\\.org>$' \"$F\"; then\n"
+" curl \\\n"
+" -s \\\n"
+" --url smtp://smtp.server2.org:587 \\\n"
+" --ssl-reqd \\\n"
+" --mail-from addr@server2.org \\\n"
+" $rcpt \\\n"
+" --user 'addr@server2.org:my-long-and-secure-passphrase' \\\n"
+" --upload-file \"$F\"\n"
+"else\n"
+" echo 'Bad \"From: \" address'\n"
+" exit 1\n"
+"fi\n"
+msgstr ""
+
+msgid ""
+"As I experimented with [Neomutt](https://neomutt.org/), 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."
+msgstr ""
+
+msgid ""
+"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."
+msgstr ""
+
+msgid "I even did it incrementally:"
+msgstr ""
+
+#~ msgid "I even did this incrementally:"
+#~ msgstr ""
+
+#~ msgid ""
+#~ "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 felt similar enough that I could almost guess "
+#~ "their behaviour. `match(...)` stores the matches of a regex on the given "
+#~ "array positionally, and `split(...)` stores the chunks in the given array."
+#~ msgstr ""
+
+#~ msgid ""
+#~ "As I experimented with [Neomutt](https://neomutt.org/), I wanted to keep "
+#~ "being able to enqueue emails for sending later, so that I didn't rely on "
+#~ "having an internet connection."
+#~ msgstr ""
+
+#~ msgid ""
+#~ "#!/bin/sh -eu\n"
+#~ "\n"
+#~ "F=\"$1\"\n"
+#~ "\n"
+#~ "rcpt=\"$(awk '\n"
+#~ " match($0, /^(To|Cc|Bcc): (.*)$/, m) {\n"
+#~ " split(m[2], tos, \",\")\n"
+#~ " for (i in tos) {\n"
+#~ " print \"--mail-rcpt \" tos[i]\n"
+#~ " }\n"
+#~ " }\n"
+#~ "' \"$F\")\"\n"
+#~ "\n"
+#~ "if grep -qE '^From: .*<addr@server1\\.org>$' \"$F\"; then\n"
+#~ " curl \\\n"
+#~ " -s \\\n"
+#~ " --url smtp://smtp.server1.org:587 \\\n"
+#~ " --ssl-reqd \\\n"
+#~ " --mail-from addr@server1.org \\\n"
+#~ " $rcpt \\\n"
+#~ " --user 'addr@server1.org:my-long-and-secure-passphrase' \\\n"
+#~ " --upload-file \"$F\"\n"
+#~ "eliif grep -qE '^From: .*<addr@server2\\.org>$' \"$F\"; then\n"
+#~ " curl \\\n"
+#~ " -s \\\n"
+#~ " --url smtp://smtp.server2.org:587 \\\n"
+#~ " --ssl-reqd \\\n"
+#~ " --mail-from addr@server2.org \\\n"
+#~ " $rcpt \\\n"
+#~ " --user 'addr@server2.org:my-long-and-secure-passphrase' \\\n"
+#~ " --upload-file \"$F\"\n"
+#~ "else\n"
+#~ " echo 'Bad \"From: \" address'\n"
+#~ " exit 1\n"
+#~ "fi\n"
+#~ msgstr ""
diff --git a/locale/pt/LC_MESSAGES/_tils/2021-01-12-awk-snippet-send-email-to-multiple-recipients-with-curl.po b/locale/pt/LC_MESSAGES/_tils/2021-01-12-awk-snippet-send-email-to-multiple-recipients-with-curl.po
new file mode 100644
index 0000000..7561292
--- /dev/null
+++ b/locale/pt/LC_MESSAGES/_tils/2021-01-12-awk-snippet-send-email-to-multiple-recipients-with-curl.po
@@ -0,0 +1,243 @@
+#
+msgid ""
+msgstr ""
+
+msgid "title: 'Awk snippet: send email to multiple recipients with cURL'"
+msgstr ""
+
+msgid "date: 2021-01-12"
+msgstr ""
+
+msgid "layout: post"
+msgstr ""
+
+msgid "lang: en"
+msgstr ""
+
+msgid "ref: awk-snippet-send-email-to-multiple-recipients-with-curl"
+msgstr ""
+
+msgid "My requirements for the `sendmail` command were:"
+msgstr ""
+
+msgid "store the email in a file, and send it later."
+msgstr ""
+
+msgid "send from different addresses, using different SMTP servers;"
+msgstr ""
+
+msgid ""
+"I couldn't find an MTA that could accomplish that, but I was able to quickly"
+" write a solution."
+msgstr ""
+
+msgid "The first part was the easiest: store the email in a file:"
+msgstr ""
+
+msgid ""
+"# ~/.config/mutt/muttrc:\n"
+"set sendmail=~/bin/enqueue-email.sh\n"
+"\n"
+"# ~/bin/enqueue-email.sh:\n"
+"#!/bin/sh -eu\n"
+"\n"
+"cat - > \"$HOME/mbsync/my-queued-emails/$(date -Is)\"\n"
+msgstr ""
+
+msgid ""
+"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:"
+msgstr ""
+
+msgid ""
+"for f in ~/mbsync/my-queued-emails/*; do\n"
+" ~/bin/dispatch-email.sh \"$f\" && rm \"$f\"\n"
+"done\n"
+msgstr ""
+
+msgid ""
+"The `dispatch-email.sh` would have to look at the `From: ` header and decide"
+" which SMTP server to use. As I [found "
+"out](https://blog.edmdesigner.com/send-email-from-linux-command-line/) that "
+"[curl](https://curl.se/) supports SMTP and is able to send emails, this is "
+"what I ended up with:"
+msgstr ""
+
+msgid "Most of curl flags used are self-explanatory, except for `$rcpt`."
+msgstr ""
+
+msgid ""
+"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."
+msgstr ""
+
+msgid ""
+"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."
+msgstr ""
+
+msgid ""
+"$ H='To: to@example.com, to2@example.com\\nCc: cc@example.com, cc2@example.com\\nBcc: bcc@example.com,bcc2@example.com\\n'\n"
+"$ printf \"$H\" | awk '/^To: .*$/ { print $0 }'\n"
+"To: to@example.com, to2@example.com\n"
+"$ printf \"$H\" | awk 'match($0, /^To: (.*)$/, m) { print m }'\n"
+"awk: ligne de commande:1: (FILENAME=- FNR=1) fatal : tentative d'utilisation du tableau « m » dans un contexte scalaire\n"
+"$ printf \"$H\" | awk 'match($0, /^To: (.*)$/, m) { print m[0] }'\n"
+"To: to@example.com, to2@example.com\n"
+"$ printf \"$H\" | awk 'match($0, /^To: (.*)$/, m) { print m[1] }'\n"
+"to@example.com, to2@example.com\n"
+"$ printf \"$H\" | awk 'match($0, /^To: (.*)$/, m) { split(m[1], tos, \" \"); print tos }'\n"
+"awk: ligne de commande:1: (FILENAME=- FNR=1) fatal : tentative d'utilisation du tableau « tos » dans un contexte scalaire\n"
+"$ printf \"$H\" | awk 'match($0, /^To: (.*)$/, m) { split(m[1], tos, \" \"); print tos[0] }'\n"
+"\n"
+"$ printf \"$H\" | awk 'match($0, /^To: (.*)$/, m) { split(m[1], tos, \" \"); print tos[1] }'\n"
+"to@example.com,\n"
+"$ printf \"$H\" | awk 'match($0, /^To: (.*)$/, m) { split(m[1], tos, \" \"); print tos[2] }'\n"
+"to2@example.com\n"
+"$ printf \"$H\" | awk 'match($0, /^To: (.*)$/, m) { split(m[1], tos, \" \"); print tos[3] }'\n"
+"\n"
+msgstr ""
+
+msgid ""
+"(This isn't the verbatim interactive session, but a cleaned version to make "
+"it more readable.)"
+msgstr ""
+
+msgid ""
+"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:"
+msgstr ""
+
+msgid ""
+"match($0, /^(To|Cc|Bcc): (.*)$/, m) {\n"
+" split(m[2], tos, \",\")\n"
+" for (i in tos) {\n"
+" print \"--mail-rcpt \" tos[i]\n"
+" }\n"
+"}\n"
+msgstr ""
+
+msgid ""
+"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."
+msgstr ""
+
+msgid "Coding to the standards is underrated."
+msgstr ""
+
+msgid ""
+"#!/bin/sh -eu\n"
+"\n"
+"F=\"$1\"\n"
+"\n"
+"rcpt=\"$(awk '\n"
+" match($0, /^(To|Cc|Bcc): (.*)$/, m) {\n"
+" split(m[2], tos, \",\")\n"
+" for (i in tos) {\n"
+" print \"--mail-rcpt \" tos[i]\n"
+" }\n"
+" }\n"
+"' \"$F\")\"\n"
+"\n"
+"if grep -qE '^From: .*<addr@server1\\.org>$' \"$F\"; then\n"
+" curl \\\n"
+" -s \\\n"
+" --url smtp://smtp.server1.org:587 \\\n"
+" --ssl-reqd \\\n"
+" --mail-from addr@server1.org \\\n"
+" $rcpt \\\n"
+" --user 'addr@server1.org:my-long-and-secure-passphrase' \\\n"
+" --upload-file \"$F\"\n"
+"elif grep -qE '^From: .*<addr@server2\\.org>$' \"$F\"; then\n"
+" curl \\\n"
+" -s \\\n"
+" --url smtp://smtp.server2.org:587 \\\n"
+" --ssl-reqd \\\n"
+" --mail-from addr@server2.org \\\n"
+" $rcpt \\\n"
+" --user 'addr@server2.org:my-long-and-secure-passphrase' \\\n"
+" --upload-file \"$F\"\n"
+"else\n"
+" echo 'Bad \"From: \" address'\n"
+" exit 1\n"
+"fi\n"
+msgstr ""
+
+msgid ""
+"As I experimented with [Neomutt](https://neomutt.org/), 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."
+msgstr ""
+
+msgid ""
+"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."
+msgstr ""
+
+msgid "I even did it incrementally:"
+msgstr ""
+
+#~ msgid "I even did this incrementally:"
+#~ msgstr ""
+
+#~ msgid ""
+#~ "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 felt similar enough that I could almost guess "
+#~ "their behaviour. `match(...)` stores the matches of a regex on the given "
+#~ "array positionally, and `split(...)` stores the chunks in the given array."
+#~ msgstr ""
+
+#~ msgid ""
+#~ "As I experimented with [Neomutt](https://neomutt.org/), I wanted to keep "
+#~ "being able to enqueue emails for sending later, so that I didn't rely on "
+#~ "having an internet connection."
+#~ msgstr ""
+
+#~ msgid ""
+#~ "#!/bin/sh -eu\n"
+#~ "\n"
+#~ "F=\"$1\"\n"
+#~ "\n"
+#~ "rcpt=\"$(awk '\n"
+#~ " match($0, /^(To|Cc|Bcc): (.*)$/, m) {\n"
+#~ " split(m[2], tos, \",\")\n"
+#~ " for (i in tos) {\n"
+#~ " print \"--mail-rcpt \" tos[i]\n"
+#~ " }\n"
+#~ " }\n"
+#~ "' \"$F\")\"\n"
+#~ "\n"
+#~ "if grep -qE '^From: .*<addr@server1\\.org>$' \"$F\"; then\n"
+#~ " curl \\\n"
+#~ " -s \\\n"
+#~ " --url smtp://smtp.server1.org:587 \\\n"
+#~ " --ssl-reqd \\\n"
+#~ " --mail-from addr@server1.org \\\n"
+#~ " $rcpt \\\n"
+#~ " --user 'addr@server1.org:my-long-and-secure-passphrase' \\\n"
+#~ " --upload-file \"$F\"\n"
+#~ "eliif grep -qE '^From: .*<addr@server2\\.org>$' \"$F\"; then\n"
+#~ " curl \\\n"
+#~ " -s \\\n"
+#~ " --url smtp://smtp.server2.org:587 \\\n"
+#~ " --ssl-reqd \\\n"
+#~ " --mail-from addr@server2.org \\\n"
+#~ " $rcpt \\\n"
+#~ " --user 'addr@server2.org:my-long-and-secure-passphrase' \\\n"
+#~ " --upload-file \"$F\"\n"
+#~ "else\n"
+#~ " echo 'Bad \"From: \" address'\n"
+#~ " exit 1\n"
+#~ "fi\n"
+#~ msgstr ""
diff --git a/scripts/spelling/international.txt b/scripts/spelling/international.txt
index 7c2d678..9b14732 100644
--- a/scripts/spelling/international.txt
+++ b/scripts/spelling/international.txt
@@ -81,6 +81,7 @@ LaTeX
Lerna
LilyPond
LiquidHaskell
+MTA
Mailutils
Marcha
Marinheiros
@@ -89,6 +90,7 @@ McGranaghan
Mentat
Merkle
NPM
+Neomutt
Nextcloud
NixOS
Nixpkgs
@@ -113,7 +115,9 @@ Raku
Reddit
Redux
SA
+SMTP
SSD
+SSMTP
SVG
Saudade
Screencast
@@ -150,12 +154,14 @@ boneco
br
brainer
buildGoModule
+cURL
cargo2nix
carte
cbindgen
cgit
ci
clojure
+cronjob
da
datalog
datom
@@ -218,6 +224,7 @@ org
pastebin
pastebins
plaintext
+positionally
pouchdb
progn
pt
@@ -226,6 +233,7 @@ rollouts
sbcl
screencast
screencasts
+sed
songbooks
sourcehut
sr