Blog

Tabellarisch

Angesichts meiner Schwäche für die tabellarische Darstellung von Informationen ist Dr. Drangs neueste Entdeckung wie für mich gemacht: Ein Unix-Tool, das eine lange Liste in ein konfigurierbares Raster von Spalten und Zeilen umwandelt.

# Zeilenweise cat genesis.txt | rs -g5 9 4 Im Anfang schuf Gott Himmel und Erde die Erde aber war wüst und wirr Finsternis lag über der Urflut und Gottes Geist schwebte über dem Wasser Gott sprach Es werde Licht Und es wurde Licht # Spaltenweise (-t) cat genesis.txt | rs -g5 -t 9 4 Im aber Urflut sprach Anfang war und Es schuf wüst Gottes werde Gott und Geist Licht Himmel wirr schwebte Und und Finsternis über es Erde lag dem wurde die über Wasser Licht Erde der Gott

Neben rs gibt es auch column, das Informationen spaltenweise in einer wählbaren Zeichenbreite anordnet. Leider vertraut column nicht auf die Macht des monospaced font, verwendet Tabulatoren als Spaltentrenner und muss daher mit expand kombiniert werden:

# Spaltenweise cat genesis.txt | column -c 65 | expand Im aber Urflut sprach Anfang war und Es schuf wüst Gottes werde Gott und Geist Licht Himmel wirr schwebte Und und Finsternis über es Erde lag dem wurde die über Wasser Licht Erde der Gott # Zeilenweise (-x) cat genesis.txt | column -x -c 65 | expand Im Anfang schuf Gott Himmel und Erde die Erde aber war wüst und wirr Finsternis lag über der Urflut und Gottes Geist schwebte über dem Wasser Gott sprach Es werde Licht Und es wurde Licht

Wer vim und einen monospaced font nutzt, kann Tabellen auch mit ASCII-Kunst gestalten. Das Paket VIM Table Mode ist tatsächlich ein awesome automatic table creator & formatter. Vorhandene CSV-Daten können mit dem Befehl \tt umgewandelt werden, und im Tabellenmodus (Aktivierung/Deaktivierung mit \tm) entstehen Tabellen wie durch Zauberhand:

|---------------------------+------------------+---------| | Titel | Autorin | Jahr | |---------------------------+------------------+---------| | Der Meister und Margarita | Michail Bulgakow | 1940 | | Die Elixiere des Teufels | E.T.A. Hoffmann | 1815/16 | | Die Göttliche Komödie | Dante Alighieri | 1321 | |---------------------------+------------------+---------|

Markdownhund

Weniger mein schlechtes Gewissen als vielmehr der Aufwand für die Gestaltung ansehnlicher CSS-Vorgaben für markdown2html veranlassen mich nach einigen Wochen zur Umkehr. Da der Hauptvorteil der ansonsten unschönen HTML-Nachrichten die übersichtliche Integration von URLs in den Nachrichtentext ist, suche ich – wie viele andere – nach einer Möglichkeit, reference links in vim zu erzeugen. Überraschenderweise stützt sich die Lösung ebenfalls auf Pandoc:

# .vimrc vnoremap <f6> :!pandoc --from markdown --to markdown --reference-links<CR>

Hagrid vs. Hockeypuck

Dank WKD muss ich PGP-Schlüssel im Bereich meiner Domains nicht in die Obhut von schwatzhaften Keyservern geben, aber über einige meiner Adressen verfüge ich nur eingeschränkt. Der föderierte Hockeypuck-Server veröffentlicht gesendete Schlüssel (gpg --send-key --keyserver keyserver.ubuntu.com D9A154D886C404A0E7AA15681218CF14F56FCD4A) kommentarlos, während Patrick Brunschwigs Hagrid-Server ein doppeltes Zustimmungsverfahren praktiziert, bevor ein Schlüssel auffindbar wird:

This is an automated message from keys.openpgp.org. If you didn't upload your key, please ignore this message. OpenPGP key: D9A154D886C404A0E7AA15681218CF14F56FCD4A This key was just uploaded for the first time, and is now published without identity information. If you want to allow others to find this key by e-mail address, please follow this link: [...] # Two minutes later: This is an automated message from keys.openpgp.org. If you didn't request this message, please ignore it. OpenPGP key: D9A154D886C404A0E7AA15681218CF14F56FCD4A To let others find this key from your email address "janeden@domain.com", please follow the link below: [...]

Zenburn

