2013-09-30 23 views
12

我正在使用PHP imap函數從POP3郵箱獲取電子郵件並將數據插入MySQL數據庫。php imap - 獲取正文並創建純文本

這裏是PHP代碼:

$inbox = imap_open($hostname,$username,$password) or die('Cannot connect: ' . imap_last_error()); 

$emails = imap_search($inbox,'ALL'); 


if($emails) 
{ 
    $output = ''; 

    rsort($emails); 

    foreach($emails as $email_number) 
    { 
     $header=imap_headerinfo($inbox,$email_number); 

     $from = $header->from[0]->mailbox . "@" . $header->from[0]->host; 
     $toaddress=$header->toaddress; 
     $replyto=$header->reply_to[0]->mailbox."@".$header->reply_to[0]->host; 
     $datetime=date("Y-m-d H:i:s",$header->udate); 
     $subject=$header->subject; 

     //remove the " from the $toaddress 
     $toaddress = str_replace('"','',$toaddress); 

     echo '<strong>To:</strong> '.$toaddress.'<br>'; 
     echo '<strong>From:</strong> '.$from.'<br>'; 
     echo '<strong>Subject:</strong> '.$subject.'<br>'; 

     //get message body 
     $message = (imap_fetchbody($inbox,$email_number,1.1)); 
     if($message == '') 
     { 
      $message = (imap_fetchbody($inbox,$email_number,1)); 
     } 
} 

它工作正常,但是在身體上的一些電子郵件,我得到=在字與字之間,或在字與字之間=20。而其他時候,電子郵件將只是空白,即使它們發送時不是空白。

這隻發生在來自某些電子郵件時。

我怎樣才能擺脫這一點,只是使電子郵件完全純文本?

+0

您是否嘗試將選項設置爲'FT_INTERNAL'?請參閱:http://php.net/manual/en/function.imap-fetchbody.php –

回答

23

發生這種情況是因爲電子郵件通常是Quoted-printable編碼的。 =是一個軟線休息,=20是一個白色空間。我認爲,您可以在郵件上使用quoted_printable_decode(),以便正確顯示。關於空白的電子郵件,我不知道,我需要更多的細節。

基本上

//get message body 
$message = quoted_printable_decode(imap_fetchbody($inbox,$email_number,1.1)); 
+2

請謹慎使用此功能,因爲之前已經搞亂了我的MIME邊界標頭,因爲'boundary = 1asa8238asd'具有相同的格式(' = 1a')作爲引用的可打印編碼字符。 –

3

關於空白電子郵件,檢查郵件的編碼。

如果它是一個二進制編碼的郵件,那麼當您嘗試將它們插入到mysql文本字段時,您將收到空白郵件。

嘗試每封郵件轉變爲UTF-8,然後將其

的iconv(mb_detect_encoding($ mail_content,mb_detect_order(),TRUE), 「UTF-8」,$ mail_content);

4
$data = imap_fetchbody($this->imapStream, $Part->uid, $Part->path, FT_UID | FT_PEEK); 
if ($Part->format === 'quoted-printable' && $data) { 
    $data = quoted_printable_decode($data); 
} 

這是必需的郵件與

內容傳輸編碼:引用可打印

但對於

內容傳輸編碼郵件:8位

只需imap_fetchbody就足夠了。

以上代碼取自Cake-php組件,該組件用於從郵箱中獲取郵件throgh IMAP。

5

幾年前,我做了一整堂課,當我需要從電子郵件中獲取內容時,我仍然在使用它。它將幫助您以可讀的格式獲取所有電子郵件正文(有時您擁有html和純文本),並獲取所有附加文件,只需準備保存在某處或發送給網站用戶即可。

它沒有真正優化,所以你可能有麻煩的大郵箱;但該課程的目的是以可讀格式訪問電子郵件,以將其放置在網站的小部件上。我讓你玩下面的例子來看看它是如何工作的。

ImapReader.class.php這裏是源代碼。

<?php 

class ImapReader 
{ 

    private $host; 
    private $port; 
    private $user; 
    private $pass; 
    private $box; 
    private $box_list; 
    private $errors; 
    private $connected; 
    private $list; 
    private $deleted; 

    const FROM = 0; 
    const TO = 1; 
    const REPLY_TO = 2; 
    const SUBJECT = 3; 
    const CONTENT = 4; 
    const ATTACHMENT = 5; 

    public function __construct($host = null, $port = '143', $user = null, $pass = null) 
    { 
     $this->host = $host; 
     $this->port = $port; 
     $this->user = $user; 
     $this->pass = $pass; 
     $this->box = null; 
     $this->box_list = null; 
     $this->errors = array(); 
     $this->connected = false; 
     $this->list = null; 
     $this->deleted = false; 
    } 

    public function __destruct() 
    { 
     if ($this->isConnected()) 
     { 
      $this->disconnect(); 
     } 
    } 

    public function changeServer($host = null, $port = '143', $user = null, $pass = null) 
    { 
     if ($this->isConnected()) 
     { 
      $this->disconnect(); 
     } 
     $this->host = $host; 
     $this->port = $port; 
     $this->user = $user; 
     $this->pass = $pass; 
     $this->box_list = null; 
     $this->errors = array(); 
     $this->list = null; 
     return $this; 
    } 

    public function canConnect() 
    { 
     return (($this->connected == false) && (is_string($this->host)) && (!empty($this->host)) 
      && (is_numeric($this->port)) && ($this->port >= 1) && ($this->port <= 65535) 
      && (is_string($this->user)) && (!empty($this->user)) && (is_string($this->pass)) && (!empty($this->pass))); 
    } 

    public function connect() 
    { 
     if ($this->canConnect()) 
     { 
      $this->box = @imap_open("{{$this->host}:{$this->port}/imap/ssl/novalidate-cert}INBOX", $this->user, 
        $this->pass); 
      if ($this->box !== false) 
      { 
       $this->_connected(); 
      } 
      else 
      { 
       $this->errors = array_merge($this->errors, imap_errors()); 
      } 
     } 
     return $this; 
    } 

    public function boxList() 
    { 
     if (is_null($this->box_list)) 
     { 
      $list = imap_getsubscribed($this->box, "{{$this->host}:{$this->port}}", "*"); 
      $this->box_list = array(); 
      foreach ($list as $box) 
      { 
       $this->box_list[] = $box->name; 
      } 
     } 
     return $this->box_list; 
    } 

    public function fetchAllHeaders($mbox) 
    { 
     if ($this->isConnected()) 
     { 
      $test = imap_reopen($this->box, "{$mbox}"); 
      if (!$test) 
      { 
       return false; 
      } 
      $num_msgs = imap_num_msg($this->box); 
      $this->list = array(); 
      for ($id = 1; ($id <= $num_msgs); $id++) 
      { 
       $this->list[] = $this->_fetchHeader($mbox, $id); 
      } 
      return true; 
     } 
     return false; 
    } 

    public function fetchSearchHeaders($mbox, $criteria) 
    { 
     if ($this->isConnected()) 
     { 
      $test = imap_reopen($this->box, "{$mbox}"); 
      if (!$test) 
      { 
       return false; 
      } 
      $msgs = imap_search($this->box, $criteria); 
      if ($msgs) 
      { 
       foreach ($msgs as $id) 
       { 
        $this->list[] = $this->_fetchHeader($mbox, $id); 
       } 
      } 
      return true; 
     } 
     return false; 
    } 

    public function isConnected() 
    { 
     return $this->connected; 
    } 

    public function disconnect() 
    { 
     if ($this->connected) 
     { 
      if ($this->deleted) 
      { 
       imap_expunge($this->box); 
       $this->deleted = false; 
      } 
      imap_close($this->box); 
      $this->connected = false; 
      $this->box = null; 
     } 
     return $this; 
    } 

    /** 
    * Took from khigashi dot oang at gmail dot com at php.net 
    * with replacement of ereg family functions by preg's ones. 
    * 
    * @param string $str 
    * @return string 
    */ 
    private function _fix($str) 
    { 
     if (preg_match("/=\?.{0,}\?[Bb]\?/", $str)) 
     { 
      $str = preg_split("/=\?.{0,}\?[Bb]\?/", $str); 
      while (list($key, $value) = each($str)) 
      { 
       if (preg_match("/\?=/", $value)) 
       { 
        $arrTemp = preg_split("/\?=/", $value); 
        $arrTemp[0] = base64_decode($arrTemp[0]); 
        $str[$key] = join("", $arrTemp); 
       } 
      } 
      $str = join("", $str); 
     } 

     if (preg_match("/=\?.{0,}\?Q\?/", $str)) 
     { 
      $str = quoted_printable_decode($str); 
      $str = preg_replace("/=\?.{0,}\?[Qq]\?/", "", $str); 
      $str = preg_replace("/\?=/", "", $str); 
     } 
     return trim($str); 
    } 

    private function _connected() 
    { 
     $this->connected = true; 
     return $this; 
    } 

    public function getErrors() 
    { 
     $errors = $this->errors; 
     $this->errors = array(); 
     return $errors; 
    } 

    public function count() 
    { 
     if (is_null($this->list)) 
     { 
      return 0; 
     } 
     return count($this->list); 
    } 

    public function get($nbr = null) 
    { 
     if (is_null($nbr)) 
     { 
      return $this->list; 
     } 
     if ((is_array($this->list)) && (isset($this->list[$nbr]))) 
     { 
      return $this->list[$nbr]; 
     } 
     return null; 
    } 

    public function fetch($nbr = null) 
    { 
     return $this->_callById('_fetch', $nbr); 
    } 

    private function _fetchHeader($mbox, $id) 
    { 
     $header = imap_header($this->box, $id); 
     if (!is_object($header)) 
     { 
      continue; 
     } 
     $mail = new stdClass(); 
     $mail->id = $id; 
     $mail->mbox = $mbox; 
     $mail->timestamp = (isset($header->udate)) ? ($header->udate) : (''); 
     $mail->date = date("d/m/Y H:i:s", (isset($header->udate)) ? ($header->udate) : ('')); 
     $mail->from = $this->_fix(isset($header->fromaddress) ? ($header->fromaddress) : ('')); 
     $mail->to = $this->_fix(isset($header->toaddress) ? ($header->toaddress) : ('')); 
     $mail->reply_to = $this->_fix(isset($header->reply_toaddress) ? ($header->reply_toaddress) : ('')); 
     $mail->subject = $this->_fix(isset($header->subject) ? ($header->subject) : ('')); 
     $mail->content = array(); 
     $mail->attachments = array(); 
     $mail->deleted = false; 
     return $mail; 
    } 

    private function _fetch($mail) 
    { 
     $test = imap_reopen($this->box, "{$mail->mbox}"); 
     if (!$test) 
     { 
      return $mail; 
     } 
     $structure = imap_fetchstructure($this->box, $mail->id); 
     if ((!isset($structure->parts)) || (!is_array($structure->parts))) 
     { 
      $body = imap_body($this->box, $mail->id); 
      $content = new stdClass(); 
      $content->type = 'content'; 
      $content->mime = $this->_fetchType($structure); 
      $content->charset = $this->_fetchParameter($structure->parameters, 'charset'); 
      $content->data = $this->_decode($body, $structure->type); 
      $content->size = strlen($content->data); 
      $mail->content[] = $content; 
      return $mail; 
     } 
     else 
     { 
      $parts = $this->_fetchPartsStructureRoot($mail, $structure); 
      foreach ($parts as $part) 
      { 
       $content = new stdClass(); 
       $content->type = null; 
       $content->data = null; 
       $content->mime = $this->_fetchType($part->data); 
       if ((isset($part->data->disposition)) 
        && ((strcmp('attachment', $part->data->disposition) == 0) 
        || (strcmp('inline', $part->data->disposition) == 0))) 
       { 
        $content->type = $part->data->disposition; 
        $content->name = null; 
        if (isset($part->data->dparameters)) 
        { 
         $content->name = $this->_fetchParameter($part->data->dparameters, 'filename'); 
        } 
        if (is_null($content->name)) 
        { 
         if (isset($part->data->parameters)) 
         { 
          $content->name = $this->_fetchParameter($part->data->parameters, 'name'); 
         } 
        } 
        $mail->attachments[] = $content; 
       } 
       else if ($part->data->type == 0) 
       { 
        $content->type = 'content'; 
        $content->charset = null; 
        if (isset($part->data->parameters)) 
        { 
         $content->charset = $this->_fetchParameter($part->data->parameters, 'charset'); 
        } 
        $mail->content[] = $content; 
       } 
       $body = imap_fetchbody($this->box, $mail->id, $part->no); 
       if (isset($part->data->encoding)) 
       { 
        $content->data = $this->_decode($body, $part->data->encoding); 
       } 
       else 
       { 
        $content->data = $body; 
       } 
       $content->size = strlen($content->data); 
      } 
     } 
     return $mail; 
    } 

    private function _fetchPartsStructureRoot($mail, $structure) 
    { 
     $parts = array(); 
     if ((isset($structure->parts)) && (is_array($structure->parts)) && (count($structure->parts) > 0)) 
     { 
      foreach ($structure->parts as $key => $data) 
      { 
       $this->_fetchPartsStructure($mail, $data, ($key + 1), $parts); 
      } 
     } 
     return $parts; 
    } 

    private function _fetchPartsStructure($mail, $structure, $prefix, &$parts) 
    { 
     if ((isset($structure->parts)) && (is_array($structure->parts)) && (count($structure->parts) > 0)) 
     { 
      foreach ($structure->parts as $key => $data) 
      { 
       $this->_fetchPartsStructure($mail, $data, $prefix . "." . ($key + 1), $parts); 
      } 
     } 

     $part = new stdClass; 
     $part->no = $prefix; 
     $part->data = $structure; 

     $parts[] = $part; 
    } 

    private function _fetchParameter($parameters, $key) 
    { 
     foreach ($parameters as $parameter) 
     { 
      if (strcmp($key, $parameter->attribute) == 0) 
      { 
       return $parameter->value; 
      } 
     } 
     return null; 
    } 

    private function _fetchType($structure) 
    { 
     $primary_mime_type = array ("TEXT", "MULTIPART", "MESSAGE", "APPLICATION", "AUDIO", "IMAGE", "VIDEO", "OTHER"); 
     if ((isset($structure->subtype)) && ($structure->subtype) && (isset($structure->type))) 
     { 
      return $primary_mime_type[(int) $structure->type] . '/' . $structure->subtype; 
     } 
     return "TEXT/PLAIN"; 
    } 

    private function _decode($message, $coding) 
    { 
     switch ($coding) 
     { 
      case 2: 
       $message = imap_binary($message); 
       break; 
      case 3: 
       $message = imap_base64($message); 
       break; 
      case 4: 
       $message = imap_qprint($message); 
       break; 
      case 5: 
       break; 
      default: 
       break; 
     } 
     return $message; 
    } 

    private function _callById($method, $data) 
    { 
     $callback = array ($this, $method); 

     // data is null 
     if (is_null($data)) 
     { 
      $result = array(); 
      foreach ($this->list as $mail) 
      { 
       $result[] = $this->_callById($method, $mail); 
      } 
      return $result; 
     } 

     // data is an array 
     if (is_array($data)) 
     { 
      $result = array(); 
      foreach ($data as $elem) 
      { 
       $result[] = $this->_callById($method, $elem); 
      } 
      return $result; 
     } 

     // data is an object 
     if ((is_object($data)) && ($data instanceof stdClass) && (isset($data->id))) 
     { 
      return call_user_func($callback, $data); 
     } 

     // data is numeric 
     if (($this->isConnected()) && (is_array($this->list)) && (is_numeric($data))) 
     { 
      foreach ($this->list as $mail) 
      { 
       if ($mail->id == $data) 
       { 
        return call_user_func($callback, $mail); 
       } 
      } 
     } 

     return null; 
    } 

    public function delete($nbr) 
    { 
     $this->_callById('_delete', $nbr); 
     return; 
    } 

    private function _delete($mail) 
    { 
     if ($mail->deleted == false) 
     { 
      $test = imap_reopen($this->box, "{$mail->mbox}"); 
      if ($test) 
      { 
       $this->deleted = true; 
       imap_delete($this->box, $mail->id); 
       $mail->deleted = true; 
      } 
     } 
    } 

    public function searchBy($pattern, $type) 
    { 
     $result = array(); 
     if (is_array($this->list)) 
     { 
      foreach ($this->list as $mail) 
      { 
       $match = false; 
       switch ($type) 
       { 
        case self::FROM: 
         $match = $this->_match($mail->from, $pattern); 
         break; 
        case self::TO: 
         $match = $this->_match($mail->to, $pattern); 
         break; 
        case self::REPLY_TO: 
         $match = $this->_match($mail->reply_to, $pattern); 
         break; 
        case self::SUBJECT: 
         $match = $this->_match($mail->subject, $pattern); 
         break; 
        case self::CONTENT: 
         foreach ($mail->content as $content) 
         { 
          $match = $this->_match($content->data, $pattern); 
          if ($match) 
          { 
           break; 
          } 
         } 
         break; 
        case self::ATTACHMENT: 
         foreach ($mail->attachments as $attachment) 
         { 
          $match = $this->_match($attachment->name, $pattern); 
          if ($match) 
          { 
           break; 
          } 
         } 
         break; 
       } 
       if ($match) 
       { 
        $result[] = $mail; 
       } 
      } 
     } 
     return $result; 
    } 

    private function _nmatch($string, $pattern, $a, $b) 
    { 
     if ((!isset($string[$a])) && (!isset($pattern[$b]))) 
     { 
      return 1; 
     } 

     if ((isset($pattern[$b])) && ($pattern[$b] == '*')) 
     { 
      if (isset($string[$a])) 
      { 
       return ($this->_nmatch($string, $pattern, ($a + 1), $b) + $this->_nmatch($string, $pattern, $a, ($b + 1))); 
      } 
      else 
      { 
       return ($this->_nmatch($string, $pattern, $a, ($b + 1))); 
      } 
     } 

     if ((isset($string[$a])) && (isset($pattern[$b])) && ($pattern[$b] == '?')) 
     { 
      return ($this->_nmatch($string, $pattern, ($a + 1), ($b + 1))); 
     } 

     if ((isset($string[$a])) && (isset($pattern[$b])) && ($pattern[$b] == '\\')) 
     { 
      if ((isset($pattern[($b + 1)])) && ($string[$a] == $pattern[($b + 1)])) 
      { 
       return ($this->_nmatch($string, $pattern, ($a + 1), ($b + 2))); 
      } 
     } 

     if ((isset($string[$a])) && (isset($pattern[$b])) && ($string[$a] == $pattern[$b])) 
     { 
      return ($this->_nmatch($string, $pattern, ($a + 1), ($b + 1))); 
     } 

     return 0; 
    } 

    private function _match($string, $pattern) 
    { 
     return $this->_nmatch($string, $pattern, 0, 0); 
    } 

} 

ImapReader.demo.php下面是使用樣品

<?php 

require_once("ImapReader.class.php"); 

$box = new ImapReader('example.com', '143', '[email protected]', 'xxxxxxxxxxxx'); 
$box 
    ->connect() 
    ->fetchAllHeaders() 
; 

echo $box->count() . " emails in mailbox\n"; 
for ($i = 0; ($i < $box->count()); $i++) 
{ 
    $msg = $box->get($i); 
    echo "Reception date : {$msg->date}\n"; 
    echo "From : {$msg->from}\n"; 
    echo "To : {$msg->to}\n"; 
    echo "Reply to : {$msg->from}\n"; 
    echo "Subject : {$msg->subject}\n"; 
    $msg = $box->fetch($msg); 
    echo "Number of readable contents : " . count($msg->content) . "\n"; 
    foreach ($msg->content as $key => $content) 
    { 
     echo "\tContent " . ($key + 1) . " :\n"; 
     echo "\t\tContent type : {$content->mime}\n"; 
     echo "\t\tContent charset : {$content->charset}\n"; 
     echo "\t\tContent size : {$content->size}\n"; 
    } 
    echo "Number of attachments : " . count($msg->attachments) . "\n"; 
    foreach ($msg->attachments as $key => $attachment) 
    { 
     echo "\tAttachment " . ($key + 1) . " :\n"; 
     echo "\t\tAttachment type : {$attachment->type}\n"; 
     echo "\t\tContent type : {$attachment->mime}\n"; 
     echo "\t\tFile name : {$attachment->name}\n"; 
     echo "\t\tFile size : {$attachment->size}\n"; 
    } 
    echo "\n"; 
} 

echo "Searching '*Bob*' ...\n"; 
$results = $box->searchBy('*Bob*', ImapReader::FROM); 
foreach ($results as $result) 
{ 
    echo "\tMatched: {$result->from} - {$result->date} - {$result->subject}\n"; 
} 

享受

+0

我不想改變你的代碼,但爲了將來可以幫助某人,我在'_fix'函數中遇到了一些問題 - 它留下了尾部的'?',剩下的空格替換爲下劃線。我用'imap_mime_header_decode'(如[這裏](http://stackoverflow.com/a/17187116/1714))代替 – Hobo

+0

謝謝你的貢獻。我的代碼是舊的,仍舊適用於舊流程,但我最近沒有對它進行測試。很快就會檢查出來。 –