【小蜗牛嗷嗷之做
】
这里面主要是一个 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
在不断奉献中谋求生存发展、打造本身的优秀品质,用人性最本质最动人的一面“营销”本身!