سؤال

أنا أبحث عن كود php جيد/عمل/سهل الاستخدام لتحليل البريد الإلكتروني الأولي إلى أجزاء.

لقد كتبت اثنين من حلول القوة الغاشمة، ولكن في كل مرة، يأتي تغيير صغير/رأس/مساحة/شيء ما ويفشل المحلل اللغوي بالكامل وينهار المشروع.

وقبل أن أشير إلى PEAR/PECL، أحتاج إلى رمز فعلي.لدى مضيفي بعض التكوينات الخاطئة أو شيء من هذا القبيل، لا يبدو أنني تمكنت من إنشاء .so بشكل صحيح.إذا حصلت على .so، فإن بعض الاختلاف في المسار/البيئة/php.ini لا يجعله متاحًا دائمًا (Apache vs cron vs cli).

أوه، وشيء أخير، أقوم بتحليل نص البريد الإلكتروني الأولي، وليس POP3، وليس IMAP.يتم نقله إلى البرنامج النصي php عبر إعادة توجيه البريد الإلكتروني .qmail.

لا أتوقع أن تكتبها قوات العمليات الخاصة لي، فأنا أبحث عن بعض النصائح/نقاط البداية للقيام بذلك "بشكل صحيح".هذه إحدى مشكلات "العجلة" التي أعلم أنه تم حلها بالفعل.

هل كانت مفيدة؟

المحلول

ما الذي تأمل أن ينتهي بك الأمر إليه في النهاية؟الجسد، الفاعل، المرسل، المرفق؟يجب أن تقضي بعض الوقت مع RFC2822 لفهم تنسيق البريد، ولكن إليك أبسط القواعد لبريد إلكتروني جيد التصميم:

HEADERS\n
\n
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 تقريبًا MIME مشفرة.قد يكون هذا نصًا مشفرًا uuuencoded، أو قد يكون html، أو جدول بيانات Excel مشفرًا uuencoded.

آمل أن يساعد هذا في توفير إطار عمل لفهم بعض مجموعات البريد الإلكتروني الأساسية.إذا قدمت مزيدًا من المعلومات الأساسية حول ما تحاول القيام به بالبيانات، فقد أتمكن (أو أي شخص آخر) من تقديم توجيه أفضل.

نصائح أخرى

جرب محلل البريد الإلكتروني 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 () لتحليل رسالة بريد إلكتروني كاملة mime في نفس التنسيق الذي يعيده FetchMessage () ، ناقص مفتاح UID.

$ 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 يمكنك تحليل رسالة والتخلص من كل ما هو ليس نص/عادي أو نص/html، ثم فرض الأمر في السلسلة الواردة ليكون مسبوقًا بـ COMMAND:أو شيء مشابه حتى تجده في الوحل.إذا بدأت بقواعد من هذا القبيل، فلديك فرصة جيدة للتعامل مع مقدمي الخدمة الجدد، ولكن يجب أن تكون مستعدًا للتعديل إذا جاء مزود جديد (أو إذا اختار مزود الخدمة الحالي تغيير بنية المراسلة الخاصة به).

تحليل البريد الإلكتروني في PHP ليس مهمة مستحيلة.ما أعنيه هو أنك لا تحتاج إلى فريق من المهندسين للقيام بذلك؛يمكن تحقيقه كفرد.حقًا كان الجزء الأصعب الذي وجدته هو إنشاء FSM لتحليل نتيجة IMAP BODYSTRUCTURE.لم أر هذا في أي مكان على الإنترنت، لذلك كتبت كتابي الخاص.يقوم روتيني بشكل أساسي بإنشاء مصفوفة من المصفوفات المتداخلة من إخراج الأمر، ويتوافق العمق الموجود في المصفوفة تقريبًا مع رقم (أرقام) الجزء المطلوب لإجراء عمليات البحث.لذلك فهو يتعامل مع هياكل MIME المتداخلة بأمان تام.

تكمن المشكلة في أن وظائف imap_* الافتراضية في PHP لا توفر قدرًا كبيرًا من التفاصيل... لذا اضطررت إلى فتح مأخذ توصيل لمنفذ IMAP وكتابة الوظائف لإرسال واسترجاع المعلومات الضرورية (IMAP FETCH 1 BODY.PEEK[1.2] على سبيل المثال)، ويتضمن ذلك النظر في وثائق RFC.

ترميز البيانات (قابلة للطباعة، وbase64، و7 بت، و8 بت، وما إلى ذلك)، وطول الرسالة، ونوع المحتوى، وما إلى ذلك.يتم توفير كل شيء لك.للمرفقات والنصوص وhtml وما إلى ذلك.قد يتعين عليك معرفة الفروق الدقيقة في خادم البريد الخاص بك أيضًا نظرًا لعدم تنفيذ جميع الحقول دائمًا بنسبة 100%.