Das Standard-Farbschema des macOS-Terminals und die grob gestrickte mutt-Farbgebung (color index red default "~N|~O") beanspruchen meine alternden Augen über Gebühr, so dass ich auf das beliebte Zenburn-Farbschema wechsele. Anders als in einer handelsüblichen Ehe muss ich Zenburn im Sinne einer konsistenten user experience mehrfach das Ja-Wort geben: Für das Terminal, für vim und für mutt. Als eigensinniger Mensch ändere ich eine Kleinigkeit in ~/.mutt/zenburn.cf (color index color110 color237 ~P), um meine eigenen E-Mails im Posteingang weiterhin identifizieren zu können.

Reputationspflege 8: PTR revisited

Der unterhaltsame Thread mit dem ursprünglichen Schwerpunkt auf Zeilenumbrüchen entwickelt sich stetig weiter, und ist mittlerweile bei einer Diskussion um die Vor- und Nachteile eigener Mailserver angekommen. Radikale Listenmitglieder verbinden mit dem self hosting die Möglichkeit, allen Kommunikationspartnerinnen E-Mail-Accounts zur Verfügung zu stellen, andere beklagen die Mithaftung durch die Blockade ganzer Subnetze durch Microsoft, Google et al und wittern Verschwörungen.

Ich nutze die Gelegenheit, um meinen Mailserver mit allen verlinkten Werkzeugen zu überprüfen, werde mit der Fehlermeldung Reverse DNS is not a valid Hostname der MXToolBox konfrontiert und muss mich von der Illusion einer perfekten PTR-Konfiguration verabschieden. Im Affekt ändere ich aber nicht etwa den PTR-Eintrag für meine IP-Adresse, sondern den MX-Eintrag für meine Domain (eden.one statt mail.eden.one) in Verbindung mit Anpassungen der Dovecot- und Postfix-Konfiguration (SSL-Zertifikate und Hostnames), obwohl sich die inkriminierte PTR-Situation dadurch ganz offensichtlich nicht verbessert. Außerdem gelingt es mir, versehentlich eine Todsünde zu begehen (NEVER list a virtual MAILBOX domain name as a mydestination domain!) und zeitweilig die Zustellung von E-Mails an meine Dovecot-Nutzerinnen zu unterbinden (<user@eden.one> (expanded from <address@eden.one>): unknown user: "user"):

# DO NOT DO THIS in /etc/postfix/main.cf myhostname = eden.one mydestination = $myhostname, localhost.localdomain, localhost virtual_mailbox_domains = eden.one

Auch nach der Korrektur dieses Fehlers setzt sich langsam die Erkenntnis durch, dass eine Domain als Hostname keine sehr gute Idee (und eben kein valid hostname) ist. Zugleich wird mir klar, dass ein PTR-Eintrag im Wesentlichen für Mailserver relevant ist und es keinen Grund gibt, den PTR-Eintrag nicht entsprechend zu gestalten:

id 44025, opcode QUERY, rcode NOERROR, flags QR RD RA ;QUESTION 138.240.160.217.in-addr.arpa. IN PTR ;ANSWER 138.240.160.217.in-addr.arpa. 21600 IN PTR mail.eden.one. ;AUTHORITY ;ADDITIONAL

Alle Änderungen an main.cf, 10-ssl.conf und 15-lda.conf werden daher zurückgenommen und auch der MX-Eintrag verweist wieder auf den FQDN mail.eden.one. Mit dieser Konfiguration ist die MXToolbox zufrieden:

Status Ok SMTP Reverse DNS Mismatch OK - 217.160.240.138 resolves to mail.eden.one
Status Ok SMTP Valid Hostname OK - Reverse DNS is a valid Hostname
Status Ok SMTP Banner Check OK - Reverse DNS matches SMTP Banner
Status Ok SMTP TLS OK - Supports TLS.
Status Ok SMTP Connection Time 0.363 seconds - Good on Connection time
Status Ok SMTP Open Relay OK - Not an open relay.
Status Ok SMTP Transaction Time 1.100 seconds - Good on Transaction Time

Lediglich einige Testwerkzeuge für Newsletter haben noch Einwände. Mail-Tester vergibt zwar die Wertung 10/10, weist aber auf einen fehlenden List-unsubscribe-Header hin sowie auf die unzureichende Gestaltung meiner Testnachricht:

Your message could be improved: There is no html version of your message.

Unspam.email hat denselben Humor, mäkelt aber darüber hinaus an meiner TLD herum –

Test failed. Your email is missing the List-Unsubscribe header.
Test failed. Your domain uses are [sic!] not trustworthy suffix!
Test failed. Your message body is not using HTML best practices! The HTML body is not composed of standard and supported HTML elements.

– und zieht dafür allen Ernstes 11 Punkte ab (89/100). Mailgenius ist ebenfalls weder mit .one noch mit dem fehlenden Listen-Header einverstanden, hat aber eine sympathische Einstellung zum fehlenden HTML-Body (97/100):

