【小蝸牛嗷嗷之做】
這裏面主要是一個 recvmail() 函數,從POP3服務器檢測並收取新的郵件,最後用 update_mail_table() 函數將新郵件信息(發信者, 主題, 發送時間, 郵件文件名, 郵件大小, 附件標誌)插入到數據庫。
我在 update_mail_table() 函數裏寫的解釋一封電子郵件內容的方法不規範,可能沒法正確解釋一些不嚴格遵照MIME規範的郵件。還有一些其它的實用函數,參考了互聯網上的別人的一些方法,Thanks the Original Author. ;)
<?php
/* 系統默認參數,注意:這裏是全局變量 */
$connection=0; // 保存與主機的鏈接
$timeout = 5; // 鏈接主機的最大超時時間
$err_str=''; // 若是出錯,這裏保存錯誤信息
$err_no; // 若是出錯,這裏保存錯誤號碼
$resp; // 臨時保存服務器的響應信息
$new_mail_count = 0; //新郵件數目
/*
* 函數功能:接收POP3服務器上的(新)郵件
* 輸入參數:$host,$user,$pass
* 返 回:若是順利執行,返回true,不然返回false,
* 錯誤信息保存在$err_str
*
*/
function recvmail($host, $user, $pass) {
/* 使用全局的數據庫鏈接 */
global $link;
/* 使用全局的pop3鏈接參數 */
global $connection;
global $timeout;
global $err_str;
global $err_no;
global $resp;
/* 此次所取回的新郵件數目 */
global $new_mail_count;
global $new_mail_dir;
$mail_uidl_stored = array(); // 數據庫裏的郵件UIDL列表
$mail_uidl_fresh = array(); // 郵件服務器上的UIDL列表
/*===================== 從數據庫讀取UIDL列表 ========================*/
$query = "select * from mail_uid_list";
if ($result = mysqli_query($link, $query)) {
$i = 0;
while ($row = mysqli_fetch_row($result)) {
$mail_uidl_stored[$i++] = $row[0];
}
mysqli_free_result($result);
} else {
printf("Can't query to MySQL Server. Errorcode: %s ", mysqli_error($link));
exit();
}
/*========================= 鏈接POP3服務器 =========================*/
if (!$connection=fsockopen($host, 110 , &$err_no, &$err_str, $timeout)) {
$err_str="鏈接到POP服務器失敗,錯誤信息:".$err_str."錯誤號:".$err_no;
return false;
} else {
getresp();
if (substr($resp,0,3)!="+OK") {
$err_str="服務器返回無效的信息:".$resp."請檢查POP服務器是否正確!";
return false;
}
}
/*========================= 登錄POP3服務器 =========================*/
if (!login($user, $pass)) {
$err_str = "賬號或者密碼錯誤!";
return false;
}
/*====================== 獲取郵件列表,用UIDL命令 ====================*/
command("UIDL", 3, "+OK");
getresp();
$i = 0;
while ($resp != ".") {
$mail_uidl_key[$i] = strtok($resp," ");
$mail_uidl_fresh[$i] = strtok(" "); // 這是郵件的UID
getresp();
$i++;
}
/*====== 對郵件列表進行分析處理,對比數據庫中的信息,收取新郵件 =======*/
$new_mail_uidl = array_diff($mail_uidl_fresh, $mail_uidl_stored);
if (empty($new_mail_uidl)) {
$new_mail_count = 0;
/* 注意:若是沒有新郵件,這裏就返回了 */
return true;
} else {
$new_mail_count = count($new_mail_uidl);
}
/* 這裏巧妙的運用了array_keys函數 */
$new_mail_num = array_keys($new_mail_uidl);
$i = 0;
while (($num = $new_mail_num[$i]) || ($new_mail_num[$i] === 0)) { // 循環收取新郵件
$num += 1;
if (!command("RETR $num", 3, "+OK")) {
return false;
}
$mail_file_str = "";
$mail_str = fgets($connection, 100);
while ($mail_str != ".\r\n") { // .\r\n 是郵件結束的標誌
$mail_file_str .= $mail_str;
$mail_str = fgets($connection, 100);
}
/* 輸出郵件文件 */
$mail_file_name_array[$i] = date("YmdHis")."_hoho_".get_radom_str(10);
file_put_contents($new_mail_dir.$mail_file_name_array[$i], $mail_file_str);
$i ++;
}
/*====================== 關閉與服務器鏈接 =========================*/
if (!command("QUIT",3,"+OK")) {
return false;
}
fclose($connection);
/*====================== 更新數據庫UID列表 ========================*/
$i = 0;
while (($num = $new_mail_num[$i]) || ($new_mail_num[$i] === 0)) { // 即便有一封新郵件,也要更新數據庫
//若是是大批量數據,最好採用數組合並,但目前沒有掌握將數據存放msyql的方法
//$mail_uidl_stored = array_unique(array_merge($mail_uidl_stored, $mail_uidl_fresh));
//只好笨笨的這樣作了
$query = "insert into mail_uid_list values('".$new_mail_uidl[$new_mail_num[$i]]."', '".$mail_file_name_array[$i]."')";
$result = mysqli_query($link, $query);
if (!$result) {
printf("Can't query to MySQL Server. Errorcode: %s ", mysqli_error($link));
exit();
}
$i ++;
}
/*================ 更新mail列表 =======================*/
$i = 0;
while ($mail_file_name_array[$i]) {
update_mail_table($mail_file_name_array[$i]);
$i ++;
}
/*=============== 注意:這裏不能關閉與數據庫的鏈接 ==================*/
//mysqli_close($link);
return true;
}
function getresp() {
/* 採用全局變量,再三思考,仍是認爲這樣效率高 */
global $connection;
global $resp;
for($resp = "";;) {
if(feof($connection))
return false;
$resp .= fgets($connection,100);
$length = strlen($resp);
if($length >= 2 && substr($resp, $length - 2, 2) == "\r\n") {
$resp = strtok($resp,"\r\n");
return true;
}
}
}
function command($command, $return_lenth=1, $return_code='+') {
/* 採用全局變量,再三思考,仍是認爲這樣效率高 */
global $connection;
global $resp;
global $err_str;
if (!fputs($connection, "$command\r\n")) {
$err_str = "沒法發送命令".$command;
return false;
} else {
getresp();
if (substr($resp, 0, $return_lenth) != $return_code) {
$err_str = $command." 命令服務器返回無效:".$resp;
return false;
} else {
return true;
}
}
}
function login($user, $password) {
if (!command("USER $user",3,"+OK")) return false;
if (!command("PASS $password",3,"+OK")) return false;
return true;
}
function get_radom_str($len){
$str = 'abcdefghijklmnopqrstuvwxyz0123456789';
//從以上字串中產生隨機串,你若是想要其它字符,能夠自行加入,如大寫字母
return substr(str_shuffle($str),0,$len);
}
function update_mail_table($mail_file_name) {
global $new_mail_dir;
$mail_file_content = file_get_contents($new_mail_dir.$mail_file_name);
$mail_file_size = filesize($new_mail_dir.$mail_file_name);
/* 記錄附件個數和對應名字、大小 */
if ($mail_file_size > 1048576) {
$mail_file_size = round($mail_file_size/1048576, "2")." MB ";
} else if ($mail_file_size > 1024) {
$mail_file_size = round($mail_file_size/1024, "2")." KB ";
} else {
$mail_file_size = $mail_file_size." Bytes ";
}
/*
* 注意!這裏好像沒有前後,因此不能拿一個做爲另外一個的參考位置出發點
*/
/*======== 發件人 ========*/
$from_start = strpos($mail_file_content, "\r\nFrom:");
$from_end = strpos($mail_file_content, "\r", $from_start + 7);
$from_str = substr($mail_file_content, $from_start, $from_end - $from_start);
if ($sender_start = strpos($from_str, "?B?")) {
$sender_start += 3;
$sender_end = strpos($from_str, "?=", $sender_start);
$sender_str = substr($from_str, $sender_start, $sender_end - $sender_start);
$sender = base64_decode($sender_str);
/* 檢測字符集類型,在recvmail_func.php中沒有這一項 */
$charset_start = strpos($from_str, "=?") + 2;
$charset_end = strpos($from_str, "?", $charset_start);
$charset = substr($from_str, $charset_start, $charset_end - $charset_start);
} else if ($sender_start = stripos($from_str, "?Q?")) {
$sender_start += 3;
$sender_end = strpos($from_str, "?=", $sender_start);
$sender_str = substr($from_str, $sender_start, $sender_end - $sender_start);
/* 有些變態的名字,還分開幾段來寫,真鬱悶! */
while ($sender_start = stripos($from_str, "?Q?", $sender_end)) {
$sender_start += 3;
$sender_end = strpos($from_str, "?=", $subject_start);
$sender_str .= substr($from_str, $sender_start, $sender_end - $sender_start);
}
$sender = quoted_printable_decode($sender_str);
/* 檢測字符集類型,在recvmail_func.php中沒有這一項 */
$charset_start = strpos($from_str, "=?") + 2;
$charset_end = strpos($from_str, "?", $charset_start);
$charset = substr($from_str, $charset_start, $charset_end - $charset_start);
} else if ($sender_start = strpos($from_str, "\"")) {
/* 「預防」有的郵件沒有 "發件人",雖然本身還沒見到例外 2008-10-21 */
$sender_start += 1;
$sender_end = strpos($from_str, "\"", $sender_start);
/* 這裏是ascii組成 */
$sender = substr($from_str, $sender_start, $sender_end - $sender_start);
} else {
$sender_start = 8;
/* 先看看是否有空格,有空格就以空格爲邊界 */
if (!$sender_end = strpos($from_str, " ", $sender_start)) {
$sender_end = $from_end;
}
$sender = substr($from_str, $sender_start, $sender_end - $sender_start);
if (substr($sender, 0, 1) == "<") {
$sender = "";
}
}
/* 發件人email地址 */
if ($sender_email_start = strpos($from_str, "<")) {
$sender_email_end = strpos($from_str, ">");
$sender_email = substr($from_str, $sender_email_start + 1, $sender_email_end - $sender_email_start - 1);
if (strlen($sender) > 30 || strlen($sender) == 0){
$sender = $sender_email;
}
}
/*======== 收件人 ========*/
/*
* 暫略
*/
/*========= 主題 =========*/
$subject_start = strpos($mail_file_content, "\r\nSubject:");
$subject_end = strpos($mail_file_content, "\r", $subject_start+10);
$subject_line = substr($mail_file_content, $subject_start, $subject_end - $subject_start);
if ($subject_start = strpos($subject_line, "?B?")) {
$subject_start += 3;
$subject_end = strpos($subject_line, "?=", $subject_start);
$subject_str = substr($subject_line, $subject_start, $subject_end - $subject_start);
$subject = base64_decode($subject_str);
/* 檢測字符集類型,在recvmail_func.php中沒有這一項 */
$charset_start = strpos($subject_line, "=?") + 2;
$charset_end = strpos($subject_line, "?", $charset_start);
$charset = substr($subject_line, $charset_start, $charset_end - $charset_start);
} else if ($subject_start = stripos($subject_line, "?Q?")) {
$subject_start += 3;
$subject_end = strpos($subject_line, "?=", $subject_start);
$subject_str = substr($subject_line, $subject_start, $subject_end - $subject_start);
/* 有些變態的名字,還分開幾段來寫,真鬱悶! */
while ($subject_start = stripos($subject_line, "?Q?", $subject_end)) {
$subject_start += 3;
$subject_end = strpos($subject_line, "?=", $subject_start);
$subject_str .= substr($subject_line, $subject_start, $subject_end - $subject_start);
}
$subject = htmlspecialchars(quoted_printable_decode($subject_str));
/* 檢測字符集類型,在recvmail_func.php中沒有這一項 */
$charset_start = strpos($subject_line, "=?") + 2;
$charset_end = strpos($subject_line, "?", $charset_start);
$charset = substr($subject_line, $charset_start, $charset_end - $charset_start);
} else {
$subject = substr($subject_line, 11, $subject_end - $subject_start - 11);
}
/*======== 發送日期 =======*/
if ($date_start = strpos($mail_file_content, "\r\nDate:")) {
$date_start += 8;
$date_end = strpos($mail_file_content, "\r", $date_start);
$date_str = substr($mail_file_content, $date_start, $date_end - $date_start);
$date = date('Y年m月d日 H:i:s', strtotime($date_str));
} else {
$date = date('Y年m月d日 H:i:s');
}
/* 檢查是否有附件 */
if (strpos($mail_file_content, "\r\nContent-Disposition: p_w_upload")) {
$has_p_w_upload = 1;
} else {
$has_p_w_upload = 0;
}
global $link;
if ($charset == "UTF-8" || $charset == "utf-8") {
$sender = iconv("UTF-8", "GB2312", $sender);
$subject = iconv("UTF-8", "GB2312", $subject);
}
/* 插入數據庫 */
$query = "insert into mail(Sender, Subject, Sendtime, Filename, Filesize, Attachment) \n
values('$sender', '$subject', '$date', '$mail_file_name', '$mail_file_size', '$has_p_w_upload')";
$result = mysqli_query($link, $query);
if (!$result) {
printf("Can't query to MySQL Server. Errorcode: %s ", mysqli_error($link));
exit();
}
}
?>
------------------------------------------------------------------------------------------
趙小蝸牛
QQ: 755721501
在不斷奉獻中謀求生存發展、打造本身的優秀品質,用人性最本質最動人的一面「營銷」本身!