使用 PHP 从 sendmail 管道创建目录并写入文件以进行编程

Posted

技术标签:

【中文标题】使用 PHP 从 sendmail 管道创建目录并写入文件以进行编程【英文标题】:Create directories and write files using PHP from a sendmail pipe to program 【发布时间】:2011-05-11 04:38:00 【问题描述】:

我有一个从管道读取电子邮件(带有附件)的脚本,我正在尝试将附件保存到磁盘以供进一步处理。我拼凑了一些来自几个站点的代码,并且在我的一生中,我无法保存文件。我使用 777 作为 chmod 值,因此权限似乎不是问题,但我想知道在使用命令行处理器而不是浏览器时是否可能仅限于某些 php 命令。此外,如果文件不是从它所在的目录执行,我什至硬编码了“包含”目录。任何帮助将不胜感激!

#!/usr/bin/php
<?php
//debug
#ini_set ("display_errors", "1");
#error_reporting(E_ALL);

include('/var/www/simple_html_dom.php');

//include email parser
require_once('/var/www/rfc822_addresses.php');
require_once('/var/www/mime_parser.php');

// read email in from stdin
$fd = fopen("php://stdin", "r");
$email = "";
while (!feof($fd)) 
    $email .= fread($fd, 1024);

fclose($fd);

//create the email parser class
$mime=new mime_parser_class;
$mime->ignore_syntax_errors = 1;
$parameters=array(
    'Data'=>$email,
);

$mime->Decode($parameters, $decoded);

//---------------------- GET EMAIL HEADER INFO -----------------------//

//get the name and email of the sender
$fromName = $decoded[0]['ExtractedAddresses']['from:'][0]['name'];
$fromEmail = $decoded[0]['ExtractedAddresses']['from:'][0]['address'];

//get the name and email of the recipient
$toEmail = $decoded[0]['ExtractedAddresses']['to:'][0]['address'];
$toName = $decoded[0]['ExtractedAddresses']['to:'][0]['name'];

//get the subject
$subject = $decoded[0]['Headers']['subject:'];

$removeChars = array('<','>');

//get the message id
$messageID = str_replace($removeChars,'',$decoded[0]['Headers']['message-id:']);

//get the reply id
//$replyToID = str_replace($removeChars,'',$decoded[0]['Headers']['in-reply-to:']);

//---------------------- FIND THE BODY -----------------------//

//get the message body
if(substr($decoded[0]['Headers']['content-type:'],0,strlen('text/plain')) == 'text/plain' && isset($decoded[0]['Body']))

    $body = $decoded[0]['Body'];

 elseif(substr($decoded[0]['Parts'][0]['Headers']['content-type:'],0,strlen('text/plain')) == 'text/plain' && isset($decoded[0]['Parts'][0]['Body'])) 

    $body = $decoded[0]['Parts'][0]['Body'];

 elseif(substr($decoded[0]['Parts'][0]['Parts'][0]['Headers']['content-type:'],0,strlen('text/plain')) == 'text/plain' && isset($decoded[0]['Parts'][0]['Parts'][0]['Body'])) 

    $body = $decoded[0]['Parts'][0]['Parts'][0]['Body'];


    $my_dir = base64_encode($fromEmail);
    shell_exec('mkdir -p /var/www/tmp/' . $my_dir . ' -m 777');
    //mkdir($_SERVER['DOCUMENT_ROOT'] . "tmp/" . $my_dir, 0777, true);

    $target_path = "var/www/tmp/" . $my_dir;
    //chdir($target_path);

    //------------------------ ATTACHMENTS ------------------------------------//

//loop through email parts
foreach($decoded[0]['Parts'] as $part)

    //check for attachments
    if($part['Content-Disposition'] == 'attachment')

        //format file name (change spaces to underscore then remove anything that isn't a letter, number or underscore)
        $filename = preg_replace('/[^0-9,a-z,\.,_]*/i','',str_replace(' ','_', $part['FileName']));

        // write the data to the file
        $fp = fopen($target_path . "/" . $filename, 'w');
        $written = fwrite($fp,$part['Body']);
        fclose($fp);

        //add file to attachments array
        $attachments[] = $part['FileName'];

    



$html = file_get_html($attachments);

更新:感谢您提供信息丰富的回复...我一直在尝试弄清楚如何从命令行运行。我现在遇到了一些错误,但它们仍然没有多大意义:

PHP Notice:  Undefined index: name in /var/www/catcher.php on line 38
PHP Notice:  Undefined index: Content-Disposition in /var/www/catcher.php on line 80
PHP Notice:  Undefined index: Content-Disposition in /var/www/catcher.php on line 80
PHP Notice:  Undefined variable: attachments in /var/www/catcher.php on line 97
PHP Warning:  file_get_contents(): Filename cannot be empty in /var/www/simple_html_dom.php on line 39

我已经指定了其他文件的完整包含路径,并且 smmta 用户应该具有读取权限,因为 /var/www/ 目录是 755。

【问题讨论】:

这个脚本有什么问题吗?当某事有效时不解决它 print_r($decoded) 看看发生了什么。错误说您缺少名称,内容处置名称可能来自:$decoded[0]['ExtractedAddresses']['from:'][0]['name']; 【参考方案1】:

如果运行脚本的用户无法写入目标目录,则在脚本中对mkdir 命令使用0777 权限根本没有关系。因此,如果此脚本以 sendmail 的使用方式运行,请确保该用户可以写入 /var/www/tmp

一些调试提示:获取完整的电子邮件并将其保存到文件中。找出这个脚本以什么用户身份运行(例如sendmail)。然后从命令行手动执行脚本并观察错误。例如:

sudo -u sendmail /path/to/script.php < /path/to/saved-email.eml

确保您已开启错误报告等功能。

编辑:查看您发布的错误,mime 解码器似乎无法按照您预期的方式正确解析您的消息。您似乎没有进行任何错误检查,因此您会收到有关未定义索引的通知和警告。

检查解码器的输入和输出。确保消息以您期望的方式解码。

【讨论】:

有趣的是,我正在使用来自http://www.phpclasses.org/package/3169-PHP-Decode-MIME-e-mail-messages.html 的似乎非常成熟的类,虽然代码中有错误消息,但似乎并没有抛出它们。此外,他的测试脚本不适用于我使用 Gmail 的基本测试消息。对其他课程有什么建议吗?

以上是关于使用 PHP 从 sendmail 管道创建目录并写入文件以进行编程的主要内容,如果未能解决你的问题,请参考以下文章

php.ini,sendmail 配置使用 php 脚本发送电子邮件

PHP、postfix、sendmail、thunderbird 仅适用于本地开发者

PHP 直接通过sendmail从PHP发送多部分/替代(文本和html一起)电子邮件

怎么利用php发送邮件求详细教程

phpmailer / sendmail返回错误“对等连接重置”

php 使用sendmail发送邮件