Warning -2 – Domain Suffix – Although your domain is not using a common spammer suffix, it is not using one of the most trustworthy suffixes.
Warning -1 – List-Unsubscribe Header – Your email is missing the List-Unsubscribe header.
Passing – HTML Body Best Practices – Your message body is using HTML best practices!

Mit so unqualifizierten Einwänden können mein Mailserver und ich leben.

Aussagekräftig

Die Weiterentwicklung von rbackup.py wird nicht langweilig, und nach einigen Monaten erscheinen mir meine PGP-signierten Backup-Benachrichtigungen zu wenig aussagekräftig. Den Output von rsync aufzugreifen, ist relativ einfach (stdout=subprocess.PIPE), aber um ihn parallel (wie bisher) im Terminal auszugeben, muss der aufgefangene Output manuell in das Terminal-Fenster gedruckt werden. Dazu wird der Parameter universal_newlines der subprocess.run-Methode verwendet, so dass ein String- statt eines Bytes-Objektes ausgegeben wird. Dieses String-Objekt wiederum lässt sich zeilenweise iterieren:

rsync_process = subprocess.run(command_list, stdout=subprocess.PIPE, universal_newlines=True) for stdout_line in rsync_process.stdout: print(stdout_line, end='')

Das ist nicht weiter kompliziert, aber es funktioniert nicht – der rsync-Output erscheint erst nach dem Abschluss des Subprozesses. Weil eine funktionierende Lösung unangemessen aufwendig ist, lasse ich der Nutzerin die Wahl zwischen einer aussagekräftigen Benachrichtigung und einer Ausgabe im Terminal (mit der Option -q):

rsync_output = '' if self.quiet: rsync_process = subprocess.run(command_list) else: print('Backing up, please be patient...') rsync_process = subprocess.run(command_list, stdout=subprocess.PIPE) rsync_output = rsync_process.stdout.decode()

Auch auf einen animierten Wartestandsanzeiger verzichte ich aus Kostengründen.

rsync_output wird in jedem Fall an logging() übergeben und dort ausgewertet. Als Belege für einen Datentransfer werden auf Stackoverflow die Zeichen > und < genannt (was den rsync-Parameter --itemize-changes für das entsprechende Logging erfordert), aber für meine Zwecke genügt ein einfacherer Test. Wenn zwischen dem initialen (sending|receiving) incremental file list und dem abschließenden sent lediglich zwei Zeilenumbrüche stehen, wird der Output nicht beigefügt:

if rsync_return_code == 0 or rsync_return_code == 24: unchanged = re.search('(sending|receiving) incremental file list\n\nsent', rsync_output) if unchanged: status = 'No files were transferred.' else: status = 'File transfer completed successfully (details below).' else: status = 'Failure, please re-run.' elapsed_time = end_time - start_time message = f'{self.summary}\nElapsed time: {elapsed_time}\nStatus: {status}' if not unchanged: message += f'\n\n==========\n{rsync_output}=========='

Bei umfangreicheren Backups erzeugt rbackup.py auf diese Weise längere Benachrichtigungen (> 50KB) und das angenehme Gefühl emsiger Geschäftigkeit.

Windmühlenkampf

Im Nachgang der Zeilenumbruchsdiskussion, die mit einer leicht pathetischen Unabhängigkeitserklärung endete, weist ein Listenmitglied auf die ausgesprochen pessimistische Perspektive eines langjährigen Eigenpostmeisters hin, dessen Mailserver von den dominanten Providern geschnitten wird:

But my emails are just not delivered anymore. I might as well not have an email server. [...]

I implemented all the acronyms [DKIM, DMARC, SPF, reverse DNS lookup, SSL in transport, PTR record], secured antispam measures, verified my domain, made sure my server is neither breached nor used to relay actual spam, added new servers with supposedly clean IPs from reputable providers, tried all the silver bullets recommended by Hacker News, used kafkaesque request forms to prove legitimity, contacted the admins of some blacklists.

Please believe me. My current email server IP has been managed by me and used exclusively for my personal email with zero spam, zero, for the last ten years.

Nothing worked.

Auf den ersten Blick sehr ernüchternd nach all meinen Bemühungen. Dank meiner notorischen Apfelbäumchen-Attitüde registriere ich mich trotzdem für die im Artikel erwähnten Programme Microsoft SNDS und Google Postmaster Tools. Erneute Ernüchterung: Google hat keinerlei Erkenntnisse zu meiner Domain/IP, und aus Sicht von Microsoft ist meine IP zwar nicht blockiert, aber junked due to user complaints or other evidence of spamming (ohne die Möglichkeit, an diesem Status etwas zu ändern). Da aber der überwiegende Teil meiner E-Mails ihre Empfängerinnen erreicht und ein Blacklist-Eintrag bei mindestens einem großen deutschen Provider kein unwiderrufliches Urteil darstellt, bin ich noch nicht bereit für die Dienste der Certified Senders Alliance (einmalig 1250 Euro + monatlich 300 Euro) oder die Verrentung meines eigenen Mailservers.

