Working with IDN domains and Punycode in C# on .Net

This article aims to give you an overview of the posibilities you can work with IDN on .Net . basically, you can rely on the built-in platform IDN/punycode support, or use a 3rd party libary such as Libidn.

1. Use the .Net framework built-in IDN / Punycode functionality

As in 2015, IDN comes in two standards,  the older RFC 3490 and the newer RFC 5891:

To see the differences between the two standards in the way how they handle particular sets of characters go to Unicode Technical Standard #46: IDNA Compatibility Processing.

So, let's see which cases you may need to implement:

1.1. Just converting a Unicode name to Punycode

If you just need to convert a Unicode string to Punycode, for whatewer reason, lets use the System.Globalization.IdnMapping class:

//let's use a Czech word with non-ASCII chars
//"příklad" means "example"
string unicode = @"příklad";
IdnMapping mapping = new IdnMapping();
string ascii = mapping.GetAscii(unicode);
// this will print: xn--pklad-zsa96e
Console.WriteLine(ascii);
string convertedBackToUnicode = mapping.GetUnicode(ascii);
// this will print the original: příklad
Console.WriteLine(convertedBackToUnicode);

1.2. Sending mail to an e-mail address within an IDN tomain

The .net framework will handle everything for you, you can use such code:

private static void SendMail()
{
    SmtpClient client = new SmtpClient();
    client.DeliveryMethod = SmtpDeliveryMethod.SpecifiedPickupDirectory;
    // lets put this e-mail to the pickup directory so we can examine it
    client.PickupDirectoryLocation = @"c:\temp";
    // lets use just some non-existing email
    MailAddress from = new MailAddress("a@example.இந்தியா");
    MailAddress to = new MailAddress("b@example.இந்தியா");
    using (MailMessage message = new MailMessage(from, to))
    {
        message.Body = "This is a test e-mail message sent by an application. ";
        string someArrows = new string(new char[] { '\u2190', '\u2191', '\u2192', '\u2193' });
        message.Body += Environment.NewLine + someArrows;
        message.BodyEncoding = System.Text.Encoding.UTF8;
        message.Subject = "test message 1" + someArrows;
        message.SubjectEncoding = System.Text.Encoding.UTF8;
        client.Send(message);
    }
}

1.3 Using the System.Uri class with IDN/Punycode

To enable the punycode support in the System.Uri class, as the MSDN documentation says, you have to change the folowing .config file settings.

<configuration>
    <uri>
        <idn enabled="All" />
        <iriParsing enabled="true" />
    </uri>
</configuration>

Then, you can use such code:

Uri uri = new Uri("http://セガ.jp/");
Console.WriteLine("We're going to communicate with: " + uri.DnsSafeHost);
// Run Fiddler, and you will see that request will be sent to 
// a punycode encoded URL - http://xn--mck3a.jp/
WebRequest wr = WebRequest.Create(uri);
using (WebResponse response = wr.GetResponse()) { }

2. Use an External library: Libidn

If you for any reason don't want to use the built-in .Net framework capabilities, you can use the open-source GNU IDN Library - Libidn, the official download also includes a C# port. It is available under the GNU Lesser General Public License version 2.1 or later.