문제

나는 원시 이메일을 여러 부분으로 구문 분석하기 위해 PHP 코드를 사용하기에 좋고/작동/간단한 것을 찾고 있습니다.

나는 몇 가지 무차별 솔루션을 작성했지만 매번 하나의 작은 변경/헤더/공간/뭔가가 발생하고 전체 파서가 실패하고 프로젝트가 무너집니다.

그리고 PEAR/PECL을 지적하기 전에 실제 코드가 필요합니다.내 호스트에 이상한 구성이 있어서 .so를 올바르게 빌드할 수 없는 것 같습니다..so를 만든 경우 path/environment/php.ini의 일부 차이로 인해 항상 사용할 수 있는 것은 아닙니다(apache vs cron vs cli).

아, 그리고 마지막으로 POP3나 IMAP이 아닌 원시 이메일 텍스트를 분석하고 있습니다..qmail 이메일 리디렉션을 통해 PHP 스크립트로 파이프됩니다.

나는 SOF가 나를 위해 그것을 작성할 것이라고 기대하지 않습니다. 나는 그것을 "올바른" 작업에 대한 몇 가지 팁/시작점을 찾고 있습니다.이것은 이미 해결된 것으로 알고 있는 "바퀴" 문제 중 하나입니다.

도움이 되었습니까?

해결책

마지막에 무엇으로 끝나기를 바라나요?본문, 제목, 보낸 사람, 첨부 파일?당신은 함께 시간을 보내야합니다 RFC2822 메일의 형식을 이해하는 데 도움이 되지만, 잘 구성된 이메일에 대한 가장 간단한 규칙은 다음과 같습니다.

HEADERS\n
\n
BODY

즉, 첫 번째 빈 줄(이중 줄 바꿈)은 HEADERS와 BODY 사이의 구분 기호입니다.헤더는 다음과 같습니다:

HSTRING:HTEXT

HSTRING은 항상 줄의 시작 부분에서 시작하며 공백이나 콜론을 포함하지 않습니다.HTEXT는 줄 바꿈 문자 뒤에 공백이 있는 한 줄 바꿈을 포함하여 다양한 텍스트를 포함할 수 있습니다.

"BODY"는 실제로 첫 번째 이중 줄 바꿈 뒤에 오는 모든 데이터입니다.(SMTP를 통해 메일을 전송하는 경우에는 다른 규칙이 있지만 파이프를 통해 처리하는 경우에는 걱정할 필요가 없습니다.)

아주 간단하게 말하자면 1982년경입니다. RFC822 용어에 따르면 이메일은 다음과 같습니다.

HEADER: HEADER TEXT
HEADER: MORE HEADER TEXT
  INCLUDING A LINE CONTINUATION
HEADER: LAST HEADER

THIS IS ANY
ARBITRARY DATA
(FOR THE MOST PART)

하지만 대부분의 최신 이메일은 그보다 더 복잡합니다.헤더는 문자 세트 또는 RFC2047 마임말이나 지금은 생각하지 못하는 수많은 것들이요.요즘에는 본문이 의미를 갖기를 원하는 경우 자신의 코드를 롤링하기가 정말 어렵습니다.MUA에 의해 생성된 거의 모든 이메일은 몸짓 광대극 인코딩되었습니다.그것은 uu로 인코딩된 텍스트일 수도 있고, html일 수도 있고, uu로 인코딩된 Excel 스프레드시트일 수도 있습니다.

이것이 이메일의 매우 기본적인 버킷 중 일부를 이해하기 위한 프레임워크를 제공하는 데 도움이 되기를 바랍니다.데이터를 사용하여 수행하려는 작업에 대한 추가 배경 정보를 제공하면 나(또는 다른 사람)가 더 나은 방향을 제공할 수 있습니다.

다른 팁

Plancake PHP 이메일 파서를 사용해 보세요:https://github.com/plancake/official-library-php-email-parser

나는 그것을 내 프로젝트에 사용했습니다.그것은 훌륭하게 작동하며 단지 하나의 클래스이며 오픈 소스입니다.

나는 이것을 함께 엮었습니다. 일부 코드는 내 것이 아니지만 어디서 왔는지 모르겠습니다 ...나중에 더 강력한 "MimeMailParser"를 채택했지만 이것은 잘 작동합니다. cPanel을 사용하여 기본 이메일을 여기에 연결하면 훌륭하게 작동합니다.

