PHP: Executar script ao carregar imagem embutida em e-mail

Essa dica é útil para quem quer saber se o e-mail que você enviou foi lido. у гэтым выпадку, inserimos uma imagem no corpo da mensagem de e-mail que, quando for aberta, irá disparar um script em servidor remoto.

Прэзентацыя

Essa técnica é muito utilizada em e-mail marketing, de modo que o remetente envia centenas ou milhares de e-mails para destinatários de sua mala-direta visando atingir um público-alvo, e quer saber o feedback (retorno) da campanha, іншымі словамі, se o destinatário leu ou não a propaganda embutida no e-mail.

Como funciona?
O raciocínio é simples, basta você colocar no corpo do e-mail (conteúdo) uma Tag HTML de IMAGEM, com o atributo SRC apontando, não diretamente para uma imagem como normalmente é feito, mas para um script personalizado hospedado em um servidor remoto, onde você consegue executar alguma rotina e, aí sim, renderizar uma imagem (ці не). Complicou? Que nada, veja o exemplo:

1
2
3
<?PHP
  <img src="http://seuservidor.com/script.php?email=pessoa@gmail.com&destinatario=Taylor+Lopes" />
?>

Para que serve?
Note que quando o usuário abrir o e-mail, automaticamente será carregada a suposta imagem, que na verdade é um script. Isso é útil para fazer estatística de e-mail que foram visualizados, inclusive determinando QUEM abriu (destinatário) e QUANDO (data/hora). ясна, isso não é nenhumaadivinhação”, sabemos quem abriu o e-mail, pois atrelamos esses dados na URL da imagem no momento de enviá-lo.

Inconveniente
Para isso funcionar, o destinatário necessariamente precisa ter configurado para que seu e-mail seja lido no formato HTML, embora isso já seja um padrão aceito pela maioria do usuários. Na pior das hipóteses, o provedor de e-mail vai exibir uma mensagem dizendo que bloqueou as imagens, mas perguntando se o usuário quer exibir, o que também normalmente é aceito, já que poucas pessoas veem malícia nessa prática. No caso do Google, aparece uma mensagem em forma de link, так:

1
2
3
...
  Imagens não exibidas - Exibir imagens abaixo - Sempre exibir imagens de suport@email.microsoft.з
...

Vou comentar duas formas de fazer isto; ambas funcionam igualmente, sendo que a segunda é mais discreta por não exibir dados na URL, embora exija mais recurso de armazenamento. Vamos lá!

рашэнне 1

На практыцы
Você precisa de apenas dois códigos PHP:
(1) um para enviar o e-mail no formato HTML com a tag IMG embutida
(2) e outro para captar as informações no momento que o e-mail for aberto

PASSO 1Enviar e-mail

sendmail.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<?PHP
  // *** Seu e-mail (e-mail de quem envia)
  $remetente_nome     = 'Anônimo';
  $remetente_email    = 'anonimo@email.com';
 
  // *** Seu alvo (e-mail para quem envia) 
  $destinatario_nome  = 'Mario Bross';
  $destinatario_email = 'mariobross@email.com';
 
  // *** Assunto e corpo da mensagem
  $assunto      = 'Testando a execução de script ao carregar imagem.';
  $mensagem     = '
    <html lang="pt-br">
      <галава>
        <meta charset="iso-8859-1" />    
        <назву>'.$assunto.'</назву>
      </галава>
      <цела>
        <img src="http://seuservidor.com/script.php?email='.urlencode($destinatario_email).'&destinatario='.urlencode($destinatario_nome).'&assunto='.urlencode($assunto).'" />
      </цела>
    </HTML>';
 
  // Cabeçalho informando que o conteúdo é do tipo HTML (para poder ler a tag IMG e executar o script)
  $header       = "MIME-Version: 1.0\n"; 
  $header      .= "Content-type: text/html; charset=iso-8859-1\n"; 
  $header      .= "From: ".(empty($remetente_nome) ? $remetente_email : '"'.$remetente_nome.'" <'.$remetente_email.'>')."\n";
 
  // Envia o e-mail
  $email = empty($destinatario_nome) ? $destinatario_email : '"'.$destinatario_nome.'" <'.$destinatario_email.'>';
  mail($email, $assunto, $mensagem, $header);
