Nur ein Doppelpunkt

Wenn ich eine Software schreibe, die eine E-Mail konstruiert – Header, Body, das Ganze in einer adäquaten Kodierung – dann habe ich verschiedene Möglichkeiten, um zu prüfen, ob ich alles richtig gemacht habe. Ich kann möglichst viele verschiedene Varianten samt jeglicher hypothetischer Sonderfälle raus in die Weltgeschichte schicken und schauen, ob alle damit klarkommen: Ob die Mail von Mailservern wie Sendmail, qmail, Postfix, Courier, Exchange, Exim oder Lotus Domino problemlos durchgeleitet werden kann (und viele davon laufen nicht nur unter einem Betriebssystem, sondern unter vielen verschiedenen, wenigstens unter verschiedenen Versionen des gleichen Betriebssystems), und ob hinterher Outlook, Outlook Express, Thunderbird, Eudora, Evolution, Mail.app, Lotus Notes, Sylpheed, Balsa, verschiedene Webmailer und Smartphone-Clients meine Mail korrekt anzeigen.

Oder ich halte mich einfach an den Standard, wie eine Mail auszusehen hat: RFC 822.

Die heutige kleine Geschichte dreht sich um einen Doppelpunkt; genauer gesagt, um zwei. Ein User auf einem unserer Server arbeitet für einen Verein, dessen Corporate Identity einen doppelten Doppelpunkt im Schriftzug des Vereins vorsieht, im Sinne von mein::verein. Als Klartextname für E-Mails ist entsprechend vorgesehen: Vorname Nachname | mein::verein. Darüber kann man streiten, aber fest steht: Es ist natürlich völlig legitim, im Klartextnamen auch Sonderzeichen verwenden.

Das Problem entzündet sich nun daran, dass jener User als Mailclient Thunderbird einsetzt, und Thunderbird erstellt aus dem Klartextnamen und der E-Mail-Adresse folgenden Absender:

From: Vorname Nachname | mein::verein <vorname.nachname@mein-verein.de>

Um’s direkt vorwegzunehmen: So ist es falsch. Richtig wäre vielmehr:

From: "Vorname Nachname | mein::verein" <vorname.nachname@mein-verein.de>

Der Grund dafür liegt darin, dass der Doppelpunkt zur Zeichenklasse der „specials“ gehört, was schon von daher nicht verwunderlich ist, als dass er bereits das Trennzeichen zwischen der Headerbezeichnung („From“) und dem Inhalt des Headers ist. RFC 822 formuliert sogar ausdrücklich aus:

     specials    =  "(" / ")" / "<" / ">" / "@"  ; Must be in quoted-
                 /  "," / ";" / ":" / "\" / <">  ;  string, to use
                 /  "." / "[" / "]"              ;  within a word.

Keine große Sache, möchte man meinen. Trivial geradezu. Aber Thunderbird macht’s eben nicht.

Problematisch wird das nun, wenn die Mail an ein Programm gelangt, das sich an den Standard hält und dann entsprechend nicht weiß, wie es mit dieser Zeile umgehen soll. Das ist vielleicht nicht ganz einfach zu verstehen, denn als Mensch schaut man auf die Zeile drauf und sieht natürlich, wie sie gemeint ist. Software ist aber kein Mensch, sondern arbeitet nach strikten Abläufen, und diese Abläufe orientieren sich im Fall von Software, die Mails verarbeiten muss, logischerweise daran, wie die Regeln laut RFC den Aufbau vorschreiben. Im konkreten Fall ist es qmail-inject, das – weil der Empfänger seine Adresse als Weiterleitung konfiguriert hat – die Mail verarbeiten muss, um sie wieder der Queue des Mailservers zuzuführen, und das endet dann mit einer Bouncemail, die uns sagt:

qmail-inject: fatal: unable to parse this line:
From: Vorname Nachname | mein::verein <vorname.nachname@mein-verein.de>

Dass der Header falsch war, war auf den ersten Blick ersichtlich. Die wichtige Frage ist aber: Warum? Hat der Absender da etwas falsch gemacht – oder gar Thunderbird?

Es stellt sich heraus: Es gibt bereits eine ganze Reihe von Bug-Reports für Thunderbird dazu. Um nur einige zu nennen:

  • 524471 – Address from is incorrectly quoted in To: header field
  • 273037 – RFC 822 ’specials‘ not being properly quoted as per spec
  • 317296 – Recipient headers can be invalid if there are invalid chars that aren’t quoted
  • 474136 – from header line – no quoting if required by a colon within display name

(Der Fehler betrifft neben dem „From:“-Header genauso auch den „To:“-Header, insofern sind die entsprechenden Bug-Reports zu letzterem ebenfalls als zu unserem Problem passend anzusehen.)

