Renderização de HTML em e-mail. Porque é que ainda estamos em 2003

Há uns dias, alguém me perguntou porque é que um e-mail que parecia impecável no browser chegava ao Outlook com as colunas todas desfeitas, os botões fora do sítio e uma imagem que parecia ter decidido mudar de residência. O HTML estava correcto. O CSS também. Pelo menos, segundo os critérios de um browser moderno. O problema estava do outro lado, no programa que tinha de mostrar aquilo ao utilizador.

Quem trabalha com HTML para e-mail conhece bem esta história. Passamos anos a acompanhar a evolução dos browsers, aprendemos a usar flexbox, grid, variáveis CSS e meia dúzia de técnicas que simplificam a vida a quem desenvolve interfaces. Depois, chega a altura de criar uma newsletter e voltamos às tabelas, ao CSS inline e aos remendos que julgávamos enterrados há duas décadas.

Não é nostalgia. É compatibilidade.

O Outlook e a herança do Microsoft Word

O problema começa quando percebemos que nem todos os clientes de e-mail interpretam HTML da mesma maneira. Um browser moderno utiliza um motor de renderização concebido para apresentar páginas Web complexas. Um cliente de e-mail pode usar um motor completamente diferente, com limitações próprias e decisões de implementação que nem sempre fazem sentido para quem escreve código.

O exemplo mais conhecido é o Outlook clássico para Windows, que utiliza o motor de renderização do Microsoft Word para apresentar mensagens HTML. Sim, o mesmo Word que usamos para escrever relatórios e documentos. Não é propriamente a ferramenta que escolheríamos para interpretar uma interface Web moderna, mas foi essa a decisão tomada pela Microsoft para determinadas versões do Outlook.

O resultado é previsível. Muitas propriedades CSS que funcionam sem problemas no Chrome, no Firefox ou no Edge podem ser ignoradas, interpretadas de forma diferente ou simplesmente produzir resultados inesperados no Outlook clássico.

Convém fazer uma distinção. Nem todos os produtos com o nome Outlook utilizam o mesmo motor de renderização. O Outlook clássico para Windows, o novo Outlook, o Outlook na Web e as aplicações móveis não se comportam necessariamente da mesma forma. O problema é precisamente esse. Não existe um único Outlook para o qual possamos optimizar o código e dar o assunto por encerrado.

É como administrar uma rede onde cada switch interpreta uma parte da configuração à sua maneira. Podemos ter a documentação impecável, mas, se o equipamento do outro lado não suportar determinada funcionalidade, a configuração não vai produzir o resultado esperado.

Flexbox e Grid não são uma aposta segura

Quem desenvolve para a Web está habituado a construir layouts com flexbox e CSS Grid. São ferramentas excelentes, reduzem a quantidade de código necessária e permitem criar interfaces adaptáveis sem recorrer a estruturas artificiais.

Nos e-mails, a história é outra.

O suporte a estas tecnologias varia entre clientes e motores de renderização. Um layout construído com display: flex pode funcionar perfeitamente no Gmail e apresentar problemas num cliente mais antigo ou numa versão específica do Outlook. Com Grid, as limitações podem ser ainda mais evidentes.

O problema não é o flexbox ou o Grid estarem mal implementados. O problema é assumir que todos os clientes de e-mail suportam as mesmas funcionalidades.

Imagine-se uma newsletter com duas colunas, uma imagem à esquerda e texto à direita. Num browser moderno, podemos construir a estrutura com flexbox e controlar facilmente o comportamento em ecrãs pequenos. Num cliente de e-mail com suporte limitado, as colunas podem deixar de alinhar, o texto pode passar para baixo da imagem ou os espaços podem desaparecer.

E depois começa a habitual investigação. O código é revisto, o CSS é alterado, a mensagem é enviada novamente e alguém pergunta se já funciona no Outlook. À terceira tentativa, a equipa já perdeu mais tempo com uma newsletter do que com a configuração de um servidor.

A solução passa por aceitar as limitações do meio. Para layouts que precisam de funcionar numa grande variedade de clientes, as tabelas HTML continuam a ser uma das opções mais fiáveis. Não são elegantes do ponto de vista de quem desenvolve aplicações Web modernas, mas são previsíveis. E, em produção, previsibilidade vale mais do que elegância.

As tabelas ainda têm lugar no e-mail

