如何在没有IMAP功能的情况下从原始电子邮件中提取电子邮件附件?

时间:2011-02-17 13:42:09

标签: php email

标题几乎说明了一切,但我会尝试将这个问题充实。

我的PHP应用程序需要从套接字读取电子邮件(这是一项要求),然后使用其中一些电子邮件(具有api令牌)作为应用程序中的文章(它是一个cms)。 / p>

我已经能够让阅读部分有所进展,但现在我们仍然坚持解析它们;具体来说,我们的问题是,我可能收到的电子邮件将在99%的时间内显示如下:

MIME-Version: 1.0\r\n
Received: by {ip_number} with {protocol}; {iso_date}\r\n
Date: {iso_date}\r\n
Delivered-To: {destination}\r\n
Message-ID: {sample_message_id}\r\n
Subject: {subject}\r\n
From: {sender}\r\n
To: {destination}\r\n
Content-Type: multipart/mixed; boundary={sample_boundary}\r\n
\r\n
--{sample_boundary}\r\n
Content-Type: multipart/alternative; boundary={sample_boundary_2}\r\n
\r\n
--{sample_boundary_2}\r\n
Content-Type: text/plain; charset={charset}\r\n
\r\n
{file_content}\r\n
--\r\n
{signature}\r\n
\r\n
--{sample_boundary_2}\r\n
Content-Type: text/html; charset={charset}\r\n
\r\n
{content_html}\r\n
{signature_html}\r\n
--{sample_boundary_2}--\r\n
--{sample_boundary}\r\n
Content-Type: image/jpeg; name="{file_name}"\r\n
Content-Disposition: attachment; filename="{file_name}"\r\n
Content-Transfer-Encoding: base64\r\n
X-Attachment-Id: {sample_attachment_id}\r\n
\r\n
{quoted_printable_file_contents}\r\n
--{sample_boundary}--\r\n

虽然我一直试图将它们重新出现,但我根本无法做到。标准电子邮件 应该在\n中结束他们的行,但是某些do in \r\n嵌套相结合的事实对我来说太过分了。

PHPClasses中有一个库将电子邮件分成MIME部分(以及其他一些东西),由一些Manuel Lemos家伙编写,他清楚地知道自己在做什么,因为它非常有效并且返回格式和解析得很好,但它并没有为我减少。

图书馆本身由+2500行无法理解的乱码组成,我无法理解(它用3种不同的camelCases编写,并使用各种缩进样式以及不同类型的ifs(如if():和{ {1}}和if()以及if(){}for(;;)for(){}之类的循环并不会让它变得更简单)

有人在这里帮忙吗?

非常感谢!

- 已编辑添加

按照Sjoern的建议,我开始为自己的问题建立解决方案(谢谢!!)。我仍然愿意接受更多建议;肯定有更好的方法来做到这一点)

for():

3 个答案:

答案 0 :(得分:1)

创建一个解析消息并递归调用它的函数。

首先,解析整个消息。如果你遇到这个:

Content-Type: multipart/mixed; boundary={sample_boundary}

{sample_boundary}上拆分邮件。然后解析每个子消息。

function parseMessage($message) {
    // Put some code here to determine the split
    $messages = explode($boundary, $message);
    $result = array();
    foreach ($messages as $message) {
        $result[] = parseMessage($message);
    }
    return $result;
}

答案 1 :(得分:0)

我知道这个问题已经过时了,但我不得不为没有IMAP和没有PEAR的附加PDF(廉价主机)做到这一点。

这段代码接收原始电子邮件消息(在$ email中),查看附件的消息,如果找到附件,则将其解压缩,解码并保存。我会添加一些检查以确保附件是您想要的类型 - 例如'pdf'。

适用于从gmail发送的base64 pdf附件 - 尚未测试任何其他内容。编辑:现已测试并使用来自雅虎的电子邮件。

(对不起,线条有点长,因为我没有把所有东西都变成变量)。

使用MAILPARSER功能http://php.net/manual/en/ref.mailparse.php

//TAKES A RAW MESSAGE $email AND FINDS PART WITH ATTACHMENT, CROPS OUT ATTACHMENT, DECODES, SAVES.
$mailparse = mailparse_msg_create();
mailparse_msg_parse($mailparse,$email);
$structure = mailparse_msg_get_structure($mailparse); 

foreach($structure as $structurepart) { 

//THIS IS THE MODIFIED LINE TO CHECK FOR AN ATTACHMENT THAT IS A PDF
//if (mailparse_msg_get_part_data(mailparse_msg_get_part($mailparse, $structurepart))['content-disposition']==='attachment' && mailparse_msg_get_part_data(mailparse_msg_get_part($mailparse, $structurepart))['content-type']==='application/pdf' )

if (mailparse_msg_get_part_data(mailparse_msg_get_part($mailparse, $structurepart))['content-disposition']==='attachment') {
    $startingposition = mailparse_msg_get_part_data(mailparse_msg_get_part($mailparse, $structurepart))['starting-pos-body'];
    $length = mailparse_msg_get_part_data(mailparse_msg_get_part($mailparse, $structurepart))['ending-pos-body'] - mailparse_msg_get_part_data(mailparse_msg_get_part($mailparse, $structurepart))['starting-pos-body'];
    $filenameasreceived = mailparse_msg_get_part_data(mailparse_msg_get_part($mailparse, $structurepart))['disposition-filename'];

    $mime_pdf = substr( $email, $startingposition,$length); 
    $mime_pdf = base64_decode($mime_pdf);

    /* Saves the data into a file */
    $fdw = fopen('/home/[userfolder]/public_html/'. $filenameasreceived, "w+");
    fwrite($fdw, $mime_pdf);
    fclose($fdw);
    /* Script End */
    echo "<br>file saved.";
  }
  }

答案 2 :(得分:0)

我必须在以下函数中将14更改为13才能使其正常工作:

  protected function hasContentType($string){

          return strtolower(trim(substr($string,0,13))) == 'content-type';
  }