Отслеживание электронной почты с помощью PHP и изображения

Я видел такие сервисы, как spypig.com, помещающие небольшое изображение в электронное письмо и отслеживающие, когда оно открывается и откуда. Они отслеживают город, страну, IP-адрес и т. д. Как это делается?

  1. Как мы узнаем, когда открыта почта? И как создается изображение?
  2. Как определяется IP-адрес и как по нему можно узнать местоположение?

person esafwan    schedule 27.03.2011    source источник
comment
И что ты хочешь с этим делать? Многие клиенты электронной почты в любом случае проверяют наличие этих веб-жучков и не отображают их, поэтому вы не можете полагаться на это в серьезном приложении.   -  person martinstoeckli    schedule 27.03.2011
comment
Я настоятельно рекомендую вам добавить фактическое расширение изображения (.jpg,.png) и вернуть фактические заголовки изображения. пример... /o/uuid-email-identifier/good.jpg - сделать динамическим. это то, что я делаю в своем программном обеспечении   -  person Jody Fitzpatrick    schedule 03.04.2018


Ответы (4)


По сути, в теле HTML вашего электронного письма будет тег <img>, который будет выглядеть следующим образом:

<img src="http://www.yoursite.com/tracker.php?id=123456" alt="" />

Когда кто-то читает его почту с включенными изображениями, почтовый клиент отправит запрос tracker.php на загрузку изображения, передав его id=123456 в качестве параметра.


Этот tracker.php скрипт будет на вашем сервере, и при вызове он будет:

  • Проверьте параметр id,
  • Используйте его, чтобы найти, какому адресу электронной почты он соответствует — при создании электронного письма для каждого из ваших подписчиков вы будете генерировать id разных электронных писем.
  • Сделайте что-нибудь -- например, запишите "электронная почта 123456 была открыта" и добавьте дополнительную информацию.
  • вернуть содержимое маленького изображения; как прозрачный gif размером 1x1.


Сценарий tracker.php знает, с какого IP-адреса он был вызван, как и любой другой PHP-скрипт:

$ipAddress = $_SERVER['REMOTE_ADDR'];

И, начиная с этого IP-адреса, вы можете использовать службу геолокации, чтобы узнать, из какой точки мира было открыто письмо.
В качестве нескольких примеров вы можете взглянуть на MaxMind или IPInfoDB

Поскольку вы знаете, что id=123456 соответствует одному конкретному адресу электронной почты, это позволяет узнать, где находится каждый из ваших подписчиков.

person Pascal MARTIN    schedule 27.03.2011
comment
Может я не до конца понял. Я просто хотел понять, почему нам нужно вернуть содержимое маленького изображения. Что произойдет, если у нас будет вот так <img src="http://www.yoursite.com/tracker.php?id=123456" alt="" style="display:none"/>? То есть установить на display:none. Не могли бы вы пролить свет на это? - person Gnanam; 31.12.2012
comment
Я думаю, вы можете не возвращать изображение, но будет некрасиво показывать значок сломанного изображения. И я не рекомендую вам использовать display:none в электронной почте, так как фильтры спама в настоящее время довольно строгие, и использование этого может привести к тому, что ваше письмо сразу попадет в папку со спамом или, возможно, даже отклонит его, потому что фильтр будет думать, что вы сокрытие вредоносного текста или кода. Даже использование белого текста на белом фоне может вызвать это действие. - person aleation; 23.01.2013
comment
как вернуть image из tracker.php? - person Mohammad Faisal; 20.02.2013
comment
Почему бы не использовать другое изображение в содержимом электронной почты, которое на самом деле предназначено для отображения, например, логотип, изображение заголовка и т. д.? - person neridaj; 03.05.2014
comment
Может ли электронная почта PHP действительно получить адрес электронной почты получателя? - person TheBlackBenzKid; 16.06.2014
comment
Чтобы скрыть изображение, кажется, самый простой способ: <img src="http://www.yoursite.com/tracker.php?id=123456" alt="" width="1" height="1" border="0"> - person Guillaume Blanco; 17.09.2014
comment
это не будет работать, когда пользователь использует приложение для открытия электронной почты (например, почтовое приложение для iPhone) - person Makio; 18.06.2015
comment
Кроме того, если кто-то читает письмо в автономном режиме, этот метод не сработает. Я прав? - person Niladri Banerjee - Uttarpara; 04.09.2015
comment
$ipAddress = $_SERVER['REMOTE_ADDR']; не возвращает правильный IP-адрес, он возвращает 66.249.84.194 IP-адрес, принадлежащий Google, любой может помочь мне решить эту проблему. - person chirag satapara; 10.11.2016
comment
@Pascal MARTIN Вы предоставляете идентификатор для каждого письма, и каждое письмо может быть просмотрено отправителем или получателем. Как узнать, какой пользователь открыл письмо? - person ; 12.06.2017
comment
Я обнаружил, что этот метод не работает в настольном клиенте электронной почты Outlook. Есть ли какая-либо причина/обходной путь для этого? - person CGriffin; 14.06.2017

<сильный>1. Разместите изображение трекера на E-mail

<img src="http://www.yoursite.com/tracker.php?eid=123456&uid=123" alt="" width="1px" height="1px">

Его работа очень проста. Как только ваша почта открыта, это изображение трекера отправляет запрос на сервер, из этого запроса мы можем получить информацию, создав URL-адрес изображения с идентификатором пользователя, а также рассмотреть, как эта почта прочитана пользователем.

Примечание. Не используйте display: none; свойство для скрытия ваших изображений, оно может фильтровать по алгоритму спама. И не размещайте коды javascript, это также блокирует спам-фильтр.

