úterý 3. března 2015

Rozbitý formát HTML emailu

V práci jsme nedávno aktualizovali HTML online editor pro vytváření obsahu emailů - přešli jsme na CK editor.
Po nasazení se nám ozval jeden z uživatelů, že někteří příjemci jeho emailů dostali email divně naformátovaný - například se jim nezobrazili obrázky či některé odkazy byly podtržené, i když dle deklarace stylu neměly být apod.

A tak začalo pátrání, co za to může. Samozřejmě prvním podezřelým byl CK editor, ale výstup, který generoval byl v pořádku. Jeho výstupní HMTL kód byl validní.

Mezitím se také zjistilo, že problémy se správným zobrazením měli jen příjemci s poštovní schránkou na AOL. Ostatním se email vždy zobrazil dobře.

Pro lepší představu, jak problém zhruba vypadal, jsem si udělal jednoduchý projekt a vytvořil testovací obsah, na kterém je problém patrný. Tvoří jej několikrát opakované logo Blogger služby, jednotlivá loga jsou oddělená mezerou - a celý obsah je na jedné řádce (shodně je  nastaven i CK editor). Takto vytvořený obsah je uložen v souboru přidaném do projektu a nastaveném jako Embedded resource:

<p><img src="http://upload.wikimedia.org/wikipedia/commons/4/43/Social_icons-blogger-22x22.png" />&nbsp;<img src="http://upload.wikimedia.org/wikipedia/commons/4/43/Social_icons-blogger-22x22.png" />&nbsp;<img src="http://upload.wikimedia.org/wikipedia/commons/4/43/Social_icons-blogger-22x22.png" />&nbsp;<img src="http://upload.wikimedia.org/wikipedia/commons/4/43/Social_icons-blogger-22x22.png" />&nbsp;<img src="http://upload.wikimedia.org/wikipedia/commons/4/43/Social_icons-blogger-22x22.png" />&nbsp;<img src="http://upload.wikimedia.org/wikipedia/commons/4/43/Social_icons-blogger-22x22.png" />&nbsp;<img src="http://upload.wikimedia.org/wikipedia/commons/4/43/Social_icons-blogger-22x22.png" />&nbsp;<img src="http://upload.wikimedia.org/wikipedia/commons/4/43/Social_icons-blogger-22x22.png" />&nbsp;<img src="http://upload.wikimedia.org/wikipedia/commons/4/43/Social_icons-blogger-22x22.png" />&nbsp;<img src="http://upload.wikimedia.org/wikipedia/commons/4/43/Social_icons-blogger-22x22.png" />&nbsp;<img src="http://upload.wikimedia.org/wikipedia/commons/4/43/Social_icons-blogger-22x22.png" />&nbsp;<img src="http://upload.wikimedia.org/wikipedia/commons/4/43/Social_icons-blogger-22x22.png" />&nbsp;</p>

Pro odeslání emailu jsem použil SMTP server od GMail, tady je kód - pro odeslání je nutné samozřejmě použít platnou emailovou adresu a heslo (své údaje jsem odstranil). Email byl odeslán na dva účty, jeden na AOL a druhý na Yahoo:

const string SmtpServer = "smtp.gmail.com";
const int SmtpPort = 587;
const string FromAddress = "...@gmail.com";
const string SmtpPassword = "<vaseheslo>";
static readonly IEnumerable<string> ToAddresses = new string[] { "....@yahoo.com", "...@aol.com" };

static void Main(string[] args)
{
    var content =  GetResourceString("EmailTest.HtmlEmailContent.html");

    SendEmail(content, "Blogger email");
}

static void SendEmail(string content, string subject)
{
    using (MailMessage mail = new MailMessage())
    {
        mail.From = new MailAddress(FromAddress);

        foreach (var address in ToAddresses)
            mail.To.Add(address);

        mail.IsBodyHtml = true;
        mail.Body = content;
        mail.BodyTransferEncoding = TransferEncoding.SevenBit;
        mail.Subject = subject + " encoded as " + mail.BodyTransferEncoding.ToString();

        using (var client = new SmtpClient(SmtpServer, SmtpPort))
        {
            client.UseDefaultCredentials = false;
            client.Credentials = new NetworkCredential(FromAddress, SmtpPassword);
            client.EnableSsl = true;
            client.Send(mail);
        }
    }
}

static string GetResourceString(string name)
{

    using (var s = System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream(name))
    {
        using (var reader = new StreamReader(s))
        {
            return reader.ReadToEnd();
        }
    }
}

A tady je výsledek pro Yahoo - ten vypadá dobře:


Ale pro  AOL je patrné, že je něco špatně:


Jeden z obrázků není zobrazen. Při kontrole HMTL kódu přes Developer Tools v prohlížeči Chrome (F12) je jasné, že je to díky mezeře/konci řádku v HMTL kódu:


A rozuzlení?


Emailový server byl špatně nakonfigurován a špatně formátoval odchozí emaily (což je v mém kódu nahoře simulováno nastavením na SevenBits). Nějaké další povídaní je i na http://sourceforge.net/p/dotnetopenmail/discussion/441285/thread/0a10e2c7/. Chyba se projevila pouze v případě, že na řádce bylo více jak 1000 znaků - dříve použivaný editor formátoval HTML na více řádků - zkrátka co HTML tag, to řádek a tak délka řádku nikdy nepřesáhla 1000 znaků a chyba se tak neprojevila. 

Nový editor (CK editor) je nastaven na bez-řádkové formátování HTML a chyba se tak projevila - i když ne u všech příjemců - většina emailových klientů opravuje podobné chyby automaticky a tak jejich uživatelé, tedy příjemci emailů, nic nepoznají - což ovšem nebyl případ AOL.

Pokud se v kódu nahoře změní kódování, tj, z 

mail.BodyTransferEncoding  =  TransferEncoding.SevenBit;

na

mail.BodyTransferEncoding  =  TransferEncoding.Unknown;

tak email již dorazí v pořádku:


Ačkoliv to nemusí být z těchto pár řádků patrné, tak pátrání po příčinách chyby zabralo několik dnů.

Žádné komentáře:

Okomentovat