34

我已经看到像 spypig.com 这样的服务在电子邮件中放置一个小图像并跟踪它何时打开以及从何处打开。他们跟踪城市、国家、IP 地址等。这是如何完成的?

  1. 我们如何知道邮件何时被打开?以及图像是如何生成的?
  2. 如何检测 IP 地址以及如何从中知道位置?
4

4 回答 4

68

基本上,在您的电子邮件的 HTML 正文中,会有一个如下所示的<img>标签:

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

当有人阅读他的邮件并启用图像时,电子邮件客户端将向 , 发送请求tracker.php以加载图像,并将其id=123456作为参数传递。


tracker.php脚本将在您的服务器上,并且在调用时,它将:

  • 检查id参数,
  • 使用它来查找它对应的电子邮件地址 - 在为每个订阅者生成电子邮件时,您将为id每封电子邮件生成不同的电子邮件。
  • 做一些事情——比如记录“电子邮件 123456 已打开”,以及一些附加信息
  • 返回小图的内容;就像一个 1x1 透明的 gif。


The tracker.php script knows from which IP address it's been called -- like any other PHP script :

$ipAddress = $_SERVER['REMOTE_ADDR'];

And, starting from this IP address, you can use a geolocation service to find out from where in the world the email has been opened.
As a couple of examples, you could take a look at MaxMind, or IPInfoDB

As you know that id=123456 corresponds to one specific email address, this allows to find out where each one of your subscribers are.

于 2011-03-27T09:50:47.837 回答
18

1. Place the tracker image at the E-mail

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

Its working is very simple, Once your mail is open, that tracker image sends the request to the server, from that request we can get information by creating the image URL with userID, and also consider as that mail is read by the user.

Note: Don't use display: none; property for hiding your images, it may filter by spam algorithm. And don't place any javascript codes, it also blocks the spam filter

2. On the tracker.php

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

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

3. The ip address is get by the following function.

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. Location:

The location is getting by any geolocation services, you can use open-source GeoLocation finder like nekudo,freegeoip.

for example

<?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'];
?>
于 2016-07-21T04:09:07.083 回答
4

The other answers are great but, since humanity seems convinced that "any tracking is evil tracking" I like to take it a step further by being "invisible" to the user by retaining the .png/.jpg/.gif etc image file extension.

I'm not sure about compatibility with all types of web servers and hosts, but for me it was a quick change to the AddHandler directive I already had in .htaccess, such as:

AddHandler application/x-httpd-lsphp .png 

...to allow processing of PHP code within files with a .png extension.

You might already have an AddHandler line to allow PHP in .htm/.html files; if so, just add the appropriate image file extension to the end of the list.

This is, roughly, my "tracking image" code, file saved as trackimage.png or whatever :

<?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'"; 
  }

Note that if error text, or anything else, is returned by the code before the image, the image will be undisplayable. It might also be worth researching possible security concerns with this that might apply to you case. For example, this.

于 2020-01-24T13:19:50.697 回答
2

关于问题的第一部分,我所做的是从 PHP 文件返回图像。除了返回图像(可以是 1x1 像素透明 png)之外,还将所有信息记录到数据库中。这样,当调用 PHP 文件时,您就知道图像已加载,即电子邮件已被读取。问题是许多现代客户端不会自动加载图像。出于隐私原因,这是不允许您尝试做的那种事情。

关于第二部分,有几个地理位置 Web 服务,您可以在其中提交 IP 并获取地理位置。您可以在返回 1x1 像素图像的 PHP 文件中执行此操作。这是此站点上关于此的一个很好的主题: 地理位置 Web 服务建议

于 2011-03-27T09:47:15.583 回答