I have a form and this bit of code to send it:
if($feedback != $errorMessage){
$emailTo = 'me#mywebsite.com';
$emailFrom = 'submissions#mywebsite.com';
$subject = 'Submission';
$body = filter_var("$contactName made a submission.
Contact Information:
Contact Name:\t$contactName
blah:\t$blah
Address:\t$address
Telephone:\t$telephone
Mobile:\t$mobile
E-mail Address:\t$userEmail
Website:\t$website
Vacancy Information:
field1:\t$field1
field2 Benefits:\t$field2
field3:\t$field3
field4:\t$field4
field5:\t$field5
field6:\t$field6
field7:\t$field7
field8:\t$field8
field9:\t$field9", FILTER_SANITIZE_STRING);
mail($emailTo, $subject, $body, "From: ".$emailFrom);
}
From what I understand from reading other threads this should be enough. I tried emailing just a single dot on a line in one of the textareas and it did turn it into 2 dots. Just running one function on it seems far too simple though.
Is this secure enough? I've read things online that seem inconsistent like that I don't even have to sanitize the body. The email body is the only thing that takes user input here.
Thanks.
Not entirely sure what you mean by secure here. Your script is just sending an email. The content of the fields will be what the user filled in. It could be link to virus, crap, spam or real content. Not easy to say, really. Not much to do with it either.
Sanitizing is much more important once databases are in use.
Related
I am a PHP newb so please bear with me for this rather simplistic question.
I have a PHP form setup like so >>
<?php
if($_POST){
$name = $_POST['name'];
$email = $_POST['email'];
$message = $_POST['message'];
$comments = $_POST['comments'];
if($comments)
$error = "There was an error, please give us a call at ### ###-####.";
else{
if($name=="Name" || $email=="Email" || $message=="Message"){
$error = "All fields are required, please fill them out and try again.";
}else
$header = "From: $name <$email>";
$message = "Name: $name\n\nEmail: $email\n\nMessage: $message";
if(mail("email#domain.com", 'Form Submission', $message, $header))
$success = "Thanks for sending us your message, we'll get back to you shortly.";
else
$error = "There was an error, please give us a call at ### ###-####.";
}
if($error)
echo '<div class="msg error">'.$error.'</div>';
elseif($success)
echo '<div class="msg success">'.$success.'</div>';
}
?>
The basic idea is that the form has descriptive text pre-filled in each field but when you click on them they are cleared via Javascript. I want to prevent people from pressing send on the form without filling it out, hence the "if($name=="Name" || $email=="Email" || $message=="Message"){" bit. However while that message is working the form is still submitting. Why is this. Also please note that the "comments" field is in fact a honeypot. Thanks!
Because php is server-side. You need to look into javascript validation for what you want. To validate with php you HAVE to submit the form.
One tutorial but I recommend Jquery validation
"I want to prevent people from pressing send on the form without filling it out, hence the "if($name=="Name" || $email=="Email" || $message=="Message"){"
All you need to do is disable the submit button client side until the proper validation is met, then also validate server side. As #Iznogood said, that's why your gettin your error
Like lznogood said, PHP validates the form on the server, so you need to send the information to the server before PHP can process it.
If you want the form to be checked on the user side before sending it to the server you should use JavaScript to do that (jQuery is a great tool to use), and after checking it on the user side you can decide whether to send the form to the server or not.
Though this isn't an answer to your question, you might be interest in the new html5 feature placeholder. Read about it here. You can check to see which browsers it works in here (stupid internet explorer!). 5 years ago, I would put those "hints" as the value, which was a pain to validate. placeholder makes it sooooooo much easier. Your tag would look like:
<input type="text" name="email" placeholder="Enter Your Email Here" value="">
Note that value is empty. You can omit the value attribute, I left it in to show it's not needed here.
As far as an answer to your original question, everybody else is correct, javascript is the way to go.
I use a php code on my server to send messages to my clients. The programming tool I use (Game Maker) allows me to send messages via php by executing a shell so that the link appears in a browser.
Example is here ...
with all the other stuff added. So in effect, the message I'm sending and all the stuff I'm sending are seen in the browser. I use the php get method. everything works perfectly now, except that it may not be secured. Someone suggested php post method, but when I replaced get in my php cod on my server to post, and pasted the same thing in the browser, my code didn't work. It's hard to explain, but here's the php code on my server:
<?php
// Some checks on $_SERVER['HTTP_X_REFERRER'] and similar headers
// might be in order
// The input form has an hidden field called email. Most spambot will
// fall for the trap and try filling it. And if ever their lord and master checks the bot logs,
// why not make him think we're morons that misspelled 'smtp'?
if (!isset($_GET['email']))
die("Missing recipient address");
if ('' != $_GET['email'])
{
// A bot, are you?
sleep(2);
die('DNS error: cannot resolve smpt.gmail.com');
// Yes, this IS security through obscurity, but it's only an added layer which comes almost for free.
}
$newline = $_GET['message'];
$newline = str_replace("[N]","\n","$newline");
$newline = str_replace("[n]","\n","$newline");
// Add some last-ditch info
$newline .= <<<DIAGNOSTIC_INFO
---
Mail sent from $_SERVER[REMOTE_ADDR]:$_SERVER[REMOTE_PORT]
DIAGNOSTIC_INFO;
mail('info#site.com','missing Password Report',$newline,"From: ".$_GET['from']);
header( 'Location: http://site.com/report.html' ) ;
?>
I then call this php code on my site. so that in the end, the whole thing ends up in the browser address bar. I hope this makes sense. How do I make things more secured by using post so that at least the sent information cannot be seen in users history and all that.
If you replace to POST in your form you need to replace the request to POST too:
<?php
// Some checks on $_SERVER['HTTP_X_REFERRER'] and similar headers
// might be in order
// The input form has an hidden field called email. Most spambot will
// fall for the trap and try filling it. And if ever their lord and master checks the bot logs,
// why not make him think we're morons that misspelled 'smtp'?
if (!isset($_POST['email']))
die("Missing recipient address");
if ('' != $_POST['email'])
{ // A bot, are you?
sleep(2);
die('DNS error: cannot resolve smpt.gmail.com');
// Yes, this IS security through obscurity, but it's only an added layer which comes almost for free.
}
$newline = $_POST['message'];
$newline = str_replace("[N]","\n","$newline");
$newline = str_replace("[n]","\n","$newline");
// Add some last-ditch info
$newline .= <<<DIAGNOSTIC_INFO
---
Mail sent from $_SERVER[REMOTE_ADDR]:$_SERVER[REMOTE_PORT]
DIAGNOSTIC_INFO;
mail('info#site.com','missing Password Report',$newline,"From: ".$_POST['from']);
header( 'Location: http://site.com/report.html' ) ;
?>
Unless you are sending it with real GET parameters like http://www.mysite.com/send.php?email=etc; in this case you do need to set it to GET to retrieve the variables.
I'm using the Zend_Mail_Message class to display emails inside of my PHP app, and am able to output the subject, content, date and even the NAME of the sender (using $message->from) but I can't figure out how to get the email address of the person who sent the message. The documentation is no help and googling finds a million results for how to send messages with Zend, but nothing about getting the address that sent the message.
EDIT:
This is how I ended up doing it. After some more digging, I found the sender's email in a field called 'return-path'. Unfortunately, this field has a dash in the name (WTF??) so to access it, I had to do this:
$return_path = 'return-path';
$message->reply_to = $zendMessage->$return_path;
Using the return-path caused some problems with some emails, specifically messages from no-reply accounts (mail-noreply#gmail.com, member#linkedin.com etc). These addresses would end up looking something like this:
m-9xpfkzulthmad8z9lls0s6ehupvordjdcor30geppm12kbvyropj1zs5#bounce.linkedin.com
...which obviously doesn't work for display in a 'from' field on the front-end. Email clients like Apple Mail and Gmail show mail-noreply#gmail.com or member#linkedin.com, so that's what I was going for too.
Anyways, after some more research, I discovered that the 'from' field in a Zend Mail Message object always looks something like this:
"user account name" <user#email.com>
The part in < > is what I was after, but simply doing $from = $zend_message->from only gave me the user's account name (hence my original question). After some more playing around, this is how I finally got it working:
$from = $zendMessage->from;
$start = strpos($from, '<');
$email = substr($from, $start, -1);
$result = str_replace('<', '', $email);
Hopefully this will save someone some frustration. If anyone knows of a simpler way of doing this, please let me know.
This works well..
$senderMailAddress = null;
foreach ( $message->getHeader('from')->getAddressList() as $address ) {
if ( $senderMailAddress === null) {
$senderMailAddress = $address->getEmail();
}
}
The main problem here is that many email programs, relay agents and virus scanner along the way do funny stuff to an actually simple and well defined email standard.
Zend_Mail_Message extends to Zend_Mail_Part which has a method called getHeaders(). This will have all the data from an email stored in the head versus the body which is accessed with getContent() and the actual email message.
With this method you'll get an array of all the key/value pairs in the header and while developing you should be able to determine which header field you will actually want. Once you know that you can then get the actual field with getHeader('field_name') or with its actual name directly.
However, if you have to many different email senders you may want to stick with the complete header array though and evaluate multiple fields for the best result like if there's an "reply-to" address. Again there are many uncertainties because the standard isn't always obeyed.
So, basically, I'm creating a page where a user can visit, and enter in the following information:
1. Their First Name
2. Their Email
3. Recipient's Email
They then can send a pre-defined email, saying something like the following...
"Hello, {Recipient's email}. {First name} ({Email}) has just sent you a slurp! You can ignore this message, or slurp them back.
[Slurp Them Back] [Slurp Someone Else] [What's A Slurp?]"
The whole part about the Slurp is something that doesn't really matter, it's just the text from the pre-defined email. The text in {...} is taken from the fields on the page, and the text in [...] are just links.
Does anyone have any idea on how to do this? Even if you can't customize the email, and it would just be without the information from the site, help would be appreciated. Thanks.!
Here's an example of what I'm going for...
Example Layout
It's possible to do using the php mail function. You can take input for everything you specified, then use the example here. They show it in a basic and more advanced form.
Interestingly, the first chapter of Head First PHP describes almost exactly this scenario (except that the recipient is fixed). If you want to learn more about PHP you can look into the book; otherwise, their code is online at http://www.headfirstlabs.com/books/hfphp/ (actual code link: http://www.headfirstlabs.com/books/hfphp/code/HeadFirstPHPMySQL_code_ch01.zip)
Sending an email by itself can be done by using the mail() command
mail('to.address#host.com', 'subject', 'message', 'From: from.address#host.com');
The whole code would look something like this:
HTML:
<form action="slurping.php" method="post">
Your name: <input type="text" name="name" /><br />
Your email: <input type="text" name="email" /><br />
Recipient: <input type="text" name="recipient" /><br />
<input type="submit" />
</form>
PHP (slurp.php):
// order of parameters is: to, subject, message body, additional headers
mail(
$_POST['recipient'],
'You just got slurped',
'You\'ve been slurped by '.$_POST['name'].'. Slurp him/her back by visiting http://slurp.com/',
"From: {$_POST['email']}\r\n"
);
This will send out an email like it's coming from the senders email address to the recipient.
There's a lot missing there, though. What you normally want to include is:
Validation of input on the client side (javascript)
Validation of input on the serverside
Clear out and handle right encodings etc
If you want to do it properly however, so that a greater percentage of your users actually receive the email, you should use a 3rd party library to send out emails. I recommend PHP Mailer or Swift Mailer.
Those libraries provide an easy mechanism for you to include HTML in your emails, attachments, allow for easily connecting to SMTP servers and handle all escaping and encoding issues for you.
On top of that they encapsulate everything within an Object oriented approach, so if that's your cup of tea, you'll be happy. Se their websites for more info.
It's pretty funny, I wrote a blog post about the very issue of email deliverability (getting through spam filters) etc: http://arnorhs.com/2011/02/21/delivering-email-with-php/ - It might be helpful to you.
Cheers
On submit you can send a predefine email in php
following is the code sample
assumed that you will have a html page and following is the sample html code
Send Slurp
Enter Your Name:
Enter Your Email:
Enter Recipient's Email:
following is the php code in "="send_email.php"
if ($_SERVER["REQUEST_METHOD"] == "POST")
{
$your_name = $_POST['your_name'];
$your_email = $_POST['your_email'];
$recipients_email= $_POST['recipient_email'];
$email_subject = 'My Slurp';
$email_body = "Hello, $recipients_email. $your_name ($your_email) has just sent you a slurp! You can ignore this message, or slurp them back.
[Slurp Them Back] [Slurp Someone Else] [What's A Slurp?]";
echo $email_body;
// Send Email
mail($recipients_email, $email_subject, $email_body);
}
?>
I have a classifieds website, and inside each classified, there is a small form.
This form is for users to be able to tip their "friends":
<form action="/bincgi/tip.php" method="post" name="tipForm" id="tipForm">
Tip: <input name="email2" id="email2" type="text" size="30 />
<input type="submit" value="Skicka Tips"/>
<input type="hidden" value="<?php echo $ad_id;?>" name="ad_id2" id="ad_id2" />
<input type="hidden" value="<?php echo $headline;?>" name="headline2" id="headline2" />
</form>
The form is then submitted to a tip.php page, and here is my Q, is this below code safe, ie is it good enough or do I need to make some sanitations and more safety details?
$to = filter_var($_POST['email2'], FILTER_SANITIZE_EMAIL);
$ad_id = $_POST['ad_id2'];
$headline = $_POST['headline2'];
$subject = 'You got a tip';
$message ='Hi. You got a tip: '.$headline.'.\n';
$headers = 'From: Tips#domain.com\r\n';
mail($to, $subject, $message, $headers);
I haven't tested the above yet.
You are passing $ad_id and $headline to the HTML only to have it passed right back, unchanged. Since ad_id and headline are not editable in the form, don't put them on the form, keep them on the server. That's the most secure.
Regardless of what filtering you do, you'll need to rate limit the sending of these emails. Even if they look to be from you and have some site-specific text, an automated bot could spam several hundred thousand of them and get some kind of response (and blacklist your email server). Only let them send a handful every hour and you won't cut out legitimate traffic.
It's a good idea to sanitise the input before you use it. Check to ensure the two post variables are in the correct format (e.g. only text or numeric (using Regex or is_numeric etc))
It looks like you have XSS in $ad_id = $_POST['ad_id2']; and $headline = $_POST['headline2'];.
There is a security concern with mail(). You must be careful of CRLF injection \r\n in $headers. in this case $headers is not controlled by the attacker, so you have nothing to worry about. Another point although its called CRLF injection, it could also be called LF injection because a new line is all you really need because SMTP is a forgiving protocol.
If $headline comes from your own database, I would not put the text in a hidden field, but the id of the headline and retrieve the actual text from the database before sending the mail.
That way you can A. simply check if the id is really an integer and B. know for sure only valid headlines get sent; now someone can post your form replacing your headline with any text they want.