Ineffizient

Der Umstieg auf eine statische Website erweist sich vor dem Hintergrund einer Studie zur Energieeffizienz von Programmiersprachen als weitsichtig, denn Python landet mit den Faktoren 75,88 (Energie) und 71,90 (Zeit) im Vergleich zu C auf dem vorletzten Platz. Aber auch für die lokale Ausführung mit einem M1-Prozessor ist Python wohl nicht mehr vermittelbar – vielleicht muss ich auf meine alten Tage noch eine neue Sprache (1,03/1,04) lernen.

Elizabeth Alexandra Mary Windsor

Wenn in einem modernen, aufgeklärten und demokratischen Staatswesen eine Monarchin stirbt, können nur ausgewiesene Expertinnen auf der Basis ihrer jahrzehntelangen Erfahrung bei ihrem Sohn und Nachfolger widerstreitende Gefühle diagnostizieren oder daran erinnern, dass das 65. Thronjubiläum der Verblichenen ohne offizielle Feiern auskommen musste, weil es auf den Todestag ihres Vaters und Vorgängers fiel (wie alle britischen Thronjubiläen seit 1953). Angesichts des viel zu frühen Todes des Staatsoberhauptes dürfen sich ihre wahlberechtigten Untertanen jedenfalls mit dem Gedanken trösten, dass selbst die Opfer anderer Kolonialmächte in einer Art indirektem Stockholm-Syndrom eine dreitägige Staatstrauer zu Ehren der rainha para todos nós verhängen. Ein Einwohner der britischen Besatzungszone kleidet seine Betroffenheit sogar spontan in ein avantgardistisches Sprachspiel:

Ich bin natürlich auch mit ihr aufgewachsen, ganz klar. Finde ich schon erschreckend, dass so eine Ikone leider dann nicht mehr unter uns weilt.

Multipersonal

Mein Bemühen, für jeden Kontext eine passende E-Mail-Adresse mit eigenem PGP-Schlüssel vorzuhalten, führt zu einem gewissen Mehraufwand in mutt: Absenderadresse anpassen, BCC-Adresse anpassen und zugehörigen PGP-Schlüssel suchen/bestätigen. Ich kann mir kaum vorstellen, dass für dieses Problem noch keine Lösung gefunden wurde, und ich habe recht:

What I did for this was select a few esc-capital hotkey combos and define macros like this in my muttrc:

macro generic \eF ":source ~/.mutt/headers.f...\r" macro generic \eH ":source ~/.mutt/headers.h...\r"

And so on. (I replaced the actual filenames with "...")

Each .mutt/headers... file looks somewhat like this:

unmy_hdr * my_hdr X-URL: ... my_hdr From: Some One <some at one...> set status_format="-%r- %f: some at one ---[Msgs:%?M?%M/?%m%?n?New:%n?%?d? Del:%d?%?F? Flag:%F?%?t? Tag:%t?%?p? Post:%p?%?b? Inc:%b?%l]---(%s%?S?/%S?)-%>-(%P)---" set signature="..."

So in the index I can hit esc-F, esc-H, etc., and it loads the set of headers I want, and also sets my status line to show me which header set I currently have loaded.

Es geht sogar noch etwas eleganter:

# .muttrc source ~/.mutt/default_address.cf macro generic \e1 ":source ~/.mutt/default_address.cf\r" macro generic \e2 ":source ~/.mutt/alternative_address1.cf\r" macro generic \e3 ":source ~/.mutt/alternative_address2.cf\r" macro generic \e4 ":source ~/.mutt/alternative_address3.cf\r" # default_address.cf set my_address = "xyz at eden.one" set my_pgp_key = '257A9B6F3DEDCA11319000877CD4656792A3A1F4' source '~/.mutt/set_address.cf' # set_address.cf set from=$my_address set pgp_default_key = $my_pgp_key set status_format="-%r $my_address: %f [Msgs:%?M?%M/?%m%?n? New:%n?%?o? Old:%o?%?d? Del:%d?%?F? Flag:%F?%?t? Tag:%t?%?p? Post:%p?%?b? Inc:%b?%?l? %l?]---(%s/%S)-%>-(%P)---" unmy_hdr * my_hdr Bcc: $my_address

