quinta-feira, 22 de março de 2012

Enviando email no PHP com a class Mail do Pear

Hoje quero apenas documentar um exemplo de utilização da classe Mail do PEAR para envio de emails em formato HTML com imagem anexada e associada no HTML.
Já havia trabalhado antes com esta biblioteca, mas eu não enviava emails em HTML e muito menos com imagem associada.
A primeira motivação para documentar este exemplo foi porque não encontrei bons exemplos da utilização desta biblioteca em sites nacionais. Eu queria ter encontrado em sites nacionais para poder entender como trabalhar com texto com acentuação.

Para poder executar o código de exemplo certifique-se de instalar as bibliotecas Mail e Mail_mime do PEAR. (Não vou explicar aqui como usar o PEAR nem como instalar nem como baixar as bibliotecas dele).

O conceito chave aqui para enviar email com conteúdo HTML e com acentuação está relacionado com o encoding e charset do texto.
Não vou explicar este conceito aqui pois não é o intuito do documento. Mas basicamente, encoding é a representação interna dos dados e o charset é o conjunto de caracteres suportado.
A idéia é que se representarmos os dados com UTF-8 (usando o encoding UTF-8), teremos um charset bem maior do que usando a codificação ASCII.

Quando não utilizamos a codificação correta o que acontece é que acabam aparecendo caracteres especiais no meio do texto
certa vez um cliente chamou isso de "caracteres mastigados" ahhahahah...

Para resolver este problema, o bloco de código abaixo foi quem ajudou:


$enc = 'utf-8';
$mime = new Mail_mime(array(
'eol' => "\n",
'text_encoding' => $enc,
'html_encoding' => $enc,
'html_charset' => $enc,
'text_charset' => $enc
));


Bom, mas e para enviar o email como HTML? A saída está em usar a própria classe Mail_mime.
Esta classe fornece os métodos setTXTBody e setHTMLBody conforme o exemplo de utilização abaixo:


$mime->setTXTBody($text);
$mime->setHTMLBody($html);


Usando os métodos acima, basta criar um texto (por exemplo usando a variável $html) com conteúdo html mesmo, ou seja, abrir as tags e marcar o texto necessário.
Mas uma das coisas que achei interessante em enviar um email com conteúdo HTML foi utilizar imagens no HTML. Como associar um arquivo de imagem se você não sabe se a imagem existe no computador do cliente? Outra questão é que o HTML é carregado no client e a página não é acessada de um servidor meu! Então a idéia é anexar a imagem no email e referenciá-la dentro do HTML.


A imagem pode ser associada através do seguinte código:

$mime->addHTMLImage("arquivo.png", "application/octet-stream", "imagem", true, "minhaimagem");


Onde o primeiro argumento é o nome do arquivo no seu servidor, o segundo argumento é o mime-type da imagem, o terceiro é o nome do arquivo, o quarto indica se o nome "imagem" é um nome de arquivo ou não e o último parâmetro é um código para usar como referência no seu HTML.
Veja abaixo um exemplo de referência no HTML para esta imagem que foi anexada:





Bom, agora segue o código completo do exemplo:



require_once ("Mail.php");
require_once ("Mail/mime.php");

// aqui sao informados os dados do cabeçalho do SMTP
// temos 3 parametros: From, To e Subject onde
// From é o email do remetente, To é o destinatário
// e Subject é o assunto do email
$headers =
array(
'From' => 'meuemail@yahoo.com.br',
'To' => $email,
'Subject' => "bem vindo ao mundo do php"
);

// aqui temos os dados de autenticação da conta de email
// hoje a maioria dos servidores de email trabalham com
// autenticação via SMTP. Antigamente, muitos servidores
// famosos de email não possuiam autenticação, o que tornava
// fácil mandar email como se estivesse usando uma conta alheia.
$params =
array(
'auth' => true,
'host' => 'smtp.mail.yahoo.com.br',
'username' => 'meuemail@yahoo.com.br',
'password' => 'foobar'
);

// criamos nossa mensagem em formato html
$html = "



Olá caro programalhão! vamos programar em php hoje!



";

// e criamos a mensagem em formato txt
$text = "Olá caro programalhão! vamos programar em php hoje!";

// agora vamos mandar o email de uma vez
$enc = 'utf-8';

// para enviar um texto em português com acentuação, é sempre bom usar o encoding utf-8
$mime = new Mail_mime(array(
'eol' => "\n",
'text_encoding' => $enc,
'html_encoding' => $enc,
'html_charset' => $enc,
'text_charset' => $enc
));

// definições para o conteúdo HTML
$mime->setTXTBody($text);
$mime->setHTMLBody($html);

// aqui está uma parte muito interessante que é onde anexamos uma imagem para ser referenciada na mensagem
// através do img src="cid:minhaimagem" - o tal cid é o código definido como último parametro do método addHTMLImage
$mime->addHTMLImage("arquivo.png", "application/octet-stream", "imagem", true, "minhaimagem");
$body = $mime->get();
$headers = $mime->headers($headers);

// enviando o email
$mail = Mail::factory('smtp', $params);
$result = $mail->send( $email, $headers, $body );

// verificando erros
if (PEAR::IsError($result))
{
log_fail("ERRO ao tentar enviar o email {$email} (" . $result->getMessage(). ")");
}


Referências:
http://pear.php.net/package/Mail
http://pear.php.net/package/Mail_Mime
http://en.wikipedia.org/wiki/UTF-8
http://en.wikipedia.org/wiki/Unicode
http://kore-nordmann.de/blog/0082_charset_versus_encoding.html

4 comentários:

  1. Porém o campo Assunto continua com acentuação incorreta. Sabes como ajustar?

    ResponderExcluir
  2. Jorge, realmente o assunto continua sem acentuação. Vou pesquisar no final de semana. Caso encontre a solução primeiro, fique a vontade para postar o comentário aqui no blog.

    ResponderExcluir
  3. Excelente tutorial. obrigado!

    Para resolver o problema da acentuação no assunto, eu concatenei o texto entre '=??=' e modifiquei a codificação da variável que está armazenada o assunto:

    $assunto= "=?UTF-8?B?".base64_encode($assunto)."?=";

    ResponderExcluir