<сильный>2. В файле tracker.php

<?php
header("Content-Type: image/jpeg"); // it will return image 
readfile("img.jpg");

dbfunction(); // place your db code
?>

<сильный>3. IP-адрес получается с помощью следующей функции.

function get_client_ip() {
    $ipaddress = '';
    if (isset($_SERVER['HTTP_CLIENT_IP']))
        $ipaddress = $_SERVER['HTTP_CLIENT_IP'];
    else if(isset($_SERVER['HTTP_X_FORWARDED_FOR']))
        $ipaddress = $_SERVER['HTTP_X_FORWARDED_FOR'];
    else if(isset($_SERVER['HTTP_X_FORWARDED']))
        $ipaddress = $_SERVER['HTTP_X_FORWARDED'];
    else if(isset($_SERVER['HTTP_FORWARDED_FOR']))
        $ipaddress = $_SERVER['HTTP_FORWARDED_FOR'];
    else if(isset($_SERVER['HTTP_FORWARDED']))
        $ipaddress = $_SERVER['HTTP_FORWARDED'];
    else if(isset($_SERVER['REMOTE_ADDR']))
        $ipaddress = $_SERVER['REMOTE_ADDR'];
    else
        $ipaddress = 'UNKNOWN';
    return $ipaddress;
}
$PublicIP = get_client_ip();

<сильный>4. Местонахождение:

Местоположение определяется любыми службами геолокации, вы можете использовать средство поиска GeoLocation с открытым исходным кодом, например nekudo,freegeoip.

Например

<?php
$json  = file_get_contents("http://ipinfo.io/$PublicIP/geo");
$json  =  json_decode($json ,true);
$country =  $json['country_name'];
$region= $json['region_name'];
$city = $json['city'];
?>
person Naveen DA    schedule 21.07.2016
comment
Может я ошибаюсь, но ипехо-часть должна была бы вызываться на сервер, чтобы вы получили только IP-адрес сервера? - person andeersg; 21.07.2016

Другие ответы замечательны, но, поскольку человечество, кажется, убеждено, что «любое отслеживание — это злое отслеживание», я хотел бы сделать еще один шаг, будучи «невидимым» для пользователя, сохраняя .png/.jpg/.gif расширение файла изображения.

Я не уверен в совместимости со всеми типами веб-серверов и хостов, но для меня это был быстрый переход на AddHandler, который у меня уже был в .htaccess, например:

AddHandler application/x-httpd-lsphp .png 

...чтобы разрешить обработку PHP-кода в файлах с расширением .png.

Возможно, у вас уже есть строка AddHandler, разрешающая PHP в файлах .htm/.html; если это так, просто добавьте соответствующее расширение файла изображения в конец списка.

Это, грубо говоря, мой код «отслеживающего изображения», файл, сохраненный как trackimage.png или что-то еще:

<?php //silently log user and return image
  $ip=$_SERVER['REMOTE_ADDR'];
  $uri=tidy($_SERVER['SCRIPT_URI']);
  $querystring=tidy($_SERVER['QUERY_STRING']);
  $useragent=tidy($_SERVER['HTTP_USER_AGENT']);

  $json  = file_get_contents("https://ipinfo.io/".$ip."/geo");
  if(($json<>'')&&(strpos($json,"error")===false)){ extract(json_decode($json ,true)); }
  $country=tidy($country);
  $prov=tidy($region);
  $city=tidy($city);
  list($lat,$lon)=explode(',',$loc);
  $lat=tidy($lat);
  $lon=tidy($lon);

  $sql = "INSERT INTO img_track_table set ip='$ip', useragent=$useragent, uri=$uri, " 
    ."querystring=$querystring, country=$country, prov=$prov, city=$city, lat=$lat, lon=$lon;";

  require 'connect.php'; $conn=new mysqli($servername, $username, $password, $dbname);
  if ($conn->connect_error) { /* couldn't connect, but do nothing about it */ } 
  }else{  //run insert query
    if(!$conn->query($sql)) { /* query error, but do nothing about it */ }
    $conn->close();
  }

  //return image
  header("Content-Type: image/png"); 
  readfile("myActualImageFile.png");

  function tidy($str){ //remove quotes and backslashes from string
    if(is_null($str)||($str=="")){return "null";}
    $str=trim(str_replace('\\','',str_replace("'","",str_replace('"',"",$str))));
    if(is_numeric($str)){return $str;}
    return "'$str'"; 
  }

Обратите внимание, что если текст ошибки или что-либо еще возвращается кодом перед изображением, изображение не будет отображаться. Возможно, также стоит изучить возможные проблемы безопасности, которые могут относиться к вашему случаю. Например, это .

person ashleedawg    schedule 24.01.2020
comment
Спасибо, очень полезно. AddHandler не сделал эту работу за меня, но AddType application/x-httpd-php .php .png - person Nick Oetjen; 07.05.2020

Что касается первой части вопроса, я вернул изображение из файла PHP. Помимо возврата изображения (это может быть прозрачный png размером 1x1 пиксель), вся информация записывается в базу данных. Таким образом, когда вызывается файл PHP, вы знаете, что изображение было загружено, т.е. электронное письмо было прочитано. Проблема в том, что многие современные клиенты не загружают изображения автоматически. Это делается для того, чтобы не допустить того, что вы пытаетесь сделать, по соображениям конфиденциальности.

Что касается второй части, есть несколько веб-сервисов геолокации, где вы отправляете IP-адрес и получаете геолокацию. Вы можете сделать это в файле PHP, который возвращает изображение размером 1x1 пиксель. Вот хорошая тема на этом сайте: рекомендации веб-службы геолокации

person Elad Lachmi    schedule 27.03.2011