代码之家  ›  专栏  ›  技术社区  ›  MB34

使用php-imap函数时出现问题

  •  0
  • MB34  · 技术社区  · 15 年前

    我正在尝试为我们的站点构建一个电子邮件消息解析器。我最终要做的是重复访问包含附件的邮件,如果邮件来自特定的电子邮件地址,则保存附件。

    这只是最初的测试,但是,我遇到了一些问题,见下面的评论。

      <?php
      echo "Loading..."."<br />\n";
      $mailuser="help@mysite.com";
    
      echo "User=$mailuser"."<br />\n";;
      $mailpass="mypassword";
      echo "Pass=$mailpass"."<br />\n";
      // had to use this because we have SSL on site and regular port 110 didn't work
      $mailhost="{localhost:995/pop3/ssl/novalidate-cert}";
      echo "Host=$mailhost"."<br />\n";
    
      $mailbox=imap_open($mailhost,$mailuser,$mailpass) or die("<br />\nFAILLED! ".imap_last_error());
      $check = imap_check($mailbox);
      // last message parsed will be stored in the file msgcounter.dat
      $firstmsg = file_get_contents('msgcounter.dat') + 1;
      $lastmsg  = $firstmsg+$check->Recent; // should be == last msg index + count of latest messages
      echo 'First:'.$firstmsg.' - Last:'.$lastmsg."<br>";
      $result   = imap_fetch_overview($mailbox,"$firstmsg:$lastmsg");
      print_r($result);
      foreach ($result as $overview) {
        echo "#{$overview->msgno} ({$overview->date}) - From: {$overview->from}
        {$overview->subject}\n";
      }
      // the following approach didn't work either, Kept getting warnings about
      // Bad message number 
      //
      // Some messages in the sequence HAVE been deleted.
      /*
      for ($index = $firstmsg-1; $index <= ($lastmsg); $index++ ) {
        if (strlen(trim(imap_fetchheader($mailbox, $index))) > 0) { 
          echo 'in message index loop:'.$index;
        }
      }
      */
      imap_close($mailbox);
    echo "completed.". "<br />\n";;
    ?>
    
    3 回复  |  直到 13 年前
        1
  •  0
  •   Charles    15 年前

    IMAP是一个糟糕的标准和更糟糕的实现的污水池。如果你不介意有点亵渎(或者,呃,很多),就有一个臭名昭著的 IMAP rant by a Ruby library dev 有一些有趣的见解。

    你应该考虑一下 using someone else's code 做脏活。

        2
  •  0
  •   MB34    15 年前

    好吧,我现在有很大一部分工作要做。 我只剩下一个问题,就是将邮件移动到另一个“文件夹”。 POP3邮箱不支持imap-mail-move,因此我不得不想出一种不同的方法。

    最后一个问题是,我知道什么消息文件与我刚打开的消息对应。我知道我可以使用std rename()函数来移动文件,但是我发现我可以在courierimapuiddb文件中查找msgnum,文件名就在那里。

    以下是我正在处理的代码,除了移动文件:

    <?php
    
    function showProgressMsg($msg)
    {
      echo $msg."<br>";
      ob_flush();
     flush();
      usleep(2500);
    }
      $mailpass="mymailpass";
      $mailhost="{localhost:995/pop3/ssl/novalidate-cert}";
      $mailuser="help@myserver.com";
      include "libs/database/db_mysql.php";
      $db = new Database;
    
      $debug=false;
      if($_GET['debug']= 'yes') {
        $debug = true;
        ini_set('output_buffering', 'Off');
        ob_start();
      }
    
      if($debug) {showProgressMsg('Opening Mailbox');}
    
      $mailbox=imap_open($mailhost,$mailuser,$mailpass) or die("<br />\nFAILLED! ".imap_last_error());
    
      // The IMAP.xml file contains the email address and user_id of the users that we accept 
      // their files via email 
      if($debug) {showProgressMsg('Reading IMAP.xml');}
      $xml = simplexml_load_string(file_get_contents('IMAP.xml'));
      $result = $xml->xpath('item');
      while(list( , $node) = each($result)) {
        $email   = $node->LI_email;
        $user_id = $node->LI_user_id;
        $search  = "RECENT FROM \"$email\"";
    
        if($debug) {showProgressMsg('Searching for '.$email);}
        $result2 = imap_search($mailbox, $search);
        if($result2) {
          $index = $result2[0];
          $structure = imap_fetchstructure($mailbox, $index);
    
          $attachments = array();
          if(isset($structure->parts) && count($structure->parts)) {
            if($debug) {showProgressMsg('Handling attachments');}
            for($i = 0; $i < count($structure->parts); $i++) {
              $attachments[$i] = array(
                'is_attachment' => false,
                'filename' => '',
                'name' => '',
                'attachment' => '');
    
              if($structure->parts[$i]->ifdparameters) {
                foreach($structure->parts[$i]->dparameters as $object) {
                  if(strtolower($object->attribute) == 'filename') {
                    $attachments[$i]['is_attachment'] = true;
                    $attachments[$i]['filename'] = $object->value;
                  }
                }
              }
    
              if($structure->parts[$i]->ifparameters) {
                foreach($structure->parts[$i]->parameters as $object) {
                  if(strtolower($object->attribute) == 'name') {
                    $attachments[$i]['is_attachment'] = true;
                    $attachments[$i]['name'] = $object->value;
                  }
                }
              }
    
              if($attachments[$i]['is_attachment']) {
                $attachments[$i]['attachment'] = imap_fetchbody($mailbox, $index, $i+1, FT_PEEK);
                if($structure->parts[$i]->encoding == 3) { // 3 = BASE64
                  $attachments[$i]['attachment'] = base64_decode($attachments[$i]['attachment']);
                }
                elseif($structure->parts[$i]->encoding == 4) { // 4 = QUOTED-PRINTABLE
                  $attachments[$i]['attachment'] = quoted_printable_decode($attachments[$i]['attachment']);
                }
              }             
            } // for($i = 0; $i < count($structure->parts); $i++)
          } // if(isset($structure->parts) && count($structure->parts))
    
          // Now add a record into the file_upload table
          for($i = 0; $i < count($attachments); $i++) {
            if (strlen(trim($attachments[$i]['filename'])) > 0) {
              $path_parts = pathinfo($attachments[$i]['filename']);
              if($debug) {showProgressMsg('Processing '.$attachments[$i]['filename']);}
              if(strtolower($path_parts['extension']) == 'zip') {
                // I am going to do something different with ziped files            
                $filename = 'file_uploads/temp/'.$user_id.'_'.$path_parts['filename'].'_'.date('m_d_Y').'.'.$path_parts['extension'];
                $fp = fopen($filename, "w");
                fwrite($fp, $attachments[$i]['attachment']);
                fclose($fp);                       
                $zip = new ZipArchive();
                if ($zip->open($filename) !== TRUE) {
                  die ('Could not open archive');
                }
                $zippedfile = $zip->statIndex(0);
                $path_parts = pathinfo($zippedfile['name']);
                $newfilename = 'file_uploads/'.$user_id.'_'.$path_parts['filename'].'_'.date('m_d_Y').'.'.$path_parts['extension'];
                $zip->extractTo('file_uploads/', $zippedfile['name']);
                $zip->close();           
                unlink($filename);
                rename('file_uploads/'.$zippedfile['name'], $newfilename);
                $filestr = preg_replace('`[\r\n]+`',"\n", file_get_contents($newfilename));
                $fp = fopen($newfilename, "w+");
                fwrite($fp, $filestr);
                fclose($fp);                       
                // remove the directory from the filename
                $filename = $user_id.'_'.$path_parts['filename'].'_'.date('m_d_Y').'.'.$path_parts['extension'];
                // Now insert into file_upload table
                $insert_sql = "INSERT INTO `file_upload` VALUES(NULL,$user_id, '$filename', 0, NOW())";
                $db->query($insert_sql) or die("Can't insert record");
              } else {
                $filename = 'file_uploads/'.$user_id.'_'.$path_parts['filename'].'_'.date('m_d_Y').'.'.$path_parts['extension'];
                $fp = fopen($filename, "w");
                $attachments[$i]['attachment'] = preg_replace('`[\r\n]+`',"\n",$attachments[$i]['attachment']);
                fwrite($fp, $attachments[$i]['attachment']);
                fclose($fp);
                // remove the directory from the filename
                $filename = $user_id.'_'.$path_parts['filename'].'_'.date('m_d_Y').'.'.$path_parts['extension'];
                // Now insert into file_upload table
                $insert_sql = "INSERT INTO `file_upload` VALUES(NULL,$user_id, '$filename', 0, NOW())";
                $db->query($insert_sql) or die("Can't insert record:".mysql_error());
              }
            } // if (strlen(trim($attachments['name'])) > 0
          } // for($i = 0; $i < count($attachments); $i++)
          // Now move the message to completed uploads mailbox
          // imap_mail_move copies the message and then sets the deleted flag.
          // Found out that imap_mail_move is unsupported on POP3 accounts
          // imap_mail_move($mailbox, "$index", "INBOX/completed+uploads") or die("can't move: ".imap_last_error()); 
    
          // This is a stop gap to circumvent the message being processed twice
          // Found out that this also is not supported by POP3 boxes
          if($debug) {showProgressMsg('Setting \Seen flag');}
          imap_setflag_full($mailbox, "$index", "\Seen \Flagged");
    
          // This clears out the deleted messages
          // imap_expunge($mailbox);
    
          /*
            So, I'm going to have to open the courierimapuiddb file and locate the msgnum
            then get the filename and use rename() to move the file to the completed uploads 
            directory.
          */
        if($debug) {showProgressMsg(',oving message');}
    
        } // if($result2)
        // Now, move the message to completed uploads 
      } // while(list( , $node) = each($result))
      if($debug) {
        showProgressMsg('Closing mailbox and cleaning up');
        ob_flush();
        flush();
        ob_end_clean();
        ini_set('output_buffering', 4096);
      }
      imap_close($mailbox);  
    ?>
    
        3
  •  0
  •   MB34    15 年前

    问题是我没有在这行中检查IMAP邮箱:

    $mailhost="{localhost:995/pop3/ssl/novalidate-cert}";

    这是要使用的正确行:

    $mailhost="{localhost/imap/ssl/novalidate-cert}";

    推荐文章