How to remove headers revealing system info when sending mail in php - 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 = ' ';

Related

php mail 'from' header not behaving

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.

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 :)

MODx emails not working

On my server, sending emails with MODx (version 2.2) fails. It would probably work with SMTP, but in principle it should work without SMTP as well, since scripts like the one below work.
Script:
<?php
$to = "someone#example.com";
$subject = "Test mail";
$message = "Hello! This is a simple email message.";
$from = "someonelse#example.com";
$headers = "From:" . $from;
mail($to,$subject,$message,$headers);
echo "Mail Sent.";
?>
Can you help me find the reason for this misbehaviour and/or solve this problem?
Edit
To answer the questions below:
I don't try to send any fancy emails to site users. I am just trying very basic stuff like resetting login and passwords via email.
I tried quickemail for debugging. The output is:
System Settings (used if property is missing):
emailsender System Setting: xxx#xxx.xx
site_name System Setting: MODX Revolution
Properties (from parameters, property set, or snippet default properties:
Tpl chunk name:
subject:
to:
fromName:
replyTo:
emailSender:
allowHtml: 1
message:
Final Values (actually used when sending email):
subject: Default Subject
to: xxx#xxx.xx
fromName: xxx#xxx.xx
replyTo: xxx#xxx.xx
emailSender: xxx#xxx.xx
allowHtml: 1
Message Body: Default Message
Send Failed
Mailer error info: Could not instantiate mail function.
Server Debug Information:
I think I already do use MOD-Mail with the core installation. Isn't that right?
My mailserver uses qmail. I just tried the script above without a $from value, and it worked. Buts still, MODx cannot send emails.
You will need to check that the default settings used by MODx match those of your servers PHP mail() configuration.
The PHP mail class MODx uses is at core/model/modx/mail/phpmailer/class.phpmailer.php. If they do not match I do not recommend changing the class, instead use SMTP which can be enabled and configured within the MODx Manager under System > System Settings
Info: By default MODx sends email using /usr/sbin/sendmail -oi -f. It is pretty common but wont work on all web servers.
When you are using the mail-function, you are using the native (standard) PHP mail-class.
Modx revo has it's own, but you are not using the class at all. This is installed by default so it should be working. Read this wiki-article for usage of the class: http://rtfm.modx.com/display/revolution20/modMail
However, if sending email does not work, this has nothing to do with Modx, and as far as I can see, your code is valid. This is rather a server/PHP-setup question.

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

Seeing "on Behalf of" in system generated emails

I use a PHP mailer with of my online programs and recently when I look in outlook I see
'crazyphil#host.validns.com on behalf of My Mailer [no-reply#mydomain.com]' when I receive emails from any of my domains.
Previously the crazyphil#host.validns.com was nobody#host.validns:
Return-path: <nobody#host.validns.com>
Received: from nobody by host.validns.com with local (Exim 4.69)
(envelope-from <nobody#host.validns.com>)
It used to be fine like that, but something on my hosts side changed and now I get the 'on behalf of'. Anyone know why this is occuring now, and not before (since all that changed was nobody to somebody!) and how to resolve it?
Thank you,
Phil
Sounds like you need to set the from header in your mailer.
Mail servers will usually append their own if one isn't found.
in normal php it'd be something like
$headers = "FROM: 'fromname' <from#example.com\r\n>";
mail($to, $subject, $body, $headers);
I already had the From in the header, but I overlooked one difference in the header:
Sender: <crazyphil#host.validns.com>
This line popped up in all emails from my host, even those sent by the cron daemon.
Getting this removed resolved the issue.
Thanks though!
--Phil

Categories