#!/usr/bin/php -q
<?php
// Config
$dbuser = 'emlusr';
$dbpass = 'pass';
$dbname = 'email';
$dbhost = 'localhost';
$notify= 'services@.com'; // an email address required in case of errors
function mailRead($iKlimit = "") 
    { 
        // Purpose: 
        //   Reads piped mail from STDIN 
        // 
        // Arguements: 
        //   $iKlimit (integer, optional): specifies after how many kilobytes reading of mail should stop 
        //   Defaults to 1024k if no value is specified 
        //     A value of -1 will cause reading to continue until the entire message has been read 
        // 
        // Return value: 
        //   A string containing the entire email, headers, body and all. 

        // Variable perparation         
            // Set default limit of 1024k if no limit has been specified 
            if ($iKlimit == "") { 
                $iKlimit = 1024; 
            } 

            // Error strings 
            $sErrorSTDINFail = "Error - failed to read mail from STDIN!"; 

        // Attempt to connect to STDIN 
        $fp = fopen("php://stdin", "r"); 

        // Failed to connect to STDIN? (shouldn't really happen) 
        if (!$fp) { 
            echo $sErrorSTDINFail; 
            exit(); 
        } 

        // Create empty string for storing message 
        $sEmail = ""; 

        // Read message up until limit (if any) 
        if ($iKlimit == -1) { 
            while (!feof($fp)) { 
                $sEmail .= fread($fp, 1024); 
            }                     
        } else { 
            while (!feof($fp) && $i_limit < $iKlimit) { 
                $sEmail .= fread($fp, 1024); 
                $i_limit++; 
            }         
        } 

        // Close connection to STDIN 
        fclose($fp); 

        // Return message 
        return $sEmail; 
    }  
$email = mailRead();

// handle email
$lines = explode("\n", $email);

// empty vars
$from = "";
$subject = "";
$headers = "";
$message = "";
$splittingheaders = true;
for ($i=0; $i < count($lines); $i++) {
    if ($splittingheaders) {
        // this is a header
        $headers .= $lines[$i]."\n";

        // look out for special headers
        if (preg_match("/^Subject: (.*)/", $lines[$i], $matches)) {
            $subject = $matches[1];
        }
        if (preg_match("/^From: (.*)/", $lines[$i], $matches)) {
            $from = $matches[1];
        }
        if (preg_match("/^To: (.*)/", $lines[$i], $matches)) {
            $to = $matches[1];
        }
    } else {
        // not a header, but message
        $message .= $lines[$i]."\n";
    }

    if (trim($lines[$i])=="") {
        // empty line, header section has ended
        $splittingheaders = false;
    }
}

if ($conn = @mysql_connect($dbhost,$dbuser,$dbpass)) {
  if(!@mysql_select_db($dbname,$conn))
    mail($email,'Email Logger Error',"There was an error selecting the email logger database.\n\n".mysql_error());
  $from    = mysql_real_escape_string($from);
  $to    = mysql_real_escape_string($to);
  $subject = mysql_real_escape_string($subject);
  $headers = mysql_real_escape_string($headers);
  $message = mysql_real_escape_string($message);
  $email   = mysql_real_escape_string($email);
  $result = @mysql_query("INSERT INTO email_log (`to`,`from`,`subject`,`headers`,`message`,`source`) VALUES('$to','$from','$subject','$headers','$message','$email')");
  if (mysql_affected_rows() == 0)
    mail($notify,'Email Logger Error',"There was an error inserting into the email logger database.\n\n".mysql_error());
} else {
  mail($notify,'Email Logger Error',"There was an error connecting the email logger database.\n\n".mysql_error());
}
?>

시도해 볼 수 있는 Mailparse 기능은 다음과 같습니다. http://php.net/manual/en/book.mailparse.php, 그러나 기본 PHP conf에는 없습니다.

원시 이메일 메시지를 PHP 배열로 구문 분석하는 라이브러리가 있습니다. http://flourishlib.com/api/fMailbox#parseMessage.

정적 메소드 parsemessage ()를 사용하여 전체 마임 전자 메일 메시지를 let

$ parsed_message = fmailbox :: parsemessage (file_get_contents ( '/path/to/email'));

다음은 구문 분석된 메시지의 예입니다.

