RBA Cash Rate: 4.35% · 1AUD = 0.67 USD · Inflation: 4.1%  
Leading Digital Marketing Experts | 1300 235 433 | Aggregation Enquires Welcome | Book Appointment
Example Interest Rates: Home Loan Variable: 5.20% (5.24%*) • Home Loan Fixed: 5.48% (6.24%*) • Fixed: 5.48% (6.24%*) • Variable: 5.20% (5.24%*) • Investment IO: 5.78% (6.81%*) • Investment PI: 5.49% (6.32%*)

Determine if an Email is Read Using PHP (and Log Who Read It)

Most web based email software will permit you to determine if an email is read by including a small image into the body of the HTML message. When rendered into an email client a request is made for the image and the server-side fancy work logs the details into a database. The PHP code on this page is designed to emulate the feature just described in a very simple way.

The Result

Following is an example of logs that are recorded when a request for your image is made:

1
1443441793,2015.09.28 23:03:13,13X.XXX.71.83,Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0) like Gecko,marty
2
1443441814,2015.09.28 23:03:34,13X.XXX.71.83,Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0) like Gecko,internoetics
3
1443441821,2015.09.28 23:03:41,13X.XXX.71.83,Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0) like Gecko,flight
4
1443442554,2015.09.28 23:15:54,13X.XXX.71.83,Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.2; WOW64; Trident/7.0; .NET4.0E; .NET4.0C; GWX:RESERVED; Microsoft Outlook 14.0.7157; ms-office; MSOffice 14),anotherperson

The last record was obtained by inserting the image into an outlook email; the others were accessed via a web browser. I've used a simple .htaccess file in the same directory as my code and rewritten the URL referencing the image (as {custom_word}/reademail.jpg). Without the rewrite you should use reademail.php?code={custom_word}.

The last field in the log example above is the custom field custom_word you can use to determine who it was that read an email. Most mass email clients permit you to include a custom field (name, email, id) into the email message and it's intended that you'll use one of those here.

The PHP Code

The following code should be copied into a file called reademail.php.

1
error_reporting(0);
2
Header("Content-Type: image/jpeg");
1
<?php 
2
/*
3
 Determine if an Email is Read Using PHP (and Log Who Read It)
4
 http://www.internoetics.com/2015/11/17/determine-email-read-using-image-log-results/
5
*/
6
 
7
$code = $_GET['code'];
8
$ip = internoetics_get_ip_address();
9
$browser = $_SERVER['HTTP_USER_AGENT'];
10
$code = validate_input($code);
11
determine_read_email_log($ip, $browser, $code);
12
 
13
/*
14
 Function Checks Image Code Input
15
 Should also be written into .htaccess
16
*/
17
 
18
function validate_input($code) {
19
  $return = (preg_match('/^([a-zA-Z-_]+)$/i', $code, $imgmatches)) ? true : false;
20
  if (!$return) $code = 'ERROR INPUT';
21
 return $code;
22
}
23
 
24
/*
25
 Function Gets User IP Address
26
*/
27
 
28
function internoetics_get_ip_address() {
29
 foreach (array('HTTP_CLIENT_IP', 'HTTP_X_FORWARDED_FOR', 'HTTP_X_FORWARDED', 'HTTP_X_CLUSTER_CLIENT_IP', 'HTTP_FORWARDED_FOR', 'HTTP_FORWARDED', 'REMOTE_ADDR') as $key) {
30
     if (array_key_exists($key, $_SERVER) === true) {
31
         foreach (explode(',', $_SERVER[$key]) as $ip) {
32
            if (filter_var($ip, FILTER_VALIDATE_IP) !== false) {
33
            return $ip;
34
          }
35
        }
36
     }
37
  }
38
}
39
 
40
/*
41
 Function Creates Date, Logs Record, and Creates Image
42
 To alter date output: http://php.net/manual/en/function.date.php
43
*/
44
 
45
function determine_read_email_log($ip, $browser, $code, $logfile='log.txt') {
46
 
47
  $time = time();
48
  $day = date('Y.m.d', $time);
49
  $hour = date('H:i:s', $time);
50
 
51
  $fh = fopen($logfile, 'a+');
52
  // $logdata = $time . ',' . $day . ' ' . $hour . ' ' . $ip . ' ' . $browser . ' ' . $code . ' ' . "\r\n";
53
  $logdata = $time . ',' . $day . ' ' . $hour . ',' . $ip . ',' . $browser . ',' . $code . "\r\n";
54
  fwrite($fh, $logdata);
55
  fclose($fh);
56
 
57
  /* Generate Image */
58
  $newimage = ImageCreate(1,1);
59
  $white = imagecolorallocate($newimage,255,255,255);
60
  ImageJPEG($newimage);
61
  ImageDestroy($newimage);
62
}
63
?>

If you plan on rewriting your image URL so it has the .jpg extension you should also include the .htaccess file below. This is a preferred method since it assists the browser or email client in rendering the image as an image rather than gibberish text.

1
RewriteEngine On
2
RewriteRule ^([a-zA-Z-_]+)/reademail.jpg reademail.php?code=$1 [L]

Considerations

  • To validate the 'custom field' input I'm using just alphanumeric text, hyphens, and underscores. We validate this in both the PHP script and the .htaccess file. If you choose to include other characters you'll have to rewrite this. If you were to use an email it may be sensible to hash it so it includes only permitted characters (for example, MD5 will include only [a-fA-F0-9] characters)... or you could just validate the email!
  • To edit the HTML in MS Outlook I use outlookhtmleditor .
Determine if an Email is Read Using PHP (and Log Who Read It)

Outlook HTML Editor (http://outlookhtmleditor.codeplex.com)

  • Rather than just including a pixel-sized image in your email you might consider generating your email (image) signature in the manner described. In addition to logging the read email you can add additional features such as the ability to use specific full-featured image email signatures based on the recipient or your own sender address. You might also consider an action that'll fire off an email 'read receipt'. I've personally used the signature method to automatically generate different email signatures for specific (and known) recipients.
  • If you were to build this funky little function into an actual tool you use you would almost certainly store data in a database. The text file is prone to errors and it was only used for the purpose of the demonstration.
  • This snipped was migrated from Internoetics without alteration (so it's a little old).

Download our 650-page guide on Finance Marketing. We'll show you exactly how we generate Billions in volume for our clients.

  E. Australia Standard Time [ UTC+10, Default ] [ CHECK TO CHANGE ]

  Want to have a chat?
 

Like this article?

Share on Facebook
Share on Twitter
Share on Linkdin
Share on Pinterest

Leave a comment