?>

PASSO 2Captar informações

добра, você notou que ao ler a TAG IMG será feita uma chamada para o arquivoscript.php”, некаторыя? Então agora temos que criá-lo para pegar as informações e armazená-las, de preferência num banco de dados.

Criando TABELA
Já que precisamos persistir os dados do destinatário que abriu o e-mail, podemos criar uma tabela como esta abaixo. Veja o campo `datahora_visualizado`, que refere-se última data e hora em que o usuário visualizou o e-mail e o campo `contador`, que irá registrar a quantidade de vezes que o e-mail foi visto.

maladireta.sql
1
2
3
4
5
6
7
8
9
CREATE TABLE  `maladireta` (
  `id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY ,
  `email` VARCHAR( 100 ),
  `destinatario` VARCHAR( 100 ),
  `assunto` VARCHAR( 200 ),
  `datahora_envio` DATETIME NOT NULL,
  `datahora_visualizado` DATETIME,
  `contador` INT DEFAULT 0
) ENGINE = MYISAM ;

Script para captar informações e exibir uma imagem
Аздабленне, vamos pegar dados como e-mail do destinatário, nome do destinatário, assunto da mensagem e a data/hora de quem abriu o e-mail, armazenando tudo no banco de dados que criamos, para caso futuramente precisarmos fazer uma estatística. No final do script, vamos de fato criar e exibir uma imagem, só para não ficar uma TAG IMG com crise existencial :), mas se não quiser exibir nada, crie pelo menos uma imagem em branco (1×1 pixel) para não ficar com a Tag quebrada.

script.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<?PHP
  // Inicializa e trata os parâmetros de entrada
  $destinatario_email = абрэзаць(strip_tags(addslashes($_REQUEST['email'])));
  $destinatario_nome  = абрэзаць(strip_tags(addslashes($_REQUEST['destinatario'])));
  $assunto            = абрэзаць(strip_tags(addslashes($_REQUEST['assunto'])));       
 
  // Faz a conexão com o banco de dados (AJUSTE SUA CONEXÃO)
  $спасылка = mysql_connect('mysql.seuservidor.com', 'root', '***suasenha***') or die('Falhou ao conectar ao banco de dados.'); 
  mysql_select_db('seubancodedados') or die('Falhou ao selecionar o banco de dados');
 
  // Monta a SQL e insere no banco de dados, caso email ainda não exista, ou atualiza contador se existir
  $sql = 'SELECT email FROM maladireta WHERE email="'.$destinatario_email.'"';
  $res = mysql_query($sql);
  калі (mysql_num_rows($res) > 0) {
    $sql = 'UPDATE maladireta SET datahora_visualizado="'.date('Y-m-d H:Я:s').'", contador=contador+1 WHERE email="'.$destinatario_email.'"';    
  }
  else {
    $sql = 'INSERT INTO maladireta VALUES (null, "'.$destinatario_email.'", "'.$destinatario_nome.'", "'.$assunto.'", "'.date('Y-m-d H:Я:s').'", null, 0)';
  }
  mysql_query($sql);
 
  // Cria e exibe a imagem embutida ao email
  header("Content-type: image/png");
  $img = imagecreatefrompng("imagem.png");
  imagepng($img);
  imagedestroy($img);
?>

заўвагу: Não esqueça de colocar junto ao script uma imagem, няма ні аднаго выпадку,, chamei deimagem.png”. Essa imagem irá aparecer no corpo do e-mail do destinatário, e é onde o pessoal de marketing coloca a propaganda, mas pode ser um logotipo ou o que você desejar. O Script foi testado e funciona!

рашэнне 2

Outra possibilidade
Conforme sugerido pelo colega Leandro, uma opção mais discreta eseguraseria, ao invés de estampar na URL da imagem um monte de dados como email, assunto, і г.д., criar um HASH no momento do envio do e-mail vinculando-o a esses dados, e enviar na URL somente o HASH. Quando o destinatário abrir o email e carregar a imagem, irá trafegar apenas o HASH que então será capturado pelo nosso script e vinculado aos dados que queremos saber.

Criando a tabela de hash e vínculo de dados
Vamos criar a tabela que será populada toda vez que enviarmos um e-mail. Note o campo `hash`, que servirá como vínculo do e-mail que foi enviado e os dados do destinatário que ficaram armazenados na tabela.

maladireta.sql
1
2
3
4
5
6
7
8
9
10
CREATE TABLE  `maladireta` (
  `id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY ,
  `hash` VARCHAR( 50 ) NOT NULL,
  `email` VARCHAR( 100 ),
  `destinatario` VARCHAR( 100 ),
  `assunto` VARCHAR( 200 ),
  `datahora_envio` DATETIME NOT NULL,
  `datahora_visualizado` DATETIME,
  `contador` INT DEFAULT 0
) ENGINE = MYISAM