array(
    'received' => '28 Apr 2010 22:00:38 -0400',
    'headers'  => array(
        'received' => array(
            0 => '(qmail 25838 invoked from network); 28 Apr 2010 22:00:38 -0400',
            1 => 'from example.com (HELO ?192.168.10.2?) (example) by example.com with (DHE-RSA-AES256-SHA encrypted) SMTP; 28 Apr 2010 22:00:38 -0400'
        ),
        'message-id' => '<4BD8E815.1050209@flourishlib.com>',
        'date' => 'Wed, 28 Apr 2010 21:59:49 -0400',
        'from' => array(
            'personal' => 'Will Bond',
            'mailbox'  => 'tests',
            'host'     => 'flourishlib.com'
        ),
        'user-agent'   => 'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.9) Gecko/20100317 Thunderbird/3.0.4',
        'mime-version' => '1.0',
        'to' => array(
            0 => array(
                'mailbox' => 'tests',
                'host'    => 'flourishlib.com'
            )
        ),
        'subject' => 'This message is encrypted'
    ),
    'text'      => 'This message is encrypted',
    'decrypted' => TRUE,
    'uid'       => 15
);

이것 https://github.com/zbateson/MailMimeParser 저에게 효과적이며 mailparse 확장이 필요하지 않습니다.

<?php
echo $message->getHeaderValue('from');          // user@example.com
echo $message
    ->getHeader('from')
    ->getPersonName();                          // Person Name
echo $message->getHeaderValue('subject');       // The email's subject

echo $message->getTextContent();                // or getHtmlContent

Pear lib Mail_mimeDecode는 여기에서 볼 수 있는 일반 PHP로 작성되었습니다. Mail_mimeDecode 소스

아마도 자신만의 MIME 파서를 작성하는 것이 그리 즐겁지 않을 것입니다."과도하게 개발된 메일 처리 패키지"를 찾는 이유는 MIME이 정말 복잡한 규칙/형식/인코딩 세트이기 때문입니다.MIME 부분은 재귀적일 수 있으며 이는 재미의 일부입니다.가장 좋은 방법은 가능한 최고의 MIME 처리기를 작성하고, 메시지를 구문 분석하고, text/plain 또는 text/html이 아닌 모든 것을 버리고, 들어오는 문자열의 명령에 COMMAND 접두사가 붙도록 강제하는 것입니다.또는 유사한 것 등을 사용하여 진흙에서 찾을 수 있습니다.이와 같은 규칙으로 시작하면 새로운 공급자를 처리할 수 있는 적절한 기회가 있지만 새 공급자가 나타나면 조정할 준비가 되어 있어야 합니다(또는 현재 공급자가 메시징 아키텍처를 변경하기로 선택한 경우).

PHP에서 이메일을 구문 분석하는 것은 불가능한 작업이 아닙니다.내 말은, 이를 수행하기 위해 엔지니어 팀이 필요하지 않다는 것입니다.개인으로서 달성 가능합니다.제가 찾은 가장 어려운 부분은 IMAP BODYSTRUCTURE 결과를 구문 분석하기 위해 FSM을 만드는 것이었습니다.인터넷 어디에서도 이 내용을 본 적이 없어서 직접 썼습니다.내 루틴은 기본적으로 명령 출력에서 ​​중첩된 배열의 배열을 생성하며 배열의 깊이는 대략 조회를 수행하는 데 필요한 부품 번호에 해당합니다.따라서 중첩된 MIME 구조를 매우 우아하게 처리합니다.

문제는 PHP의 기본 imap_* 함수가 그다지 세분화된 기능을 제공하지 않는다는 것입니다... 그래서 IMAP 포트에 대한 소켓을 열고 필요한 정보를 보내고 검색하는 함수를 작성해야 했습니다(IMAP FETCH 1 BODY.PEEK[1.2] 예를 들어) RFC 문서를 살펴보는 것이 포함됩니다.

데이터 인코딩(quoted-printable, base64, 7bit, 8bit 등), 메시지 길이, 콘텐츠 유형 등모든 것이 귀하에게 제공됩니다.첨부 파일, 텍스트, HTML 등의 경우모든 필드가 항상 100% 구현되는 것은 아니기 때문에 메일 서버의 미묘한 차이도 파악해야 할 수도 있습니다.

보석은 FSM입니다... Comp Sci에 대한 배경 지식이 있다면 이것을 만드는 것이 정말 재미있을 수 있습니다(핵심은 괄호가 일반 문법이 아니라는 것입니다;)).그렇지 않으면 전통적인 방법을 사용하면 어려움을 겪거나 보기 흉한 코드가 생성될 것입니다.또한 시간이 필요합니다!

도움이 되었기를 바랍니다!

