Usando PHP para tratar E-mail com Acentos e Caracteres Especiais

Artigo que mostra como utilizar o PHP para incluir acentuação ou caracteres especiais em e-mail, tanto no título do assunto quanto no conteúdo.

Introdução

Ao utilizar a função mail do PHP, você pode se deparar com um inconveniente por causa de codificação de caracteres usada para o assunto ou o conteúdo do e-mail. O problema é que o protocolo SMTP só permite a transmissão de dados em US-ASCII. Para utilizar caracteres que não fazem parte da tabela US-ASCII, é preciso utilizar um mecanismo de codificação dos dados para que o resultado seja compatível com US-ASCII. Neste artigo, veremos como fazer isso e enviar e-mail com assunto e conteúdo corretamente.


Codificação do assunto

Para codificar o assunto de um e-mail, basta utilizar a expressão:

"=?charset?método?texto codificado?=

Em "charset", é colocada a codificação de caracteres do texto do assunto.

Em "método", é colocada a letra "B" para base64 ou "Q" para quoted-printable.

Em "texto codificado", é colocado o texto codificado do assunto, usando o método e charset definidos.

Veja um exemplo para montar o assunto com o método base64 a partir de um assunto em UTF-8:

$assunto = 'Açúcar possui acento';
$assunto_codificado = sprintf('=?%s?%s?%s?=', 'UTF-8', 'B', base64_encode($assunto));

Para usar o método quoted-printable, é preciso usar a função quoted_printable_encode, disponível a partir do PHP 5.3.0 ou imap_8bit, disponível na extensão IMAP. Este método deixa o conteúdo menor e mais legível, porém, depende da disponibilidade da função. A função base64_encode, por sua vez, está disponível desde o PHP 4. Veja um exemplo de codificação com quoted-printable:

$assunto = 'Açúcar possui acento';
$assunto_codificado = sprintf('=?%s?%s?%s?=', 'UTF-8', 'Q', quoted_printable_encode($assunto));

Depois, basta passar o parâmetro $subject da função mail com o valor codificado.

mail($destinatario, $assunto_codificado, $mensagem, $header)

Codificação do conteúdo

Para enviar o conteúdo do e-mail, também é utilizado um dos métodos de codificação. Porém, o método utilizado é especificado no cabeçalho do e-mail. Para especificar o cabeçalho, basta utilizar as diretivas:

  • Content-Type - para definir o mime-type do conteúdo do e-mail e o charset.
  • Content-Transfer-Encodding - para definir o método de codificação.

Neste caso, o conteúdo precisa de uma quebra de linha a cada 76 caracteres. As funções de codificação quoted-printable já fazem a quebra automática. A função base64_encode precisa de um auxilio da função chunk_split. Veja um exemplo de um e-mail com conteúdo textual enviado com codificação base64:

$conteudo = <<<TXT
Conteúdo do e-mail.
Blá blá blá.
TXT;

$conteudo_codificado = chunk_split(base64_encode($conteudo), 76, "\r\n");

$header = <<<HTTP
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: base64
Content-Disposition: inline
From: {$remetente}
To: {$destinatario}
HTTP;

mail($destinatario, $assunto_codificado, $conteudo_codificado, $header);

Extra

Além do assunto e do conteúdo do e-mail, também é possível codificar o nome do remetente e do destinatário do e-mail. É utilizado o mesmo mecanismo do assunto. Veja um exemplo para codificar o nome do destinatário do e-mail com base64:

$nome = 'Alguém com Acento no Nome';
$email = 'alguem@teste.com';
$destinatario = sprintf('=?%s?%s?%s?= <%s>', 'UTF-8', 'B', base64_encode($nome), $email);

5 comentários

Yuri disse...

Ótimo post.

Para funcionar eu tive que adicionar aos headers isso também:

"MIME-Version: 1.0\r\n"

Gustavo Varella disse...

Resolveu o problema do assunto :))
O e-mail estava com o corpo de texto na codificação correta, mas o assunto vinha errado.
Heheh Muito Obrigado!

Fagner disse...

O corpo da mensagem fica desta forma "Q29udGXDumRvIGRvIGUtbWFpbC4KQmzDoSBibMOhIGJsw6Eu
" ao utilizar esta configuração; funcionou apenas para o assunto.

Rubens Takiguti Ribeiro (autor do blog) disse...

Fagner, certifique-se que passou o cabeçalho do e-mail corretamente, conforme mostrado no exemplo do artigo. Veja a linha:
Content-Transfer-Encoding: base64

Ela diz que o conteúdo do arquivo (que é o texto do e-mail) está em base64.