الجوهرة هي FSM... إذا كان لديك خلفية في Comp Sci، فقد يكون من الممتع حقًا القيام بذلك (المفتاح هو أن الأقواس ليست قواعد نحوية عادية؛))؛وإلا فسيكون الأمر بمثابة صراع و/أو يؤدي إلى تعليمات برمجية قبيحة باستخدام الطرق التقليدية.كما أنك تحتاج إلى بعض الوقت!

أتمنى أن يساعدك هذا!

لست متأكدًا مما إذا كان هذا سيساعدك - آمل ذلك - ولكنه سيساعد بالتأكيد الآخرين المهتمين بمعرفة المزيد عن البريد الإلكتروني. ماركوس بوينتون قام بأحد أفضل العروض التقديمية بعنوان "Mail() and life after Mail()" في مؤتمر PHP London في مارس من هذا العام الشرائح و MP3 على الانترنت.إنه يتحدث بقدر من السلطة، حيث عمل على نطاق واسع مع البريد الإلكتروني وPHP على مستوى عميق.

تصوري هو أنك في عالم من الألم تحاول كتابة محلل عام حقًا.

تحرير - يبدو أن الملفات قد تمت إزالتها من موقع PHP London؛وجدت الشرائح على ماركوس الموقع الخاص: الجزء 1 الجزء 2 لم أتمكن من رؤية MP3 في أي مكان بالرغم من ذلك

نعم، لقد تمكنت من كتابة محلل أساسي، استنادًا إلى RFC وبعض البرامج التعليمية الأساسية الأخرى.لكن الحدود المتداخلة متعددة الأجزاء هي التي تفسدني باستمرار.

اكتشفت أن رسائل الوسائط المتعددة (وليست الرسائل القصيرة) المرسلة من هاتفي هي مجرد رسائل بريد إلكتروني قياسية، لذلك لدي نظام يقرأ البريد الإلكتروني الوارد، ويتحقق من (للسماح فقط من هاتفي)، ويستخدم الجزء الأساسي لتشغيل مختلف الأوامر على الخادم الخاص بي.إنه يشبه جهاز التحكم عن بعد عبر البريد الإلكتروني.

نظرًا لأن النظام مصمم لإرسال الصور، فهو يحتوي على مجموعة من الأجزاء المشفرة بشكل مختلف.جزء mms.smil.txt، ونص/عادي (وهو أمر عديم الفائدة، يقول فقط "هذه رسالة html")، وجزء تطبيق/smil (وهو الجزء الذي ستلتقطه الهواتف)، وجزء نص/html مع إعلان لشركة الاتصالات الخاصة بي، ثم رسالتي، ولكن كلها ملفوفة بتنسيق html، ثم أخيرًا مرفق ملف نصي مع رسالتي العادية (وهو الجزء الذي أستخدمه) (إذا قمت بإدخال صورة كمرفق في الرسالة، فسيتم وضعها في المرفق 1، مشفر بالأساس 64، ثم يتم إرفاق جزء النص الخاص بي كمرفق 2)

لقد جعلته يعمل مع تنسيق البريد الدقيق من مشغل شبكة الجوال الخاص بي، ولكن عندما قمت بتشغيل رسالة من هاتف شخص آخر من خلاله، فشل ذلك بمجموعة كاملة من الطرق البائسة.

لدي مشاريع أخرى أرغب في توسيع نطاق هذا الهاتف->البريد->تحليل->نظام الأوامر إليه، لكني بحاجة إلى محلل مستقر/صلب/عام لإخراج الأجزاء المختلفة من البريد لاستخدامه.

سيكون هدفي النهائي هو الحصول على وظيفة يمكنني من خلالها تغذية البريد الخام عبر الأنابيب واستعادة مصفوفة كبيرة تحتوي على مصفوفات فرعية ترابطية من أزواج الرؤوس var:val وواحدة للنص الأساسي كسلسلة كاملة

كلما بحثت أكثر عن هذا، كلما وجدت نفس الشيء:حزم التعامل مع البريد العملاقة والمتطورة التي تفعل كل شيء تحت الشمس فيما يتعلق بالبريد، أو البرامج التعليمية عديمة الفائدة (بالنسبة لي، في هذا المشروع).

أعتقد أنه سيتعين علي أن أعض الرصاصة وأكتب شيئًا بنفسي بعناية.

تعمل هذه المكتبة بشكل جيد للغاية:

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

واجهت نفس المشكلة لذلك كتبت الفصل التالي:Email_Parser.فهو يأخذ بريدًا إلكترونيًا خامًا ويحوله إلى شيء جميل.

يتطلب الأمر PEAR Mail_mimeDecode ولكن يجب أن يكون من السهل تثبيته عبر WHM أو مباشرة من سطر الأوامر.

أحضره هنا : https://github.com/optimumweb/php-email-reader-parser

بسيط PhpMimeParser https://github.com/breakermind/PhpMimeParser يمكن لـ Yuo قطع رسائل التمثيل الصامت من الملفات والسلاسل.احصل على الملفات و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