Spamlisten 2

Nicht alle Mailinglisten haben eine zuvorkommende Administratorin, die die Listenkonfiguration für einzelne Mitglieder ändert, und zum Glück ist das auch nicht erforderlich, sofern alle Nachrichten von DMARC-gesicherten Domains DKIM-Signaturen enthalten und unverändert weitergeleitet werden. Wenn eine Mailingliste allerdings aus anderen Erwägungen DKIM-Signaturen entfernt, muss sie zu hacky workarounds greifen, um wenigstens ein neutrales DMARC-Ergebnis (none) zu erzielen.

Auf diesen Zusammenhang zwischen DKIM-Filter und From-munging hatte mich zwar bereits der Admin von mutt-users hingewiesen, aber erst nach der geduldigen Erläuterung eines weiteren Listenadmins verstehe ich es auch. Seine Mailingliste dnswl-users lässt Nachrichten (weitgehend) unverändert, so dass die Kombination header.from=eden.one und dkim=pass (2048-bit key) header.d=eden.one header.i=@eden.one header.b=grIPKv+A; das gewünschte DKIM-Ergebnis liefert:

Authentication-Results: posteo.de; dkim=permerror (0-bit key) header.d=dnswl.org header.i=@dnswl.org header.b=qaYjhQGI; dkim=pass (2048-bit key) header.d=dnswl.org header.i=@dnswl.org header.b=t3u1c/SQ; dkim=pass (2048-bit key) header.d=eden.one header.i=@eden.one header.b=grIPKv+A; dkim-atps=neutral

Der SPF-Test gegen die IP-Adresse des Mailinglisten-Servers ist zwar ebenfalls erfolgreich –

Received-SPF: Pass (mailfrom) identity=mailfrom; client-ip=130.255.78.51; helo=mail.dnswl.org; envelope-from=dnswl-users+bounces-150-mailaddress=eden.one@dnswl.org;

– trägt aber mangels identifier alignment mit header.from=eden.one nicht zum DMARC-Ergebnis bei, das trotzdem ordentlich ausfällt:

Authentication-Results: posteo.de; dmarc=pass (p=quarantine dis=none) header.from=eden.one

Wir merken uns: spf=pass oder dkim=pass sind hinreichend für dmarc=pass. Zusätzliche DKIM-Signaturen der Mailingliste wie im obigen Beispiel dienen gemäß Abschnitt 5.8 des RFC 6377 der Reputation der Liste und haben keinen Einfluss auf die DMARC-Prüfung. Statt Listenadmins zu behelligen, hätte ich auch einfach Abschnitt 6.6.2 des RFC 7489 lesen können:

To arrive at a policy for an individual message, Mail Receivers MUST perform the following actions or their semantic equivalents. Steps 2-4 MAY be done in parallel, whereas steps 5 and 6 require input from previous steps.

The steps are as follows:

  1. Extract the RFC5322.From domain from the message (as above).
  2. Query the DNS for a DMARC policy record. Continue if one is found, or terminate DMARC evaluation otherwise. See Section 6.6.3 for details.
  3. Perform DKIM signature verification checks. A single email could contain multiple DKIM signatures. The results of this step are passed to the remainder of the algorithm and MUST include the value of the "d=" tag from each checked DKIM signature.
  4. Perform SPF validation checks. The results of this step are passed to the remainder of the algorithm and MUST include the domain name used to complete the SPF check.
  5. Conduct Identifier Alignment checks. With authentication checks and policy discovery performed, the Mail Receiver checks to see if Authenticated Identifiers fall into alignment as described in Section 3. If one or more of the Authenticated Identifiers align with the RFC5322.From domain, the message is considered to pass the DMARC mechanism check. All other conditions (authentication failures, identifier mismatches) are considered to be DMARC mechanism check failures.
  6. Apply policy. Emails that fail the DMARC mechanism check are disposed of in accordance with the discovered DMARC policy of the Domain Owner. See Section 6.3 for details.

Hypertexthund

Jahrelang – und noch vor wenigen Tagen – habe ich den Gedanken, HTML-Mails zu versenden, weit von mir gewiesen:

Creating HTML mail with mutt feels more like a surrender. :)

Apart from the known drawbacks of HTML mail, the markdown2html script has a couple of requirements to further complicate my (already overly complex) mailstack.

Andererseits ist die Konfiguration –

# .muttrc set send_multipart_alternative=ask-no set send_multipart_alternative_filter='/opt/homebrew/bin/markdown2html'

– nach der Installation des Skriptes und seiner Voraussetzungen

cp /opt/homebrew/Cellar/mutt/2.2.7/share/doc/mutt/samples/markdown2html /opt/homebrew/bin/ chmod 755 /opt/homebrew/bin/markdown2html brew install pandoc pip3 install Pynliner pip3 install Pygments

