0

I am attempting to write some tests for an email parser I am building and having trouble getting started.

For normal operation an email will be piped to the script, but for the tests I want to simulate the piping action : )

My test is starting out like this:

#!/opt/php70/bin/php
<?php

define('INC_ROOT', dirname(__DIR__));

$script = INC_ROOT . '/app/email_parser.php';

//$email = file_get_contents(INC_ROOT . '/tests/test_emails/test.email');
$email = INC_ROOT . '/tests/test_emails/test.email';

passthru("{$script}<<<{$email}");

With the script as is, the only thing passed to stdin is the path to the test email. When using file_get_contents I get:

sh: -c: line 0: syntax error near unexpected token '('
sh: -c: line 0: /myscriptpath/app/email_parser.php<<<TestEmailContents

Where TestEmailContents is the contents of the raw email file. I feel like I have executed scripts in this manner in the past using the heredoc operator to pass data into stdin. But for the last few days I have been unable to find any information to get me past this stumbling block. Any advice will be mucho appreciado!

1
  • It looks like redirecting with the heredoc operator (<<<) is not necessary when executing the script. Am having better luck with the single redirect operator (<). Commented Oct 29, 2016 at 2:33

2 Answers 2

1

The syntax error experienced was exactly that. To get the file contents and pass it in as a here string I needed to single quote the string:

$email = file_get_contents(INC_ROOT . '/tests/test_emails/test.email');

passthru("{$script} <<< '{$email}'");

But, in my case passing in a raw email did not require the use of a here string. The line endings are preserved either way. Redirecting the file to the script yielded the same results.

$email = INC_ROOT . '/tests/test_emails/test.email';

passthru("{$script} < {$email}");
Sign up to request clarification or add additional context in comments.

3 Comments

very interesting. Found your thread because i need to do the same thing. I have a script that parses incoming emails and it works fine - I don't want to touch it. However I want to write another script that reads all files from a certain Inbox and passes each file/email to the parsing script to go through all the past emails (that came in before the parsing script was implemented). I know this is old, but any chance you still have the final solution?
I used both methods above and in both cases the raw emails being processed did so cleanly 50% of the time, the other 50% I got errors similar to your OP. Someone suggested doing base64_encode(file_get_contents('emailFile')) and that eliminated all the errors, however it also caused a problem with my parsing script failing explode the STDIN into individual lines - instead of 200+ lines per email to loop through, each email was now two lines, and as a result nothing was captured.
Correction! Your second one, passthru("{$script} < {$email}") ; worked just fine, turns out my $email had a typo in it.
0

To read stdin in PHP you can use php://stdin filename: $content = file_get_contents('php://stdin'); or $f = fopen('php://stdin', 'r');.

To pass a string to an invoked process you have two options: popen or proc_open. The popen function is easier to use, but it has limited use. The proc_open is a bit more complicated, but gives you much finer control of stdio redirection.

Both function give you file handle(s) on which you can use fwrite and fread. In your case the popen should be good enough (simplified):

$f = popen('./script.php', 'w');
fwrite($f, file_get_contents('test.email'));
pclose($f);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.