简体   繁体   中英

Create directories and write files using PHP from a sendmail pipe to program

I have a script that reads emails (with attachments) from a pipe and I'm trying to save the attachment(s) to disk for further processing. I've cobbled together some code from a few sites and for the life of me I cannot get the files to save. I'm using 777 as the chmod value so permissions don't seem to be a problem but I wanted to know if maybe I'm limited to certain PHP commands when using the command line processor rather than the browser. Also, I've even hardcoded the "include" directories in the event the file is not executed from the directory where it is located. Any help would be greatly appreciated!

#!/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);

Update: Thanks for the informative response...I've been trying to figure out how to run from the command line. I'm getting some errors now, but they still don't make much sense:

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

I have already specified the full include path to the other files and the smmta user should have read access as the /var/www/ directory is 755.

Using 0777 permissions on the mkdir command in your script does not matter at all if the user that the script is running under cannot write to your target directory. So, if this script is running as used sendmail for example, make sure that this user can write to /var/www/tmp .

Some debugging tips: Get a complete e-mail and save it to a file. Figure out what user this script runs as (eg sendmail ). Then execute the script manually from the commandline and watch for errors. Eg:

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

Make sure you have error reporting turned on etc.

Edit: Looking at the errors you posted, it seems that the mime decoder cannot properly parse your message the way you're expecting it. You appear not to be doing any error checking, so instead you get notices and warnings about undefined indexes.

Check in the input and output of the decoder. Make sure the message is decoded the way you expect it to be.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM