PHP电子邮件追踪是如何开发制作的
当前位置:点晴教程→知识管理交流
→『 技术文档交流 』
应用场景 找工作、发送推广邮件等,发信时想知道对方是否已经看过自己的求职或推广信。网站www.spypig.com可以实现在收信人每次查看你的邮件时发送Email通知你邮件已经被查看过了,并记录查看的次数。使用过程中发现,它的实现原理还很简单,所以就用PHP照着葫芦画瓢自己写了个。 概述 当你想知道自己发送的邮件是否被收信人查看过时,使用电子邮件追踪系统(Email Tracking System)就可以帮助你。 使用方法 打开链接电子邮件追踪系统,输入Email地址和标题,选择接收通知的次数,然后激活获取Tracking Image,在一分钟内将其复制到你的Email邮件正文中,再正常发送邮件就行了。
实现原理 由于<img />标签的src属性会主动引入外部文件,所以将调用“tracker程序”(此程序会正常输出一张图片)的URL作为src的值,并将此<img />放入邮件正文中与之一起发送出去。这样,每当收信人打开该邮件显示该<img />时,都会调用“tracker程序”,这时“tracker程序”会发送email通知你。而邮件也必须是HTML格式的才行。 程序说明 程序共有四部分:
代码 创建表的SQL: email_tracker SQL CREATE TABLE `email_tracker` ( `unique_id` varchar(50) NOT NULL, `email` varchar(100) default NULL, `title` varchar(100) default NULL, `number` tinyint(4) default '3', `times` tinyint(4) default '-1', `ip` varchar(16) default NULL, `sent_time` int(11) default '0', PRIMARY KEY (`unique_id`), UNIQUE KEY `unique_id` (`unique_id`) ) ENGINE=MyISAM; tracker.php接收参数产生一个新的Email Tracker: tracker.php $db = get_db(); $ip = $_SERVER['REMOTE_ADDR']?$_SERVER['REMOTE_ADDR']:'127.0.0.1'; //获取用户IP $unique_id = get_unique_id($ip); // 产生一个唯一ID $number = intval($_POST['number']); $email = trim($_POST['email']); $title = trim($_POST['title']); $sent_time = time(); // 作为发送邮件的时间 $db->query("INSERT INTO `email_tracker` (unique_id, email, title, number, ip, sent_time) VALUES ('$unique_id', '$email', '$title', $number, '$ip', '$sent_time')"); 用于产生唯一ID的get_unique_id函数: get_unique_id function current_microsecond() { list($usec, $sec) = explode(" ",microtime()); return $sec.substr($usec, 2); } // 获取随机数 function random() { $tmp = rand(0,1)?'-':''; return $tmp.rand(1000, 9999).rand(1000, 9999).rand(1000, 9999).rand(100, 999).rand(100, 999); } // 产生一个伪GUID // 三段 : 一段是地址 一段是微秒 一段是随机数 function get_unique_id($ip) { $raw = strtoupper(md5($ip.'-'.current_microsecond().'-'.random())); return substr($raw,0,8).'-'.substr($raw,8,4).'-'.substr($raw,12,4).'-'.substr($raw,16,4).'-'.substr($raw,20); } blank.php由邮件正文中Tracking Image调用,发送Email通知用户邮件已阅,并生成一个图片。 blank.php if(!($unique_id = trim($_SERVER['QUERY_STRING']))) exit_with_image_blank(); $db = get_db(); $tracker = $db->fetch_one("SELECT * FROM `email_tracker` WHERE unique_id='$unique_id'"); // 记录不存在,或Tracking已经结束 if(empty($tracker) && $tracker['times'] >= $tracker['number']) { // 输出一个空白图片并退出 exit_with_image_blank(); } // 邮件发送时到现在经过的时间 $time_elapsed = time() - $tracker['sent_time']; // 不到一分钟 if($time_elapsed < 60) { if($tracker['times'] < 0) { // 还未激活Email Tracker $db->query("UPDATE `email_tracker` SET times=0 WHERE unique_id='$unique_id'"); } exit_with_image_blank(); } // 一分钟之后,times<0表示Email Tracker未激活 if($tracker['times'] < 0) { $one_minute_ago = time() - 60; // 删除所有经过一分钟还未激活的Email Tracker $db->query("DELETE FROM `email_tracker` WHERE times < 0 && sent_time < $one_minute_ago");//unique_id='$unique_id' exit_with_image_blank(); } // 获取收信人IP $rcpt_ip = $_SERVER['REMOTE_ADDR']?$_SERVER['REMOTE_ADDR']:'127.0.0.1'; if($rcpt_ip == $tracker['ip']) { //与用户IP相同,也许是用户自己打开了Email $tracker['times']++; } else { // 是收信人打开了Email, 查阅次数增加一次 $tracker['times']++; } $db->query("UPDATE `email_tracker` SET times=$tracker[times] WHERE unique_id='$unique_id'"); if($tracker['times'] >= $tracker['number']) { // Tracking已经结束, 删除记录 $db->query("DELETE FROM `email_tracker` WHERE unique_id='$unique_id'"); } // 发送Email send_mail('mailtracker0@gmail.com', $tracker['email'], array( 'subject' =>'Your email "'.$tracker['title'].'" has been read!', 'body' =>notify_content($tracker, $rcpt_ip, $time_elapsed), 'headers' =>"MIME-Version: 1.0;\r\nContent-type:text/html; charset=\"utf-8\";\r\n", 'host' =>'smtp.gmail.com', 'ssl' =>true, 'port' =>465, 'auth' =>true, 'user' =>'mailtracker0', 'pass' =>'**********' )); // 输出一个空白图片并退出 exit_with_image_blank(); send_mail函数用于发送通知邮件: send_mail /* * 参数: * from required 发信人email * recipients required 收信人email地址,如果有多个email则以','分隔或传递数组 * params optional 其它可选参数组成的数组 * ----subject 邮件主题 * ----body 邮件正文 * ----headers * ----host 用于发邮件的SMTP主机 * ----port 端口 * ----timeout 超时时间 * ----ssl 是SSL加密,默认为false * ----auth 是否要身份验证,默认为false * ----user 用于身份验证的用户名 * ----pass 用于身份验证的密码 **/ function send_mail($from, $recipients, $params = array()) { if(empty($from) || empty($recipients) || !is_array($params)) return 'params error.'; define('CRLF', "\r\n"); $port = 25; $host = 'localhost'; $timeout = 10; $auth = false; $ssl = false; $subject = 'untitled'; foreach ($params AS $key => $value) { $$key = $value; } if(!is_array($recipients)) $recipients = explode(',', trim($recipients)); if(!is_array($headers)) $headers = explode(CRLF, trim($headers)); if(!is_string($body)) $body = ''; $body = str_replace(CRLF . '.', CRLF . '..', $body{0} == '.' ? '.'.$body : $body); // 连接SMTP服务器 $connection = fsockopen($ssl?'ssl://'.$host:$host, $port, $errno, $errstr, $timeout); if(!is_resource($connection)) { return 'Failed to connect to server: '.$errstr; } while($line = @fgets($connection, 1024)) if($line{3} == ' ') break; // 保存命令 $datas = array(); if($auth === true) { // 需要验证身份 $datas[] = array('EHLO '.$host.CRLF, '250', 'EHLO command failed, output: '); $datas[] = array('AUTH LOGIN'.CRLF , '334', 'AUTH command failed, output: '); $datas[] = array(base64_encode($user).CRLF, '334', 'AUTH command failed, output: '); $datas[] = array(base64_encode($pass).CRLF, '235', 'AUTH command failed, output: '); } else { $datas[] = array('HELO '.$host.CRLF, '250', 'HELO command failed, output: '); } // 设置发信人 $datas[] = array('MAIL FROM: <'.$from.'>'.CRLF, '250', 'MAIL FROM error, output: '); // 设置收信人 foreach($recipients AS $value) { $datas[] = array('RCPT TO: <'.$value.'>'.CRLF, '250', 'RCPT TO error, output: '); } $datas[] = array('DATA'.CRLF, '354', 'DATA command failed, output: '); // 邮件headers $datas[] = 'From: '.$from.CRLF; $datas[] = 'Subject: '.$subject.CRLF; foreach($headers AS $value) { $datas[] = $value.CRLF; } $datas[] = CRLF; $datas[] = $body.CRLF; $datas[] = array('.'.CRLF , '250', 'DATA(end) command failed, output: '); $datas[] = array('QUIT'.CRLF, '221', 'QUIT command failed, output: '); $return_value = ''; // 执行命令 foreach($datas AS $data){ if(is_string($data)) { @fwrite($connection, $data, strlen($data)); } else { @fwrite($connection, $data[0], strlen($data[0])); while($line = @fgets($connection, 1024)) if($line{3} == ' ') break; if(!($data[1] === substr($line, 0, 3))) { // 出错, 保存错误信息 $return_value .= $data[2].$line.'<br />'; } } } @fclose($connection);// 关闭连接 return empty($return_value)?true:$return_value; } notify_content跟据邮件模板生成通知邮件的正文: notify_content function notify_content($tracker, $rcpt_ip, $time_elapsed) { foreach ($tracker AS $key => $value) { $$key = $value; } $hours = intval($time_elapsed / 3600); $minutes = intval(($time_elapsed % 3600) /60); $seconds = $time_elapsed % 60; $time_elapsed = ''; if($hours > 0) $time_elapsed .= $hours.' hours '; if($minutes > 0) $time_elapsed .= $minutes.' minutes '; if($hours == 0 && $seconds > 0) $time_elapsed .= $seconds.' seconds '; $sent_time = date('Y-m-d H:i:s', $sent_time - date("Z") + 8 * 3600); ob_start(); include_once('msg_template.html'); $mail_body=ob_get_contents(); ob_end_clean(); return $mail_body; } exit_with_image_blank函数输出一个空白图片并退出: exit_with_image_blank
function exit_with_image_blank() { $img = imagecreate(15, 15); $white = imagecolorallocate($img, 0xff, 0xff, 0xff); imagefill($img, 0, 0, $white); header('Cache-Control: no-cache, must-revalidate'); header('Content-Type:image/png'); imagepng($img); imagedestroy($img); exit; } 该文章在 2012/1/14 11:16:52 编辑过 |
关键字查询
相关文章
正在查询... |