Numa página Web, usar tabelas para organizar um layout é geralmente uma má escolha. Existem ferramentas mais adequadas, mais flexíveis e mais acessíveis.

Num e-mail HTML, porém, as tabelas continuam a desempenhar um papel útil. Permitem definir estruturas com colunas, controlar alinhamentos e manter elementos no sítio certo em clientes que não suportam bem as técnicas modernas de CSS.

Podemos, por exemplo, criar uma tabela exterior para controlar a largura total da mensagem e uma tabela interior para organizar o conteúdo. Cada célula recebe o texto, as imagens ou os botões necessários. É uma abordagem antiga, mas suficientemente compatível para muitos cenários.

Isto não significa que devamos transformar todos os elementos numa tabela. A ideia é usar tabelas para a estrutura principal quando a compatibilidade o exige e reservar o CSS para aquilo que cada cliente consegue interpretar de forma consistente.

Também convém não complicar demasiado o layout. Uma newsletter com três colunas, vários fundos sobrepostos e alinhamentos dependentes de propriedades pouco suportadas será sempre mais difícil de manter do que uma mensagem simples, com uma coluna principal e uma hierarquia visual clara.

A simplicidade não resolve todas as incompatibilidades, mas reduz o número de sítios onde as coisas podem correr mal. É o equivalente a manter uma configuração de rede compreensível em vez de criar uma cadeia de regras que só o autor consegue decifrar.

CSS inline. O velho conhecido

Outro hábito que parece estranho a quem desenvolve para a Web é colocar estilos directamente nos elementos HTML.

Em vez de depender exclusivamente de uma folha de estilos ou de um bloco <style>, podemos escrever algo como <td style="padding: 20px; font-family: Arial, sans-serif; color: #333333;">.

Não é a forma mais agradável de manter código. Os estilos ficam repetidos, as alterações tornam-se menos cómodas e o HTML cresce rapidamente. Ainda assim, o CSS inline continua a ser uma técnica importante na produção de e-mails.

Alguns clientes removem ou alteram partes do HTML e do CSS, limitam determinados seletores ou tratam de forma diferente os estilos definidos no cabeçalho. O comportamento varia consoante o cliente, pelo que não devemos assumir que todos os estilos serão preservados.

Colocar as propriedades essenciais directamente nos elementos ajuda a reduzir algumas destas diferenças. Não garante compatibilidade absoluta, mas torna o resultado mais previsível.

Há, contudo, uma ressalva. CSS inline não significa colocar tudo em todo o lado. Devemos concentrar-nos nas propriedades necessárias para garantir a apresentação, como cores, tipografia, espaçamento e alinhamento, e testar os casos em que dependemos de comportamentos mais específicos.

Também não devemos esquecer que o CSS inline não substitui os testes. Uma mensagem pode estar perfeitamente estilizada e, ainda assim, apresentar problemas com imagens, dimensões, botões ou conteúdo que varia entre clientes.

MJML e outras ferramentas para não escrever tudo à mão

É precisamente para reduzir este trabalho que existem ferramentas como o MJML.

O MJML é uma linguagem de marcação concebida especificamente para criar e-mails responsivos. Em vez de escrevermos manualmente todas as tabelas e os respectivos estilos, construímos a mensagem com componentes próprios, como secções, colunas, imagens e botões. O compilador gera depois HTML preparado para funcionar numa variedade de clientes de e-mail.

Na prática, podemos descrever uma estrutura de duas colunas com componentes do MJML e deixar que a ferramenta produza grande parte do HTML necessário. O resultado é normalmente mais fácil de manter do que uma mensagem construída à base de tabelas escritas à mão.

Isto não elimina todas as limitações dos clientes de e-mail. O MJML não consegue obrigar o Outlook a suportar uma propriedade CSS que o seu motor de renderização não conhece. Também não dispensa a validação do resultado final.

É uma ferramenta para reduzir o trabalho repetitivo e evitar alguns erros comuns, não uma licença para deixar de testar.

Há ainda outra vantagem. Separar a intenção do código final facilita a manutenção. Se quisermos alterar a largura de uma secção ou o comportamento de uma coluna, podemos trabalhar num nível mais simples e deixar que o compilador trate de gerar a estrutura compatível.

