php mail 'from' header not behaving - php

I have an odd problem.
I have a 'standard' Email include I use that wraps the php mail() function. This has been in use for a few years and in two places in my site is quite happily sending mail every day. However, on re-using the same include in a different part of the same site on the same host, I am finding I cannot send mail including a 'From' header. The only difference is this new sending location on the site is a basic auth-protected directory.
So before people leap in and tell me this or that, remember, this is the exact same code as it working at the same time on the same host and so the exact-same include works in two locations and not the third.
So I set, among other headers (as this carries multipart HTML Email):
$headers = "From: $fromName <$fromEmail>\n";
$headers .= "Reply-To: \"$fromName\" <$fromEmail>\n";
$headers .= "Sender: \"$fromName\" <$fromEmail>\n";
This works fine in two locations on the site, but the inclusion of the 'From' line causes a mail send failure in a third location on the same host. The code also works fine from my dev machine, it's only the Live hosted box that won't send mail from this third location. Now...
Yes I know I'm using "\n" and not "\r\n", but my experience has been
"\r\n" is necessary on Windows hosts but causes problems on *ix
hosts - and yes I know the RFC says CRLF - and so this is 'fixed'
later in the wrapper if it's on a Windows host but left as "\n" on
*ix
No, setting "\r\n" does not make any difference!
I have experiemented with the mail() fifth paramter and using -f, but that
only gives me mail sent on behalf of
The 'Sender' field actually has the effect that on opening the message the recipient sees; From Pretty_name [email_address], however, in Outlook at least, in the mail list the sender is shown as email_address, not 'Pretty_name'
I've experiented with ini-set, but that only sets an Email address and the message is already going with the desired From Email address, it's the 'Pretty_name' that won't work
So remember - the exact same code is runing elsewhere on the same site without any problems, but the issue here seems to be (for a reason I've yet to fathom) that the same code can only be used without the 'From' header from this location.
Anyone any ideas on what seems such inconsistent behaviour?
Thx

First, if mail() returns false, then make sure you output the last error message:
print_r(error_get_last());
If the error message doesn't really indicate much about the email itself, then it's likely something wrong in the php.ini file (e.g. configuration mistake during an upgrade or something). You can test that by isolating the problem code to a separate file, then temporarily swap out the php.ini file for the default one, restart your web server to let the new php.ini take effect, and run your test again (I'd recommend dumping phpinfo() along with your script so you can confirm that the new php.ini is in effect).
Second, use \r\n. I know it has no functional difference in your test here, but it IS the right line ending and using just \n WILL cause problems in some mail servers that actually follow the rules. When you use \n, you are relying on the mail server to have additional code that handles automatic correction of errors.
Using \r\n might cause problems in some poorly-coded servers that DON'T follow the rules, but that's not really your problem to solve. Always follow the RFC.

Related

PHP text messages suddenly sending from a different address

I have a website that sends out text messages from the server. I'm using PHP for it:
$headers = "From: " . "Business Name <info#businessdomain.com>" . "\r\n";
$result = #mail( $to,$subject,$message,$headers);
Up until yesterday, the FRM: was always "Business Name" in the text message.
Suddenly, I'm now getting reports that FRM: is coming in as username#173.222.21.166 where username is my actual FTP account username (real IP not provided of course)!!
I definitely don't want to expose my FTP username. Is there something that would determine the FRM: name other than what I have set? I haven't changed the script at all... and suddenly it has changed.
UPDATE: using PHP mail not SMS Gateway
You can add a command line parameters to php's mail function, one of which is from.
mail($to, $subject, $message, $headers, '-finfo#businessdomain.com');
Note the -f directly infront of your from address
This may be related to the mail server on the local machine or the mail configuration on the local machine. There are certain settings, which can prevent faking the FROM header and substituting it by the actual user running the program that sends the mail.
I recommend checking the mail config for php and for the system itself.

How to remove headers revealing system info when sending mail in php

I am using PHPs mail() function. I've noticed when going through the message (that gets sent) properties that some headers are present which specify
the filename which sent the email
which version of php I'm running
my OS info
I've removed the domain, but this is basically what's included. How can I stop this being included, or am I just being security paranoid? Also, I would like to keep using phps mail function as opposed to setting up something else. Thanks.
X-PHP-Originating-Script: 1000:emailtest.php
From: hidden#hidden.hh
Reply-To: hidden#hidden.hh
X-Mailer: PHP/5.3.10-1ubuntu3.10
Message-Id: <20140315193810.ADD43120489#hidden.hh>
Thanks #Wrikken for pointing me in the right direction
This article highlights two properties in php.ini that can be changed:
mail.add_x_header = Off
expose_php = Off
I have no idea why they'd be on by default..
For ultimate obscuration for all emails sent, you can control the postfix headers on the email server. This also allows you to hide your obscure your hostname. Major wrote a good article that should get you pointed in the right direction. It's a little more advanced, but I think it's the way to go:
https://major.io/2013/04/14/remove-sensitive-information-from-email-headers-with-postfix/
Apart from settings described in this answer
this issue on GitHub suggest removing X-Mailer header like this
$mail = new PHPMailer(true);
$mail->XMailer = ' ';

How to limit outbound SMTP mail sent from PHP

We have shared hosting servers which use PHP fastcgi (on IIS) for several clients (shared hosting). Regularly clients use old exploitable code which causes holes in their applications that eventually gets used by hackers to install malicious code. Most of the time this code is being used to send spam from our servers.
We have no control over our clients code, so patching the holes is quite impossible.
We would however like to block the clients sending spam once they send more then X email messages in Y amount of time.
The setup is fastcgi based, so there is little relation between php and the webserver.
PHP sends its mail through SMTP on localhost. The mailserver allows relay of all localhost connections (obviously).
One thing that goes through my mind is setting an environment variable containing an identifier in the fastcgi environment and using php's prepend file option to add a header to all mail send by php's mailer. After that we could use that mail header to identify the spamming culprit.
The option above still would not take care of spam scripts using regular telnet (telnet localhost, HELO, MAIL FROM etc... ) when sending email.
My question to you: is the idea that i've mentioned the best and perhaps only option to deal with our issue? Or are there better solutions for this situation? And if so, please explain how you would deal with the issue.
You can filter that on you MTA (message transfer agent). For example, allow no more than 50 emails in 1 hour for each user in Exim ( http://www.exim.org ) config file (/etc/exim/exim.conf):
begin acl
acl_check_not_smtp:
warn ratelimit = 0 / 1h / strict / $sender_address_local_part
log_message = Sender rate $sender_rate / $sender_rate_perio
acl_not_smtp = acl_not_smtp
begin acl
acl_not_smtp:
deny message = Sender rate overlimit - $sender_rate / $sender_rate_period
ratelimit = 50 / 1h / strict
accept
And no matter how they try to send, via php mail() or other method.
Most shared hosts block the use of PHP's mail() function, as that can be easily exploited. Instead they advice using sendmail or similar scripts which require SMTP authentication before sending. Assuming you're not already doing this, once implemented, you should be able to keep track of number of emails sent from a particular domain/email account and put restrictions on it.
Okay, stick with me on this one. I have not implemented it but it looks good.
The concept here is that you could
run a php file before EVERY page on your customers site
in that php file rename the mail function to mail_internal().
in that php create a new function called mail to do your check / verification that your customer is allowed to send mail, and if they are call the mail_internal() function with the same parameters.
You will have to install the runkit PECL extension
http://us.php.net/manual/en/runkit.installation.php
Changes
in php.ini
auto_prepend_file /var/www/allclients_forcedfile.php
in /var/www/allclients_forcedfile.php
runkit_function_rename ( "mail" , "mail_internal" );
function mail ( $to , $subject , $message, $additional_headers = "", $additional_parameters ="" )
{
$args = func_get_args();
error_log("mail_internal : $_SERVER[HTTP_HOST] : ".implode(" : ",$args));
//lookup whether you want to send more mail for this client maybe by keeping a counter in some file in the $SERVER[DOCUMENT_ROOT]
if($sendmoremail)
return mail_internal ( $args[0], $args[1] , $args[2], $args[3] , $args[4] );
return false;
}
As expected it seems Stack Overflow is not the right place for this question. The provided answers do not expose some clear method to identify FastCGI sessions' connections to the MTA (SMTP) server.
I will go with my initial concept of adding an identifier to php's environment. This identifier can be read in PHP's prepend file by using the getenv() function. This identifier can then be added to mail headers for outgoing mail.
Furthermore I have enabled the mail.add_x_header ini setting which will help identify which script caused the spam run.
I am leaving the question open for the bounty duration, hoping other options will magically appear :)

Is -f key mandatory for PHP mail() send emails with correct from address?

Having a real tough time fixing an issue on a RS cloud server. The emails sent by PHP scripts, although a From header is included, the from address is getting changed to current user that is running the php.
e.g
mail('someone#gmail.com', 'Test mail', 'Reply back when you see this', 'From: web#mysite.com' . "\r\n");
Although the additional header is included, the email is being sent as apache#mysite.com or manjuser#mysite.com (when I login to ssh as manjuser and run the php from cli). Clearly overriding the from address. This is resulting in emails not getting delivered to destination. RS email app rejects it as both apache and manjuser email boxes are not present.
Question is:
Is there a way to tell sendmail/postfix to use the From header or a fixed email address instead of requiring -f to be sent every single time mail function is used?

php redirect email to file

I am using php5.
Are there some settings or a simple php.ini directive that would redirect all the emails to a folder?
I want on the development machine to have all the emails generated by the system not sent to the actual receiver but put in a folder.
Thanks.
I used to have some code like this (kinda pseudocode):
define ('DEBUG', true);
function send_email($to, $subject, $body) {
if (DEBUG) {
file_put_contents('some_folder/' . $to . date('dmY-His') . '.html', $body);
}else{
// Actual code to send email
}
}
But i agree with others, it's easier/better to setup an development email account to receive those emails.
I don't think you will be able to do something like this. Mails are sent by a mail server so it must be your mail server that writes them to a file instead of sending them.
Why not simply send it to a special development email?
Sample:
define('DEBUG', true);
if(DEBUG)
{
// Override recipient
$recipient = 'development#domain.tld';
}
// Send mail...
No settings that I'm aware of in PHP itself. However, if you're using Postfix on your development server, here's a recipe I cooked up to redirect all outbound email to a single (local) address:
/etc/postfix/main.cf: (add this to the existing file, don't replace everything)
virtual_alias_maps = regexp:/etc/postfix/virtual
/etc/postfix/virtual:
/.*/ duskwuff#localhost
You can configure your mail server to accept SMTP messages as normal, but make it unable to forward them onto another mail server. If your mail server supports it, make it redirect all messages to a postmaster account, or any other address of your choice.
This means that PHP will behave as normal, everything will appear to work straight away with the message, but it just won't go to the 'intended' recipient.
It also means that you can inspect headers (pretty much as they would normally appear), to support debugging.
There are many ways to do this. Basically, you need to define the sendmail command in your php.ini to point to a program or script which will save the mail locally.
One solution is this:
Catch emails with php script
Another is this:
Mail catcher

Categories