本身用PHP寫的POP3電子郵件收取流程

【小蝸牛嗷嗷之做
 
    這裏面主要是一個 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
在不斷奉獻中謀求生存發展、打造本身的優秀品質,用人性最本質最動人的一面「營銷」本身!
相關文章
相關標籤/搜索