Para quem desenvolve newsletters regularmente, esta abordagem pode poupar bastante tempo. Para uma mensagem pontual, talvez seja suficiente um modelo HTML simples, bem testado e documentado. Nem todos os problemas precisam de mais uma ferramenta instalada no servidor.

O problema também existe do lado de quem recebe

Até aqui, falámos de quem cria e-mails. Mas há outra metade da história que merece a mesma atenção.

Quando um cliente de e-mail recebe uma mensagem HTML, não deve assumir que o conteúdo é seguro só porque chegou através de um servidor legítimo ou porque foi enviado por alguém conhecido.

O HTML de um e-mail pode conter imagens externas, ligações para páginas maliciosas, elementos inesperados e construções que tentam explorar diferenças no comportamento dos clientes. O facto de a mensagem ser apresentada dentro de uma aplicação de correio electrónico não a torna inofensiva.

Por isso, um cliente de e-mail bem concebido deve tratar o HTML recebido como conteúdo não fiável. A prioridade não é reproduzir fielmente tudo aquilo que o remetente enviou. É apresentar a mensagem sem permitir que o conteúdo execute acções perigosas ou comprometa a privacidade do utilizador.

Uma das primeiras medidas consiste em bloquear conteúdo remoto por omissão, sobretudo imagens e outros recursos carregados a partir de servidores externos.

Pode parecer um incómodo quando recebemos uma newsletter e temos de carregar num botão para ver as imagens. Mas existe uma razão para isso.

As imagens remotas também servem para vigiar

Uma imagem num e-mail pode parecer perfeitamente normal. Um logótipo, uma fotografia de um produto ou um pequeno elemento decorativo.

Só que a imagem pode estar alojada num servidor externo e ser carregada através de um URL único, associado à mensagem ou ao destinatário.

Quando o cliente de e-mail pede essa imagem ao servidor, o pedido pode revelar que a mensagem foi aberta. Dependendo da informação disponível e da forma como o servidor regista os pedidos, também pode permitir recolher dados técnicos sobre a ligação e estimar determinadas características do dispositivo ou da localização.

É aqui que entram os chamados tracking pixels. São normalmente imagens minúsculas, por vezes transparentes, usadas para registar a abertura de uma mensagem. O utilizador pode nem sequer saber que existem.

Bloquear imagens remotas por omissão reduz esta forma de acompanhamento. Não elimina todo o tracking, porque as ligações podem também encaminhar o utilizador para sistemas de medição e alguns clientes carregam ou armazenam imagens de forma que altera o significado dos registos. Ainda assim, é uma medida simples que devolve algum controlo a quem recebe o e-mail.

Há um detalhe adicional. Alguns serviços de correio electrónico carregam imagens através de proxies ou fazem o seu armazenamento em cache. Nestes casos, o remetente pode receber informação sobre um pedido de imagem sem conseguir determinar com precisão quando, ou mesmo se, o utilizador abriu a mensagem. Os dados de abertura nunca foram uma fonte perfeita de verdade, apesar de muita gente os tratar como se fossem a saída de um monitor de rede.

Um cliente de e-mail pode, portanto, mostrar uma mensagem sem carregar automaticamente imagens externas e permitir ao utilizador autorizar o seu carregamento quando considerar necessário. É um compromisso razoável entre usabilidade e privacidade.

Sanitizar HTML não é o mesmo que o esconder

Bloquear imagens remotas resolve apenas uma parte do problema. O HTML recebido também precisa de ser tratado antes de ser apresentado.

Uma abordagem comum consiste em sanitizar o conteúdo, removendo elementos, atributos e construções que não devem ser aceites. Ferramentas como o DOMPurify ajudam a fazer este trabalho em ambientes JavaScript, filtrando HTML de acordo com regras de segurança.

Mas convém perceber o que estamos a fazer. Sanitizar não é simplesmente apagar algumas etiquetas suspeitas com uma expressão regular. O HTML tem uma estrutura complexa, e tentar limpá-lo através de substituições improvisadas pode deixar passar construções perigosas ou produzir resultados inesperados.

Uma biblioteca de sanitização mantida e devidamente configurada é um ponto de partida muito melhor. Ainda assim, o DOMPurify não deve ser tratado como uma solução completa para todas as ameaças associadas ao e-mail. É necessário definir uma política adequada ao conteúdo que pretendemos apresentar, restringir os elementos e atributos permitidos e garantir que os URLs são tratados correctamente.