Enviando o e-mail

sendmail.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
<?PHP
  // *** Seu e-mail (e-mail de quem envia)
  $remetente_nome     = 'Anônimo';
  $remetente_email    = 'anonimo@email.com';
 
  // *** Seu alvo (e-mail para quem envia) 
  $destinatario_nome  = 'Mario Bross';
  $destinatario_email = 'mariobross@email.com';
 
  // *** Outros dados a persistir e HASH (identificador)
  $hash               = md5(ранцье());
  $assunto            = 'Testando a execução de script ao carregar imagem.';
  $datahora_envio     = date('Y-m-d H:Я:s');
 
  // Faz a conexão com o banco de dados
  $спасылка = mysql_connect('mysql.seuservidor.com', 'root', '***suasenha***') or die('Falhou ao conectar ao banco de dados.'); 
  mysql_select_db('seubancodedados') or die('Falhou ao selecionar o banco de dados');  
 
  // Monta a SQL e insere no banco de dados
  $sql = 'INSERT INTO maladireta VALUES (null, "'.$hash.'", "'.$destinatario_email.'", "'.$destinatario_nome.'", "'.$assunto.'", "'.$datahora_envio.'", null, 0)';
  mysql_query($sql);
 
  // *** Mensagem a ser enviada
  $mensagem     = '
    <html lang="pt-br">
      <галава>
        <meta charset="iso-8859-1" />    
        <назву>'.$assunto.'</назву>
      </галава>
      <цела>
        <img src="http://seuservidor.com/script.php?hash='.$hash.'" />
      </цела>
    </HTML>';
 
  // Cabeçalho informando que o conteúdo é do tipo HTML (para poder ler a tag IMG e executar o script)
  $header       = "MIME-Version: 1.0\n"; 
  $header      .= "Content-type: text/html; charset=iso-8859-1\n"; 
  $header      .= "From: ".(empty($remetente_nome) ? $remetente_email : '"'.$remetente_nome.'" <'.$remetente_email.'>')."\n";
 
  // Envia o e-mail
  $email = empty($destinatario_nome) ? $destinatario_email : '"'.$destinatario_nome.'" <'.$destinatario_email.'>';
  mail($email, $assunto, $mensagem, $header);
?>

Perceba que, у гэтым выпадку, a URL (SRC) da imagem fica apenas com o HASH.

Contabilizando e-mail visualizado