Besonderes Augenmerk wäre hier auf den zweiten zu legen, in dem ansatzweise eine Diskussion dazu stattfand, während in den anderen überhaupt nichts Signifikantes passiert ist. Im fraglichen Ticket beklagt sich ein Anwender, bei der Verarbeitung der Mail auf Empfängerseite mittels javamail würde die Zielanwendung crashen. Nun ist das ohne Frage unschön und sollte nicht „so“ passieren, aber immerhin haben wir hier auch zwar nicht mit einem Crash zu tun, aber doch immerhin mit einem sauberen Abbruch, der ordentlich ausgibt, warum der Mailheader nicht verarbeitet werden konnte. Ob nun Crash oder sauberer Abbruch: Für den Enduser ist das nicht relevant. Die Mail wird nicht weitergeleitet. Das ist schlecht.

Einer der Thunderbird-Entwickler stellt nun zunächst ganz sachlich fest:

I assume he’s speaking about RFC 822, which states merely that : is a special, and „must“ be quoted if not being used as a delimiter. We may be not adhering to this spec.

Einsicht ist der erste Schritt zur Besserung, möchte man meinen. Doch weit gefehlt:

I receive mails daily where the colon is not quoted, and Mozilla doesn’t crash. Nor did Eudora, Outlook or Outlook Express, Pine, nor any other mail client I’ve used. It should be able to gracefully handle errors, and somethign as simple as a colon in the TO: field line should not crash it.

Das sind so die Momente, wo ich froh bin, nur vor einem Monitor zu sitzen, um nicht einem realen Menschen meine akute Sprachlosigkeit demonstrieren zu müssen. „Andere Mailclients haben da auch kein Problem mit“ ist nun wirklich überhaupt kein Grund, eine Missachtung von Standards zu rechtfertigen. Wenn ich selbst einen Mailclient schreiben wollte, dann interessiere ich mich nicht die Bohne dafür, welcher Mailclient in welchen Aspekten irgendwie rummurkst: Entweder er macht es richtig, oder er macht es falsch. Thunderbird macht es falsch, und es ist nicht meine Aufgabe, in meiner Software Workarounds für Bugs in Thunderbird zu schreiben.

Nun ist es natürlich völlig legitim, zu sagen: Naja gut, javamail sollte nun aber nicht gleich crashen. Ist ja auch richtig. „Be liberal in what you accept“ und so. Aber davon unabhängig kann man ja trotzdem auch schon mal den Fehler auf der eigenen Seite beheben, gerade nachdem man schon eingesehen hat, dass es einen gibt. Aber, Überraschung:

In fact, no character there should crash the app. In fact, the app should never crash due to malformed mails. That’s just bad form. […] Good luck to the javamail guys in fixing their crasher.

Mit anderen Worten: Ist mir egal. Die Gegenseite soll sich nicht so anstellen. Viel Glück.

Ich glaube, was mich an dieser Sache so bestürzt, ist, dass ich diese Geisteshaltung ausgerechnet bei einem Open-Source-Projekt erlebe. Schließlich ist freie Software ideell eng mit offenen Standards und darauf basierend mit einem starken Bestreben nach Interoperabilität verbunden. Man stelle sich vor, im Bereich der Entwickler von Browsern einerseits und Webservern andererseits gäbe es ähnliches Gezetere, weil man sich eben nur so vage und nicht ganz genau an den HTTP-Standard hielte, mit der Folge, dass ein Internet Explorer nur noch mit einem IIS so richtig kommunizieren könnte und ein Firefox nur noch mit einem Apache. Das wäre natürlich total lächerlich und würde die Entwicklung des Webs um Jahre zurückwerfen.

Vielleicht sehe ich die Sache auch deshalb so eng, weil ich seit Beginn meines Arbeitslebens eng mit der Software von Dan Bernstein verbunden bin, der unter anderem auch den qmail-Mailserver entwickelt hat, dessen Komponente qmail-inject sich gerade an dem fehlerhaften Header stört. Bernstein gehört zu den Leuten, die geradezu eine innige Liebe zu Standards und Interoperabilität entwickelt haben – und vor allem eine um so innigere Abneigung gegenüber Produkten und Personen, die diese Liebe nicht teilen. Auf den Mailinglisten weht ein rauer Wind, und nicht wenige haben über die Jahre hinweg geradezu eine „Nee, wenn das Programm von Bernstein ist, dann benutze ich das nicht, der Typ ist ein A***“-Haltung kultiviert. Letztlich ist das aber genau so ein Personenkult (nur eben ein negativer), wie Bernstein ihn stets abgelehnt hat: Für ihn war und ist wichtig, dass Software korrekt und berechenbar funktioniert, unabhängig davon, ob dahinter ein netter Mensch steht oder ein A***. Für diese Haltung hege ich große Sympathie.

Doch kurz zurück zum Bug-Report. Dessen bizarrster Punkt ist nämlich noch gar nicht gekommen. Der kommt erst jetzt, in der kurzen Code-Analyse eines anderen Community-Mitglieds:

According to nsMsgHeaderParser.cpp we’re not quoting :s so as not to break some systems which aren’t expecting them to be quoted…

Also, nur um das nochmal festzuhalten: Quoting spezieller Zeichen ist eine ausdrückliche Vorgabe von RFC 822. Und weil es nun „einige Systeme“ gibt, die mit einem solchen Quoting nicht umgehen können, sich also nicht an den Standard halten … spart Thunderbird sich das Quoting einfach und hält sich so ebenfalls nicht mehr an den Standard – und empfiehlt dann denen, die sich an den Standard halten und sich somit legitimerweise an dem fehlerhaften Header stören, doch gefälligst mal Fünfe gerade sein zu lassen. Bizarr finde ich das vor allem deshalb, weil alle anderen mir bekannten Mailclients (um mich mal kurz auf das argumentative Niveau des Bug-Reports herabzulassen) in Tests den Klartextnamen mit den Doppelpunkten korrekt in Anführungszeichen setzen, sogar Outlook und Outlook Express, die in Sachen Standardkonformität sich nun wirklich über Jahre hinweg einen außerordentlich schlechten Ruf erarbeitet haben.

Insbesondere die Arroganz, mit der hier die Veranwortung für den eigenen Fehler auf Dritte geschoben wird, hat mich bei der Lektüre wirklich erstaunt. „Be liberal in what you accept“ sollte aus meiner Sicht ein Ansatz sein, um die Interoperabilität zwischen Applikationen zu erhöhen – nicht aber eine Rechtfertigung dafür, selbst fehlerhafte Daten generieren zu dürfen: „Be conservative in what you send“ ist schließlich ebenfalls eine Vorgabe des gleichen Robustheitsprinzips. Übrigens die, die zuerst genannt wird. Und ich finde, von anderen zu verlangen, ihre Hausaufgaben zu machen, steht in erster Linie denen zu, die ihre eigenen bereits gemacht haben. Das sieht unser Thunderbird-Entwickler aber nicht so und polemisiert:

I think clients these days are generally smart enough to know what’s a header and what isn’t (usually).

Na und? Vielleicht stehe ich mit dieser Ansicht zunehmend alleine da. Aber ich finde wichtig, dass Software berechenbar ist und nicht „smart“. Dass sie Fehler in Daten als Fehler in Daten benennt und diese sauber und ordentlich ablehnt. Zu verlangen, dass eine Software Daten als fehlerhaft erkennt, daraus eigene Schlüsse zu ziehen versucht und dann statt dem, wozu man sie beauftragt hat, das macht, was sie für vermeintlich richtig hält, würde ich als Ursache vieler Übel betrachten.

Demjenigen, der den Fehler überhaupt erst an die Thunderbird-Entwickler gemeldet hat, gebührt das Schlusswort des Bug-Reports, und er offenbart dabei von allen Beteiligten die größte Weisheit:

I agree it is dumb to not have the client gracefully handle this. Yet if it is part of a standard, it makes sense. Otherwise standards become pointless; not all reasons for a given standard are always obvious up front, even when we know most of the reasons.

Und das ist genau der Punkt: Kaum eine einzelne Person kann die Vielzahl von Gründen dafür ermessen, warum sich ein Standard so und nicht anders entwickelt hat. Vor allem kann kaum eine einzelne Person die Folgen einer Abweichung vom Standard einschätzen – hier versäumt man zwei Anführungszeichen; da crasht deswegen ein Mailclient, und dort funktioniert eine Weiterleitung nicht mehr. Die Entwickler wären gut beraten, ein wenig Demut walten zu lassen und sich zu sagen: Im Zweifelsfall wissen wir zwar nicht, warum der Standard das so vorschreibt. Vielleicht finden wir es auch dumm, wie es der Standard will. Aber: Dutzende von Mailservern auf Dutzenden von Betriebssystemen sowie hunderte von Mailclients verlassen sich darauf, dass alle es so machen, wie der Standard es verlangt – also sollten wir uns lieber auch daran halten.

Lassen wir zum Schluss noch einmal Bernstein zu Wort kommen, der sich bereits vor über einem Jahrzehnt reichlich desillusioniert zum Thema Protokolldesign äußerte:

So you want to design a protocol? I’ll let you in on an evil secret: most implementors will never read your spec.
Instead, they’ll look at some common examples and write the most obvious code that works for those examples.

Thunderbird hat mir heute ein weiteres frustrierendes Beispiel für diese Geisteshaltung geliefert. Der letzte Eintrag des Tickets ist übrigens aus dem Dezember 2004. Jüngere Tickets, die das Problem ebenfalls beschreiben, blieben bisher unbearbeitet. Für mich entspricht das einem unausgesprochenen WONTFIX.