trotz der erforderlichen Anpassungen im Skript (#!/usr/bin/python3#!/opt/homebrew/bin/python3) derartig einfach, dass ich der Versuchung erliege. Selbstverständlich beschränke ich den HTML-Versand auf berufliche Kontaktpersonen mit entsprechender Neigung und wenige Tags, aber ein Sündenfall bleibt ein Sündenfall.

Weißgelistet

Wenige Tage nach der Blacklisting-Episode überrascht mich Sparkpost mit einer sehr positiven Bewertung:

SpamAssassin v3.4.0 (2014-02-07) Result: ham (-7.0 points, 5.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] -5.0 RCVD_IN_DNSWL_HI RBL: Sender listed at https://www.dnswl.org/, high trust [217.160.240.138 listed in list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.0 T_SCC_BODY_TEXT_LINE No description available.

Seit wann ist meine IP-Adresse bei dnswl.org gelistet, und dann auch noch im Status high trust? dnswl.org selbst weiß von nichts, und auch Posteo als dnswl.org-Kunde hat im X-Spam-Status meiner E-Mails bislang nur auf meinen ruppigen Schreibstil, aber nicht auf dnswl.org Bezug genommen. Erst nachdem ich meine Domain/IP-Adresse tatsächlich registriert habe, erfahre ich bei Posteo eine Aufwertung (RCVD_IN_DNSWL_NONE=-0.0001), die dem initialen dnswl.org-Score (none) entspricht. Vielleicht hat SpamAssassin mehr als 8 Jahre nach seiner Kompilation resigniert?

Aber es gibt noch einen plot twist: Mein IP-Eintrag bei dnswl.org trägt zwar den First Seen-Zeitstempel 2022-09-02, aber den Last Seen-Zeitstempel 2022-06-09. Könnte es sein, dass nur der altgediente SpamAssassin nicht Teil einer groß angelegten Verschwörung gegen meine IP-Adresse ist? Die Wahrheit ist leider etwas profaner

Last seen might be the last legitimate (not-rate-limited) query, or message in some QA surveillance network (pure speculation).

– und die Chance meiner Domain/IP-Kombination auf eine Bewertung oberhalb der Ebene medium trust ist wohl sehr gering. Freundlicherweise prüft Benny Pedersen den Status der IP-Adresse bei sehr vielen Black-/Whitelists. Es stellt sich heraus, dass ich lediglich in Russland (gremlin.ru) und in Polen (polspam.pl) nicht wohlgelitten bin, wobei Polspam im Blacklist-Eintrag freundlicherweise auf die klare Rechtslage hinweist:

Before you send SPAM,read first:District Court Warsaw sig.IC3136/17:justification of the judgment:Even a single SPAM message causes violation of personal rights!

Die Kommunikation mit Bürgerinnen und Einrichtungen der Russischen Föderation habe ich seit einigen Monaten deutlich reduziert, und bei meinen polnischen Gesprächspartnerinnen entschuldige ich mich hiermit prophylaktisch für eine verzögerte Zustellung von E-Mails: Przepraszam za późną odpowiedź!

Dünnbündel

Die Einführung eines neuen Helferleins nehme ich zum Anlass, meine Synchronisations- und Datensicherungsgewohnheiten zu hinterfragen. Für private E-Mails wird nur noch das laufende Jahr synchronisiert, und eine Reihe von voluminösen Mail-Ordnern werden aus der Backup-Liste entfernt. Auch das verschlüsselte Sparsebundle wird verschlankt und anschließend komprimiert:

snafu@local ~ % du -sh Backup.sparsebundle 18G Backup.sparsebundle snafu@local ~ % hdiutil compact Backup.sparsebundle Starting to compact… Reclaiming free space… ....................... Finishing compaction… Reclaimed 2.3 GB out of 28.7 GB possible.

Ein Gewinn von weniger als 10% ist unbefriedigend, und im Internet rät man dazu, ein frisches Sparsebundle mit effizienten 1MB-Bändern anzulegen:

hdiutil create -size 30g -type SPARSEBUNDLE -encryption AES-256 -imagekey sparse-band-size=2048 -fs APFS -volname CoreBackup -attach ~/Backup.sparsebundle

Im leeren Zustand ist das Bündel sehr schlank –

snafu@local ~ % du -sh Backup.sparsebundle 8.2M Backup.sparsebundle

– aber auch nach dem ersten Backup kann ich nicht klagen:

snafu@local ~ % rbackup image [...] snafu@local ~ % du -sh Backup.sparsebundle 5.2G Backup.sparsebundle

Noch viel erfreulicher als die Rückgewinnung von ~ 10G SSD-Kapazität sind die erheblich schnelleren USB-Backups:

Source dir: /Users/snafu/Backup/ Target dir: /Volumes/backup_key1/Backup/2022-09-02 Type: Incremental Elapsed time: 0:37:02.689781 Status: Success

Mailstack 2

Der Tendenz zum technologischen Konservatismus stelle ich mich manchmal mit mühsam rationalisierten Veränderungen entgegen, z.B. einem Wechsel von Offlineimap zu isync/mbsync (verwirrenderweise trägt das Projekt einen anderen Namen als das Programm). Diese Maßnahme ist nicht besonders originell und wird in der Regel mit der höheren Geschwindigkeit von mbsync begründet, was aber nur bedingt stimmt.

Die Konfiguration der beiden Anwendungen ist durchaus vergleichbar, wobei mbsync neben einem generischen Kommando zur Passwort-Abfrage (PassCmd) unter macOS auch den Schlüsselbund unterstützt (UseKeychain yes) und statt des Fingerabdrucks eines SSL-Zertifikates den Pfad zum Zertifikat erwartet (CertificateFile /Users/snafu/.mbsync/mail.cer). Für die Abfrage des Zertifikates von einem Mailserver wird ein openssl-Wrapper (mbsync-get-cert) mitgeliefert, dessen Output natürlich mit dem veröffentlichten Fingerabdruck des Mailproviders abgeglichen werden sollte (openssl x509 -in posteo.cer -noout -fingerprint -sha256). Für meinen eigenen Mailserver vereinfacht sich die automatische Zertifikatsaktualisierung auf eine Kopieroperation:

if not filecmp.cmp(pem_path, mbsync_path): result = f'Replacing {mbsync_path} with updated certificate...' shutil.copyfile(pem_path, mbsync_path) else: result = f'File {mbsync_path} was up to date.' print(result)

Objektiv ändert sich durch den Wechsel nichts, aber die mbsync-Dokumentation stärkt mir den Rücken beim schwierigen Umgang mit gewissen Software-Produkten (This is mostly a debugging option, but may also be used to limit average bandwidth consumption (GMail may require this if you have a very fast connection), or to spare flaky servers like M$ Exchange.).

Viel Lärm um Zeilenumbrüche

Ohne erkennbaren Anlass wurde vor einigen Tagen die schon häufiger geführte Diskussion um die richtige Formatierung von E-Mails in zwei separaten Threads der Mailingliste mutt-users aufgegriffen. Während einer der Threads nach wenigen Beiträgen endete, wuchs der andere sich zu einem schier endlosen Geflecht aus. Man diskutierte die einschlägigen RFCs, kleine Smartphone-Bildschirme sowie die (fehlende) Unterstützung verbreiteter MUAs für RFC2646 (format=flowed) und schlug die Definition eines neuen MIME-Typs vor. Aufwendige Lösungen mit mehreren vim-Fenstern und par-Pipes und sogar der Versand von HTML-Mails mit mutt wurden als Kompromissangebot ins Spiel gebracht. Radikale Ansätze wie der Verzicht auf Zeilenumbrüche wurden geschmäht, und der Aufwand für die Drehung eines Smartphones wurde gegen den Aufwand für eine Smartphone-kompatible Formatierung von E-Mails abgewogen.

Staunend stehe ich vor dem Furor der Diskutantinnen und frage mich, ob format=flowed für Empfängerinnen mit den üblichen MUAs tatsächlich besser aussieht. In mutt führt diese Formatierung nämlich zu einer weniger schönen Darstellung, vor allem in Verbindung mit Listen/Aufzählungen:

# hard wrapped 3. In enim justo, rhoncus ut, imperdiet a, venenatis vitae, justo. Nullam dictum felis eu pede mollis pretium. Integer tincidunt. 4. Cras dapibus. Vivamus elementum semper nisi. Aenean vulputate eleifend tellus. Aenean leo ligula, porttitor eu, consequat vitae, eleifend ac, enim. # format=flowed 3. In enim justo, rhoncus ut, imperdiet a, venenatis vitae, justo.    Nullam dictum felis eu pede mollis pretium. Integer tincidunt. 4. Cras dapibus. Vivamus elementum semper nisi. Aenean vulputate    eleifend tellus. Aenean leo ligula, porttitor eu, consequat vitae,    eleifend ac, enim.

Outlook (Mac) stellt beide Varianten nahezu identisch dar (mit einer Begrenzung der Zeilenbreite auf etwa 72 Zeichen), und auch mit Apple Mail (iOS/iPadOS) ist im Porträtformat kein Unterschied sichtbar. Im Querformat wird die Bildschirmbreite mit format=flowed tatsächlich vollständig genutzt (> 72 Zeichen), was aber zu Lasten der Aufzählungen geht und – wie in mutt – unschöne Lücken durch aufeinander folgende Leerzeichen erzeugt.

Mit anderen Worten: Die Kombination von set text_flowed = yes (in .muttrc) und autocmd FileType mail setlocal formatoptions+=w (in .vimrc) funktioniert zwar as advertised, ist aber nicht zu empfehlen. In den Worten von Derek Martin:

The bottom line is there is absolutely no reason why hard-wrapped lines of plain text at 72 characters should ever need to display unreadably for any desktop user, or even anyone on any reasonable mobile device which can rotate lines parallel to their longer side, that doesn't boil down to the choice of the user. Flouting the standards is a bad habit to be in. They exist for good reason; if you choose to abandon them you do so at your own peril, and the rest of us should not be expected to accommodate you.

Einigen Teilnehmerinnen ist die geringe Relevanz der gesamten Diskussion für den Lauf der Welt durchaus bewusst, und dennoch beharren sie auf ihrer technologischen Unabhängigkeit:

Apart from that, the big difference between using whatsapp or email is that with email you get independence: I have my own email servers using my own domains that just a court can take away from me, use the OS and MTA of my choice that I can modify and compile from source, set up my spam filters, webmail and everything else just the way I want, and everything works the way I want.

It's like being the owner of my own piece of land or just a poor peasant in somebody's else huge land.

Volltextsuche

Vor einigen Jahren hatte ich die Suchfunktion für meine Website aus Kapazitätsgründen auf Seitentitel und Autorinnen beschränken müssen, aber die Rahmenbedingungen haben sich seitdem erheblich geändert. Einerseits lässt Moore's Law Server sehr viel entspannter mit großen Datenbanken umgehen (so dass ich zwischenzeitlich eine komputational teure tag cloud implementieren konnte, wenn auch mit lastdämpfendem Caching), andererseits müssen Besucherinnen meiner Website seit mehr als einem Jahr ganz ohne Suchfunktion auskommen. Und weil ich selbst die Vielzahl der Einzelseiten nicht ausschließlich per psql durchforsten möchte, erweitere ich meine Django-Anwendung wie folgt:

# forms.py class SearchForm(forms.Form): page_title = forms.CharField(max_length=100, label = 'Titel', required=False) page_content = forms.CharField(max_length=100, label = 'Inhalt', required=False) page_author = forms.CharField(max_length=100, label = 'Autor*in', required=False) # views.py results = Page.objects.filter(title__icontains=form.cleaned_data['page_title'], content__icontains=form.cleaned_data['page_content'], author__last_name__icontains=form.cleaned_data['page_author']).order_by('title')

Bei einem DB-Volumen von ~ 120MB zuckt die CPU-Kurve des Datenbankservers nicht einmal.

デジタル経営研究委員会臨時ワーキンググループ

Wenn mein Gremium zur digitalen Effizienzsteigerung temporäre digitale Verwaltungsforschungskommittee-Arbeitsgruppe hieße und in seiner 13. Sitzung eine Problemanalyse vereinbart hätte, würde ich keine zu großen Hoffnungen auf rasche Erfolge im War on Floppy Discs schüren.

Unberührbar

Der robuste Umgang von Homebrew mit Paketversionen sorgt immer wieder für Überraschungen. Nach der Umbenennung von postgresql in postgresql@14 muss ich wieder einmal diverse Verlinkungen in /opt/homebrew/bin korrigieren und schließlich psycopg2 neu installieren (natürlich erst nach einer Anpassung des Symlinks für pip3). Leider wird so nicht nur eine (mit zunehmendem Alter ohnehin wachsende) Sympathie für ein konservativeres Paketmanagement gefördert, sondern auch eine riskante Aversion gegen Updates.

Gemeinkörper

Der Verzicht auf grundlegende Gebote der Höflichkeit bei der Verwendung elektronischer Kommunikationsmittel und insbesondere auf Mailinglisten bleibt nicht ohne Folgen:

X-Spam-Status: No, score=-0.125 tagged_above=-1000 required=7 tests=[POSTEO_RUDE_BODY_30=0.375, P_AUTH_RES_DMARC_PASS=-0.5, T_POSTEO_TLSINY=0.01, T_SCC_BODY_TEXT_LINE=-0.01] autolearn=disabled

Ich werde wohl meine Posts künftig etwas förmlicher einleiten müssen (Sehr geehrte Listenadministratorin, verehrte Listenmitglieder und Besucher*innen des Mailinglistenarchivs...).