The unicode email address extensions are pleasantly simple to implement. Here is an overview of the RFCs and some notes I made while doing my first implementations; this posting is a very brief description of the protocol and format extensions involved. Despite its brevity it's nearly complete, because these extensions are so simple.
Mail message format: Using UTF8 everywhere is now permitted. Instead of using RFC2047 encoding, quoted-printable and more, messages can use UTF8 everywhere.
To: Jøran Øygårdvær <jøran@blåbærsyltetøy.gulbrandsen.priv.no>
Subject: Høy på pæra
Content-Type: text/plain; charset=utf8
Gørrlei av eksempler.
No encoding is necessary anywhere. The message above lacks From and Date, apart from that it's correct.
Sending mail using SMTP: The server advertises the SMTPUTF8 extension, the MAIL FROM command includes the argument SMTPUTF8, and the email addresses can then use UTF8.
$ telnet mx.example.com 25
Connected to mx.example.com
Escape character is '^]'.
220 mx.example.com ESMTP Postfix (3.0.0)
mail from:<> smtputf8
250 2.1.0 Ok
250 2.1.5 Ok
354 End data with .
Note that the EHLO argument is sent before the client knows whether the server supports SMTPUTF8. It's best to use ASCII-only EHLO arguments.
The SMTPUTF8 argument to MAIL FROM has two purposes: Notify the mail server that one or more addresses may contain UTF8, and make sure that the recipient software does not receive a message it will not be able to parse.
Thus, if you send a message to आर्न्ट@यूनिवर्सल.भारत with a cc to email@example.com and the mail software at example.com does not support SMTPUTF8, then only आर्न्ट@यूनिवर्सल.भारत will receive the message. The mail server for example.com will reject the message. This is intentional.
An MTA needs to do an IDN conversion (e.g. from blåbærsyltetøy.gulbrandsen.priv.no to xn--blbrsyltety-y8ao3x.gulbrandsen.priv.no) as part of MX lookup, a client that connects to its local server doesn't need even that.
Access using IMAP: The server advertises the ENABLE extension, the client sends ENABLE UTF8=ACCEPT (that's legal even if the server advertises only ENABLE), the server acknowledges having enabled UTF8=ACCEPT, and from that point, both server and client can use UTF8 for any quoted string, including folder names, search strings and addresses.
$ telnet imap.example.com 143
Connected to imap.example.com.
Escape character is '^]'.
* OK [CAPABILITY … ENABLE …
a login arnt pils
a OK [CAPABILITY … ENABLE …UTF8=ACCEPT …
b enable utf8=accept
* ENABLED UTF8=ACCEPT
b OK done
c select "Gørrlei"
Testing: Gmail supports this, both for SMTP, IMAP and webmail. The jøran@… address is an autoresponder, you can send mail to it and will receive a reply in a few seconds. Blåbærsyltetøy means blueberry jam and includes all of the three special letters used in Norwegian, æ, ø and å, so it's often used as a test word.
There are more details, but this is 90% of what's needed to write a correct implementation.
Unicode addresses in email, such as مثال@مثال.السعودية, can be written using either Punycode or UTF8. (Or, if you're feeling inventive, in another manner you invent.) Which is best?
UTF8 looks like this:
From: Arabic Example <مثال@مثال.السعودية>, punycode is
From: Arabic Example <firstname.lastname@example.org>.
The answer follows from two of the design goals for the unicode email extensions:
- Allow UTF8 everywhere
- Extend email, don't restrict it
RFC 821 and its successors do not contain any rules such as
you MUST NOT put the letter n next to an x, so Punycode is allowed. EAI allows Punycode by virtue of not forbidding what was previously allowed. But the right way is to use UTF8 everywhere. Use UTF8 in the subject field, in the body text, in the address… everywhere! That's allowed, it's a design goal, and it's better than Punycode for four reasons.
First, it's simpler than using Punycode in addresses, 2047 encoding in the subject text and qp/b64 encoding in the body text.
Second, it's very, very readable. A surprising amount of legacy software does the right thing if you send it UTF8, and that goes for humans who read email source too.
Third, Punycode's interpretation is only specified for domains, and if rumour is to be believed, people are using two incompatible encodings for the localpart. (In the example above, the second and third instances of xn-- are specified, but the first is not and one vendor reputedly does it differently.) You're permitted to send a punycoded localpart to anyone, but the recipient is not required to interpret it in the way you intend.
Fourth, sending Punycode habituates users to accept random hex blobs in addresses. A phisher's dream.
So use UTF8 everywhere in the message. Mapping to Punycode is necessary when doing the MX lookup in order to transmit the message, but only then.
I've implemented unicode mail three times now; in Postfix (paid for by CNNIC and not yet integrated), in aox and lastly in an old mail reader I'm porting from the Zaurus PDA to Android (unreleased as yet, send me mail if you'd like beta access). This is mostly a random collection of notes and remarks I collected while writing the code.
The specification was produced by an IETF working group called EAI (short for email address internationalisation). The WG produced two generations of RFCs. First, an experimental series which I ignore, then a revised, simplified and improved series. This covers the second generation, which takes the general position that unicode mail is only sent to recipients who understand it. There is no conversion during transport, and (almost) no fallback to ASCII.
RFC 6530 is an overview/introduction. It points to the other documents, and has some extra text. Worth reading.
6531 describes how unicode addresses are used with SMTP: MAIL FROM, RCPT TO and VRFY accept UTF8 addresses, and there's a safeguard to provoke a syntax error in case a unicode message body would otherwise reach someone who cannot accept it. […More…]
There is only one way to send email with SMTP: Connect, send EHLO, MAIL FROM, RCPT TO, BODY and the message. There are variations, but they're small. Most protocols offer implementers much more choice, many even demand much more.
This post is about a way to quantify the efficiency of the choices an implementer makes. It's a bit extremist, because extremism is simple and requires little thought: Bytes transmitted are defined to be useful if they're displayed on the user's display before the use case ends, and to be waste in all other cases.
The wasted bytes may be avoidable waste, unavoidable waste, Schrödinger's waste or even useful waste — it doesn't matter. This method applies a simple and unfair definition. Because the test is simple you can apply it quickly, and usually you learn something from doing the analysis.
The method leads to three numbers and hopefully nonzero insight: Percentage of bytes used to display, number of bytes downloaded per character displayed, and finally number of bytes used per character displayed. You get the insight not from the three numbers, but rather as a side effect of computing the three numbers.
I'll elaborate with two longish examples. […More…]