PDA

View Full Version : Sendmail gives error only when invoked via apache




SSmagicman
May 5, 2011, 01:02 PM
Hi,

I have a bash script that used sendmail to send a simple e-mail...

-------------------------------------------------------------------------------- ---------------------------
DistributionList=`/usr/libexec/PlistBuddy -c "Print :EmailDistributionList" /Library/WebServer/Documents/server_settings.plist`;
MessageFile="/tmp/build_failure_email.txt";

if [ -e $MessageFile ];
then
rm $MessageFile
fi

#echo "To: $DistributionList" >> $MessageFile;

Subject="My Subject...";
echo "Subject: ${Subject}" >> $MessageFile;

FromName="My Name";
FromAddress="me@mydomain.com";
echo "From: $FromName <${FromAddress}>" >> $MessageFile;


echo "Message Body line 1..." >> $MessageFile;
echo "Message Body line 2." >> $MessageFile;

/usr/sbin/sendmail "$DistributionList" < $MessageFile
#/usr/sbin/sendmail -t "$DistributionList" < $MessageFile

-------------------------------------------------------------------------------- ---------------------------

When I run this script from the command line it works perfectly fine! No errors, and I get the e-mail, all is good in the world. Now If I have a webpage running out of /Library/WebServer/Documents and have a php file there that invokes the script, then it outputs the following error:

SendMail: fatal: Recipient addresses must be specified on the command line or via the -t option

Note, apache is running as an administrative user (the same user that I manually called the script from when it worked). As you can see I AM specifying the address on the command line, and I have also tried it with -t and putting the address in the file. But neither way works when the bash script is called from apache by way of the PHP script. I have spent hours trying to figure this out with no luck. Can anyone provide any pointers?

THANKS!



willieva
May 5, 2011, 02:15 PM
It looks like the DistributionList isn't getting filled in. Print that out prior to the sendmail call to see what is happening.

It's always a good idea to start a bash script with #!/bin/bash so you're sure it's being run as a bash script.

kainjow
May 5, 2011, 02:16 PM
I don't know why it's not working, but why not use PHP's mail() function to send the email instead (which uses sendmail)?

ulbador
May 5, 2011, 02:35 PM
There would be two main things that would cause this to fail.

First, the proper environment variables. This seems not to be the case because everything has a full path on it.

The second and more likely problem, is some sort of permission error. Does whatever user the apache process is running as have the right permission to run that? You can test it with something like "su _www /pathToMyScript".