script.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?PHP
  // Captura o HASH do e-mail visualizado
  $hash = абрэзаць(strip_tags(addslashes($_REQUEST['hash'])));
 
  // Faz a conexão com o banco de dados
  $спасылка = mysql_connect('mysql.seuservidor.com', 'root', '***suasenha***') or die('Falhou ao conectar ao banco de dados.'); 
  mysql_select_db('seubancodedados') or die('Falhou ao selecionar o banco de dados');
 
  // Monta a SQL e atualiza data de visualização do email e contador no banco de dados
  $sql = 'SELECT hash FROM maladireta WHERE hash="'.$hash.'"';
  $res = mysql_query($sql);
  калі (mysql_num_rows($res) > 0) {
    $sql = 'UPDATE maladireta SET datahora_visualizado="'.date('Y-m-d H:Я:s').'", contador=contador+1 WHERE hash="'.$hash.'"';
    mysql_query($sql);
  }
 
  // Cria e exibe a imagem embutida ao email
  header("Content-type: image/png");
  $img = imagecreatefrompng("imagem.png");
  imagepng($img);
  imagedestroy($img);
?>

ах, se você quiser consultar os e-mails que foram visualizados a partir de uma data, poderia fazer um script com uma SQL tipo essa que, няма ні аднаго выпадку,, busca todos os registros recentes de e-mail vistos a partir de 27 студзень 2013. Fica a dica

1
2
3
4
5
6
7
8
 
  SELECT * 
  FROM 
      `maladireta` 
  WHERE 
      contador > 0 AND 
      DATE(datahora_visualizado) >= DATE("2013-01-27")
;
Усяго доступы: 34925

8 водгукі “PHP: Executar script ao carregar imagem embutida em e-mail

  1. Leandro Chaves сказаў:

    Тэйлар,
    Não é uma boa prática colocar o email do usuário no link da imagem. O ideal é inserir os dados no banco na hora do envio e colocar um hash ou o id da tabela no link, para assim identificar quem abriu o e-mail.

    • Oi Leandro, obrigado pelo comentário. Isso é discutível. Pensando em Segurança da Informação você tem razão, mas na prática seria certo preciosismo, pois o link de e-mail (imagem) que você considera importante proteger estará disponível apenas na caixa de entrada do próprio destinatário. É o mesmo que esconder algo de mim que já sei! акрамя таго, você teria que manter no seu banco uma outra tabela com os milhares de registros da sua mala-direta, mesmo sem saber se os e-mails ali contidos são válidos. Aí se você quisesseenchugarseu banco, não poderia, pois por uma questão de integridade referencial entre as tabelas, seria obrigado a manter os registros, sob pena de nunca saber quem abriu o e-mail. Mas já que estamos falando de segurança, para evitar ter o e-mail interceptado por um Wireshark da vida, o que poderia ser feito é usar SSL (https) tanto no envio do e-mail, quanto no link da imagem. Mas gostei da sua proposta, vou publicar uma solução assim, кошт!

  2. Ала ,
    Estou querendo pegar o IP da pessoa que leu a mensagem , entretanto se for um cliente do hotmail por exemplo ele pega um IP com faixa de dominio nos EUA. Daí não me ajuda muito . Como faço para pegar o IP real da maquina dele ?

  3. Régis сказаў:

    Estranho As vezes funciona e as vezes não funciona usando o Chrome, Opera e Fire Fox no gmail e hotmaillimpo o cache e cookies, mas as vezes não faz a gravação no BD se o email foi aberto ou não !!

  4. diego сказаў:

    Galera..tenho um script de cadastro com nome..emailcpfrgqueria que depois que usuario cadastrar tudo e enviasse pro meu banco de dadosretorna algo pro email dele automatico..tipo
    EXEMPLO:”informações cadastrada com sucesso..aguarde nosso contato

    Teria como??

    • Opa, como disse no Post: “Para isso funcionar, o destinatário necessariamente precisa ter configurado para que seu e-mail seja lido no formato HTML”. Por padrão o HTML é renderizado, mas mesmo o Gmail se mudar a renderização para TEXTO, daí não vai funcionar, pois ele vai simplesmente exibir as TAGs HTML como texto ao invés de renderizá-las.

пакінуць каментар

Ваш электронны адрас не будзе апублікаваны. Абавязковыя для запаўнення палі пазначаныя *