PHP電子郵件追蹤是如何開發(fā)制作的
當(dāng)前位置:點晴教程→知識管理交流
→『 技術(shù)文檔交流 』
應(yīng)用場景 找工作、發(fā)送推廣郵件等,發(fā)信時想知道對方是否已經(jīng)看過自己的求職或推廣信。網(wǎng)站www.spypig.com可以實現(xiàn)在收信人每次查看你的郵件時發(fā)送Email通知你郵件已經(jīng)被查看過了,并記錄查看的次數(shù)。使用過程中發(fā)現(xiàn),它的實現(xiàn)原理還很簡單,所以就用PHP照著葫蘆畫瓢自己寫了個。 概述 當(dāng)你想知道自己發(fā)送的郵件是否被收信人查看過時,使用電子郵件追蹤系統(tǒng)(Email Tracking System)就可以幫助你。 使用方法 打開鏈接電子郵件追蹤系統(tǒng),輸入Email地址和標(biāo)題,選擇接收通知的次數(shù),然后激活獲取Tracking Image,在一分鐘內(nèi)將其復(fù)制到你的Email郵件正文中,再正常發(fā)送郵件就行了。
實現(xiàn)原理 由于<img />標(biāo)簽的src屬性會主動引入外部文件,所以將調(diào)用“tracker程序”(此程序會正常輸出一張圖片)的URL作為src的值,并將此<img />放入郵件正文中與之一起發(fā)送出去。這樣,每當(dāng)收信人打開該郵件顯示該<img />時,都會調(diào)用“tracker程序”,這時“tracker程序”會發(fā)送email通知你。而郵件也必須是HTML格式的才行。 程序說明 程序共有四部分:
代碼 創(chuàng)建表的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接收參數(shù)產(chǎn)生一個新的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); // 產(chǎn)生一個唯一ID $number = intval($_POST['number']); $email = trim($_POST['email']); $title = trim($_POST['title']); $sent_time = time(); // 作為發(fā)送郵件的時間 $db->query("INSERT INTO `email_tracker` (unique_id, email, title, number, ip, sent_time) VALUES ('$unique_id', '$email', '$title', $number, '$ip', '$sent_time')"); 用于產(chǎn)生唯一ID的get_unique_id函數(shù): get_unique_id function current_microsecond() { list($usec, $sec) = explode(" ",microtime()); return $sec.substr($usec, 2); } // 獲取隨機數(shù) function random() { $tmp = rand(0,1)?'-':''; return $tmp.rand(1000, 9999).rand(1000, 9999).rand(1000, 9999).rand(100, 999).rand(100, 999); } // 產(chǎn)生一個偽GUID // 三段 : 一段是地址 一段是微秒 一段是隨機數(shù) 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調(diào)用,發(fā)送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已經(jīng)結(jié)束 if(empty($tracker) && $tracker['times'] >= $tracker['number']) { // 輸出一個空白圖片并退出 exit_with_image_blank(); } // 郵件發(fā)送時到現(xiàn)在經(jīng)過的時間 $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; // 刪除所有經(jīng)過一分鐘還未激活的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, 查閱次數(shù)增加一次 $tracker['times']++; } $db->query("UPDATE `email_tracker` SET times=$tracker[times] WHERE unique_id='$unique_id'"); if($tracker['times'] >= $tracker['number']) { // Tracking已經(jīng)結(jié)束, 刪除記錄 $db->query("DELETE FROM `email_tracker` WHERE unique_id='$unique_id'"); } // 發(fā)送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函數(shù)用于發(fā)送通知郵件: send_mail /* * 參數(shù): * from required 發(fā)信人email * recipients required 收信人email地址,如果有多個email則以','分隔或傳遞數(shù)組 * params optional 其它可選參數(shù)組成的數(shù)組 * ----subject 郵件主題 * ----body 郵件正文 * ----headers * ----host 用于發(fā)郵件的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服務(wù)器 $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: '); } // 設(shè)置發(fā)信人 $datas[] = array('MAIL FROM: <'.$from.'>'.CRLF, '250', 'MAIL FROM error, output: '); // 設(shè)置收信人 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 = ''; // 執(zhí)行命令 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);// 關(guān)閉連接 return empty($return_value)?true:$return_value; } notify_content跟據(jù)郵件模板生成通知郵件的正文: 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函數(shù)輸出一個空白圖片并退出: 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 編輯過 |
關(guān)鍵字查詢
相關(guān)文章
正在查詢... |