That may not work without setting a login shell for the apache user, so edit the /etc/passwd entry for the apache user (or whatever user your Apache is running as, I believe the default is _www on OSX) and temporarily change it from probably /usr/bin/false to /bin/sh (don't forget to change it back)

Finally, the -t option tells it to parse the message to figure out who to send it to. So with:

/usr/sbin/sendmail -t < $MessageFile

$MessageFile would have to contain like:


To: Me@me.com
From: You@you.com
Subject: Hello

World

SSmagicman
May 5, 2011, 02:38 PM
It looks like the DistributionList isn't getting filled in. Print that out prior to the sendmail call to see what is happening.

It's always a good idea to start a bash script with #!/bin/bash so you're sure it's being run as a bash script.

DistributionList gets filled in OK. I printed it out. And I also replaced it with a single address hard-coded. Again, the same script run from the Terminal works, but when called from the web interface doesn't.

Also, I just included a small section of the script here which is why the #!/bin/bash is missing, the whole thing spans multiple files and is dozens of pages long. But thanks for the suggestions.

I don't know why it's not working, but why not use PHP's mail() function to send the email instead (which uses sendmail)?

I am building a web interface to run a series of shell scripts that reside on the server. The bash script are written such that they can be used independently for the task they are meant for, or the same scripts can be run from this web UI. The scripts are mostly for doing software builds, testing, and uploading to another server. So moving any of the functionality out of the bash script into the webapp really wouldn't work, because then the same script couldn't be used manually to do the same thing.


Finally, the -t option tells it to parse the message to figure out who to send it to. So with:

/usr/sbin/sendmail -t < $MessageFile

$MessageFile would have to contain like:


To: Me@me.com
From: You@you.com
Subject: Hello



Right, as you can see in the code in my original post I had the line commented out that added the To: field to the $MessageFile. But when that line is there, the error is still produced. Or if the to address is provided on the command line the error is still produced. Or if the to address is provided both places the error is still produced.


The second and more likely problem, is some sort of permission error. Does whatever user the apache process is running as have the right permission to run that? You can test it with something like "su _www /pathToMyScript".


Well, my Apache process is already running as my administrative (non-root) user. That is because of other things I do in the scripts. So it is not running as _www. And the script runs fine, its the single command that calls sendmail that produces the error.


That may not work without setting a login shell for the apache user, so edit the /etc/passwd entry for the apache user (or whatever user your Apache is running as, I believe the default is _www on OSX) and temporarily change it from probably /usr/bin/false to /bin/sh (don't forget to change it back)


When I open /etc/passwd the comments at the top say that the file is only used when running in single user mode, which is not the case here. Also I do not see any entry there in the file for any of the Mac OS X users that are listed in the Accounts preference pane, such as the one my script is running as. I do see _www listed there with /usr/bin/false, but again apache isn't running as that user.

chown33
May 5, 2011, 03:23 PM
I am building a web interface to run a series of shell scripts that reside on the server. The bash script are written such that they can be used independently for the task they are meant for, or the same scripts can be run from this web UI. The scripts are mostly for doing software builds, testing, and uploading to another server. So moving any of the functionality out of the bash script into the webapp really wouldn't work, because then the same script couldn't be used manually to do the same thing.

The php interpreter can be run from the command-line. It has a man page, which see.

Change all your uses of $MessageFile to "$MessageFile". Quoting is always good hygiene in shell scripts.

Run the printenv command and the id command to make sure both are what is needed. I realize you've said you've checked those, but having the evidence in a log file is better.

Make sure the home directory for your user id is correct. If some command is looking for config info or defaults in a file, then you could have the correct uid but the wrong $HOME.

Have you tried running the bash script with the -x option? This will cause expanded command-lines to be echoed before being executed. Check to make sure the command-line with -t blah blah is what you expect it to be, and doesn't have any unexpected things like maybe some quoted whitespace that might be misinterpreted as a recipient to sendmail.

To turn on -x in the bash script itself:
set -x


If you still don't see anything, then replace the /usr/sbin/sendmail command in the script with the pathname of a diagnostic shell script that enumerates and prints its cmd-line args, and logs exactly what the contents of its stdin is (the hexdump command may be handy).

I would also suggest that to diagnose the problem it's possible we'd need to see the exact data in the MessageFile. Since that contains email addresses, I'm not asking you to post it. I'm just saying that without an actual fail-case of the actual code being run, on the actual data being processed, all any of us can do is guess.

ulbador
May 5, 2011, 11:22 PM
Right, as you can see in the code in my original post I had the line commented out that added the To: field to the $MessageFile. But when that line is there, the error is still produced. Or if the to address is provided on the command line the error is still produced. Or if the to address is provided both places the error is still produced.

chown is probably right here, without knowing the data, it'll probably be difficult to diagnose.

As one more thing to try, notice the difference between your "sendmail -t" example and the one I quoted. It could potentially be an important difference.

As mentioned by others, you really are probably best off just putting this in a PHP script and executing it via the command-line, unless you have a hugely compelling reason not to. My company has dozens of little scripts that are run from the command-line from Apache, cron and everywhere else that do everything you can think of, and they all work great.

You can even put "#!/usr/bin/php" (or whatever the path to your PHP binary, type 'which php') at the top of your PHP scripts, chmod the x permission, and call your php scripts just like you would a shell script.


system("/home/myName/myPhpScript.php");

vs

system("/usr/bin/php /home/myName/myPhpScript.php");

SSmagicman
May 11, 2011, 11:05 AM
All,

I hate to admit it, but this was actually something really simple.

I had the portion of the script that sent the e-mail in a separate file, that was (supposed to be) sourced at the top of the main script. When I was running the main script interactively from the command line (when everything worked) it worked because I had already manually sourced that other file earlier in the Terminal session. And when apache was calling that other file it didn't work because that file hadn't been sourced yet. The reason it showed up as a sendmail error message was because in that other file I had named the routine that sent the e-mail "SendMail" as opposed to "sendmail" but when that other file wasn't sourced it was calling the normal sendmail program with no parameters -- thus the error.

Multiple mistakes here: 1) naming the separate routine "SendMail" rather than something more unique, 2) not sourcing the other file at the top of the main file.

Thanks for the help.