Também importa perceber onde será apresentado o HTML. Um cliente que renderiza mensagens num ambiente isolado, sem acesso a funcionalidades sensíveis da aplicação, tem uma superfície de ataque diferente de uma aplicação que mistura directamente o conteúdo recebido com a sua própria interface.

A sanitização deve fazer parte de uma estratégia de defesa em profundidade, juntamente com o isolamento da renderização, a restrição de recursos externos e o controlo das ligações. E, naturalmente, o cliente deve impedir a execução de JavaScript arbitrário proveniente das mensagens. Um e-mail não precisa de executar código para mostrar texto, imagens e ligações.

A regra é simples. O remetente controla o conteúdo da mensagem, mas não deve controlar a aplicação que a apresenta.

Compatibilidade não pode justificar tudo

Existe uma tentação, sobretudo em sistemas antigos, de aceitar qualquer comportamento estranho em nome da compatibilidade. Se o Outlook não mostra uma imagem, acrescenta-se mais um atributo. Se uma coluna desaparece, introduz-se outra tabela. Se um cliente remove um estilo, duplicam-se as propriedades até a mensagem parecer aceitável.

Algumas destas técnicas são necessárias. O problema começa quando deixamos de perceber porque existem e passamos a acumulá-las por hábito.

Quem gera HTML para e-mail deve trabalhar com uma base de código previsível, limitar a complexidade dos layouts e testar as mensagens nos clientes que realmente importam para o público. Também deve manter modelos reutilizáveis e documentar as excepções que foram introduzidas para resolver problemas concretos.

Uma alteração aparentemente inofensiva num modelo partilhado pode afectar dezenas de newsletters. Sem testes e sem registo das decisões, acabamos a descobrir o problema através de um ticket aberto por alguém que recebeu uma mensagem com o botão de compra fora do sítio.

É o tipo de situação em que um pequeno processo de validação vale mais do que uma tarde a corrigir HTML à pressa. O falhanço não deixa rasto, mas acrescenta experiência. O problema é que, sem documentação, a experiência desaparece quando muda a pessoa que trata do sistema.

Do lado do cliente, a prioridade deve ser igualmente clara. O HTML recebido é conteúdo não fiável. Deve ser apresentado num ambiente controlado, sem execução arbitrária de código, com sanitização adequada e com o carregamento de recursos externos bloqueado por omissão.

São preocupações diferentes, mas complementares. Uma tenta garantir que a mensagem chega ao destinatário com uma apresentação aceitável. A outra procura impedir que essa mesma mensagem abuse da confiança do destinatário.

Afinal, ainda estamos em 2003?

Não exactamente. Os clientes de e-mail evoluíram, o suporte a CSS melhorou e existem ferramentas que tornam o desenvolvimento de mensagens responsivas bastante menos doloroso. Mas a compatibilidade continua fragmentada, e há clientes que mantêm decisões técnicas que condicionam o trabalho de quem produz HTML.

Por isso, a melhor abordagem não é tentar reproduzir num e-mail tudo aquilo que conseguimos fazer numa página Web. É perceber as limitações do meio e escolher técnicas adequadas ao resultado pretendido.

Tabelas quando são necessárias. CSS inline para os estilos essenciais. MJML quando compensa automatizar a geração do HTML. Testes reais nos clientes relevantes, em vez de confiar apenas no resultado apresentado pelo browser.

E, do outro lado, um cliente de e-mail que não confunda fidelidade visual com segurança. Bloquear imagens remotas por omissão, sanitizar HTML com ferramentas apropriadas, isolar a renderização e impedir tracking desnecessário são decisões razoáveis, não luxos reservados a quem tem tempo para se preocupar com privacidade.

No fundo, o e-mail continua a ser uma tecnologia extraordinariamente útil, mas não funciona como uma página Web normal. Quem escreve mensagens tem de aceitar que o código será interpretado por motores diferentes. Quem constrói clientes tem de assumir que o conteúdo recebido pode ser hostil.

O resto é engenharia. E alguma paciência. Afinal, já aprendemos há muito tempo que um sistema não se torna fiável por funcionar no nosso ecrã. Torna-se fiável quando continua a funcionar nos ecrãs dos outros, sem comprometer a segurança de ninguém.

Deixe um comentário