이것이 당신에게 도움이 될지 확신할 수 없습니다. 그러기를 바랍니다. 그러나 이메일에 대해 더 많은 것을 알고 싶어하는 다른 사람들에게는 확실히 도움이 될 것입니다. 마커스 보인턴 올해 3월 PHP 런던 컨퍼런스에서 "Mail()과 Mail() 이후의 삶"이라는 제목의 최고의 프레젠테이션을 선보였습니다. 슬라이드 그리고 MP3 온라인 상태입니다.그는 이메일과 PHP를 심층적으로 다루면서 어느 정도 권위를 갖고 있습니다.

내 생각에는 당신이 진정한 일반 파서를 작성하는 데 어려움을 겪고 있는 것 같습니다.

편집 - PHP London 사이트에서 파일이 제거된 것 같습니다.마커스의 슬라이드를 찾았어요 자신의 사이트: 1 부 2 부 MP3를 어디서도 볼 수 없었어요

예, 저는 해당 rfc 및 기타 기본 튜토리얼을 기반으로 기본 파서를 작성할 수 있었습니다.하지만 나를 계속 혼란스럽게 만드는 다중 부분 마임 중첩 경계입니다.

내 휴대전화에서 보낸 MMS(SMS 아님) 메시지는 표준 이메일일 뿐이라는 것을 알았기 때문에 수신 이메일을 읽고 발신자를 확인하고(내 휴대전화에서만 허용하도록) 신체 부위를 사용하여 다른 이메일을 실행하는 시스템이 있습니다. 내 서버의 명령.이메일을 통한 원격 제어와 비슷합니다.

시스템은 사진을 전송하도록 설계되었기 때문에 다르게 인코딩된 부분이 많이 있습니다.mms.smil.txt 부분, text/plain(쓸모가 없습니다. '이것은 html 메시지입니다'라고만 표시됨), application/smil 부분(전화기가 인식하는 부분), text/html 부분 내 이동통신사에 대한 광고, 내 메시지, 모두 html로 포장된 다음 마지막으로 내 일반 메시지가 포함된 텍스트 파일 첨부 파일(내가 사용하는 부분)(이미지를 메시지의 첨부 파일로 밀어 넣으면 다음 위치에 놓입니다.) 첨부 파일 1, base64로 인코딩된 경우 내 텍스트 부분이 첨부 파일 2로 첨부됩니다.

내 이동통신사의 정확한 메일 형식으로 작업했지만 다른 사람의 전화에서 메시지를 실행했을 때 여러 가지 비참한 방식으로 실패했습니다.

나는 이 전화->메일->분석->명령 시스템을 확장하고 싶은 다른 프로젝트가 있지만, 그것을 사용하기 위해 메일에서 다른 부분을 가져오려면 안정적인/단단한/일반 파서가 필요합니다.

내 최종 목표는 원시 파이프 메일을 공급할 수 있는 기능을 갖고 헤더 var:val 쌍의 연관 하위 배열과 본문 텍스트에 대한 전체 문자열을 포함하는 큰 배열을 다시 가져오는 것입니다.

이것에 대해 점점 더 많이 검색할수록 같은 것을 더 많이 발견합니다.메일과 관련된 모든 작업을 수행하는 거대하고 과도하게 개발된 메일 처리 패키지 또는 (이 프로젝트에서는 나에게) 쓸모없는 튜토리얼입니다.

내 생각에는 총알을 물리고 조심스럽게 내 자신을 써야 할 것 같아요.

이 라이브러리는 매우 잘 작동합니다.

http://www.phpclasses.org/package/3169-PHP-Decode-MIME-e-mail-messages.html

동일한 문제가 발생하여 다음 클래스를 작성했습니다.이메일_파서.원시 이메일을 가져와서 멋진 객체로 바꿔줍니다.

PEAR Mail_mimeDecode가 필요하지만 WHM을 통해 또는 명령줄에서 바로 쉽게 설치할 수 있습니다.

여기에서 받으세요: https://github.com/optimumweb/php-email-reader-parser

간단한 PhpMimeParser https://github.com/breakermind/PhpMimeParser Yuo는 파일, 문자열에서 MIME 메시지를 잘라낼 수 있습니다.파일, HTML 및 인라인 이미지를 가져옵니다.

$str = file_get_contents('mime-mixed-related-alternative.eml');

// MimeParser
$m = new PhpMimeParser($str);

// Emails
print_r($m->mTo);
print_r($m->mFrom);

// Message
echo $m->mSubject;
echo $m->mHtml;
echo $m->mText;

// Attachments and inline images
print_r($m->mFiles);
print_r($m->mInlineList);
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top