Forum Moderators: coopster

Message Too Old, No Replies

PHP Mail function

         

mr_nabo

8:10 pm on Dec 10, 2007 (gmt 0)

10+ Year Member



I know problems with setting up a PHP Mail script been mentioned lots of times, but I'm really struggling with solving this one.

I'm certain I've got these in the wrong order anyway, but I also get the following error:

Parse error: syntax error, unexpected T_STRING, expecting ',' or ';' in /home/staygood/public_html/includes/formmail.inc.php on line 48

I'll post my form and mail script and hopefully someone can help me out.

Form page: contact.php

<html>...<p>...</p>
<?php

// Stop the form being used from an external URL (spammers)
// Get the referring URL
$referer = $_SERVER['HTTP_REFERER'];

// Get the URL of this page
$this_url = "http://".$_SERVER['HTTP_HOST'].$_SERVER["REQUEST_URI"];

// If the referring URL and the URL of this page match and if there's data coming from a form then do the mailing
if ($_POST & ($referer == $this_url)) {

include($_SERVER['DOCUMENT_ROOT'] . '/includes/formmail.inc.php');

} else {

?>


<p>

<blockquote id="contactform">

<h3>Contact form</h3><br /><br />

<form action="<?php echo strip_tags($_SERVER['php_self']);?>" method="POST">

<label for="firstname">First name</label><br />
<input name="firstname" value="" /><br />

<label for="surname">Surname</label><br />
<input name="surname" value="" /><br />

<label for="email">Email address</label><br />
<input name="email" value="" /><br />

<label for="tel">Telephone number (please include area code<br />
i.e. +44 (0)207 #*$! #*$!x</label><br />
<input name="tel" value="" /><br />

<label for="comment">Enquiry</label><br />
<textarea name="comment" rows="5" ></textarea><br /><br />

<input type="submit" value="Send" class="submit">

</form>

</blockquote>

</p>

<?php }?>

<p>....

And now the script I include in the form: formmail.inc.php

<?php
// multiple recipients
$to = 'email@yahoo.co.uk' . ', '; // note the comma
$to .= 'email@yahoo.co.uk';

// received variables
$firstname = strip_tags($_POST['firstname']);
$surnamee = strip_tags($_POST['surname']);
$email = strip_tags($_POST['email']);
$tel = strip_tags($_POST['tel']);
$comments = strip_tags($_POST['comments']);

// subject
$subject = 'Enquiry from blah.com';

// message
$message = '
<html>
<head>
<title>Enquiry from blah.com</title>
</head>
<body>
<h2>Enquiry</h2>
<p><b>Below is an enquiry submitted using the contact form of blah.com</b></p>
<p>First name: ' . $firstname . ' </p>
<p>Surname: ' . $surname . ' </p>
<p>Email: ' . $email . ' </p>
<p>Tel: ' . $tel . ' </p>
<p>Enquiry: ' . $comments . '</p>
<p><b>Please get back to them asap.</b></p>
</body>
</html>
';

// To send HTML mail, the Content-type header must be set
$headers = 'MIME-Version: 1.0' . "\r\n";
$headers .= 'Content-type: text/html; charset=iso-8859-1' . "\r\n";

// Additional headers
$headers .= 'To: Bob <bob@yahoo.co.uk>, John <John@yahoo.co.uk>' . "\r\n";
$headers .= 'From: blah.com <enquiries@blah.com>' . "\r\n";
$headers .= 'Cc: admin@yahoo.co.uk' . "\r\n";

// Mail it
if (mail($to, $subject, $message, $headers))
{
echo '

<blockquote id="contactform">

<h2>Thanks!</h2>

<p>Thank you for getting in contact, we'll be in touch soon!</p>

<p>Terry and Fred</p>

</blockquote>

';

} else {

echo '

<h2>Eh?</h2>

<p>There was a problem sending your message. Please get in contact with either Terry or Fred using the details listed here: tootie frootie</p>

';

}

?>

Thanks for reading this far!

justgowithit

9:10 pm on Dec 10, 2007 (gmt 0)

10+ Year Member



You need to escape your apostrophe in the line, "Thank you for getting in contact, we'll be in touch soon!"

It should read, "Thank you for getting in contact, we\'ll be in touch soon!"

You should also consider breaking up your message into numerous smaller lines instead of one long statement.

PHP Manual:

Each line should be separated with a LF (\n). Lines should not be larger than 70 characters.

mr_nabo

9:32 pm on Dec 10, 2007 (gmt 0)

10+ Year Member



Thanks for getting back to me. That sorted out the error message, so thanks for that. However, I can't get the script to send an email. Any ideas? I'm not sure if I've placed the script in the correct place/am calling it when I should be calling it.

Something else I'm having trouble with is that I want to add some checks as to whether the inputs had been filled in or not and display any error messages in red above the input field. I've seen examples out there, but they don't seem to indicate where one should place the error messages or how.

Thanks for any help

justgowithit

9:45 pm on Dec 10, 2007 (gmt 0)

10+ Year Member



Is the mail() function throwing a boolean true or false?

You should check out this book. It talks a lot about handling forms in a user-friendly manor with PHP and it's a good book for building a foundational understanding.
PHP/MySQL Programming for the Absolute Beginner

mr_nabo

10:04 am on Dec 11, 2007 (gmt 0)

10+ Year Member



I'll check out that book, sounds like a good place to get up to speed.

While I wait for it to arrive, I think my problem might be that I've put a $_SERVER['php_self'] as the action. To be honmest, I've never been able to work out how $_SERVER['php_self'] can pass variables on to a script that is included on the same page, I always thought you were meant to pass variables on to an external script such as formmail.inc.php, but various tutorials have shown this technique.

Could this be my problem? Do I need to put my if statement that checks for spammers in the action of the form?

PHP_Chimp

11:13 am on Dec 11, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



The action attribute of the form tag is the page that the information will be sent to.
So if you are processing the form on the same page it is called from you would have something like -

if ($_POST /* or $_GET...whatever you are using */) {
// the form has been sent so process
}
else {
//form not been sent so display html
}

You dont have to use that exact code, but there should be some form of processing if the form has been sent, or the html is displayed if nothing has been posted.

So you can do either. If you want to have the form and processing done on the same page then use $_SERVER['PHP_SELF'], if you want to process on a different page then use that page in the action. The are positives and negatives for both methods. There was a thread about the relative benefits for both a while ago, so it may be worth looking back to see the pros and cons for both.

<edit>
YES, make sure you check for mail spam. There seems to be a lot of it around at the moment, so be very careful with what you allow people to enter in there address, or you end up with 1000's of addresses in there and suddenly you are a spammer :(

[edited by: PHP_Chimp at 11:16 am (utc) on Dec. 11, 2007]

mr_nabo

8:02 am on Dec 12, 2007 (gmt 0)

10+ Year Member



Thanks for all your help so far. So far, I have a script that appears to be working except for actually mailing something out, so I have 2 questions:

1) What can I do to check why the form is not sending emails out? I've used just the mail() function by itself from my local computer and it sent out one email and now doesn't any more.

Emails don't appear to be being sent out from the server I'm hosting the site on yet the script is executing ok as it is passing all the tests right up until the mail funciton.

Could it be a huge delay? I'm sending to a Yahoo address so I'm suspecting this might be the case? Only problem is that I've tried it with a gmail account as well...

2) Is this enough spam protection for the form? :
- email field is validated
- if other fields are blank an error message is given
- I strip tags from user input of all fields
- I check the referrer URL against the actual URL of the page (as recommended here)
- Oh, and I've made a budget captcha image with some letters and numbers in it and test for them in a field as well

Thanks

justgowithit

1:52 pm on Dec 12, 2007 (gmt 0)

10+ Year Member



The mail function is subject to server config issues that can cause the function to throw a bool true because the server is accepting the call but not actually sending mail. In my experience this is often the case when sending SMTP.

Have you verified that the path to sendmail is correct?

from my local computer

Are you running Apache on a windows OS?

When I debug a script I trim it down to where I think the problem is and then go from there. In this case it seems like everything is working with the exception of the mail function.

I would suggest that you upload a simple bare-bones test script so that you can concentrate on this area alone.

Create a new script like 'mail_test.php'......


<?php
//-> This script is for testing mail() only - 12/12/07

//-> Send to multiple address to control spam blocks
$to = 'you@yourdomain.com . ', ';
$to .= 'yous@too.com . ', ';
$to .= 'etc@etc-etc.com';

if (mail($to, 'Test Subject', 'Test Message')) {
echo 'TRUE';
} else {
echo 'FALSE';
}

?>

Every time you refresh this page you'll invoke the script. If you see 'TRUE' and no mail arrives, you've got a config issue. If you see FALSE, you (or your host) probably has mail() disabled.

PHP_Chimp

9:43 pm on Dec 12, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Is this enough spam protection for the form? :
- email field is validated
- if other fields are blank an error message is given
- I strip tags from user input of all fields
- I check the referrer URL against the actual URL of the page (as recommended here)
- Oh, and I've made a budget captcha image with some letters and numbers in it and test for them in a field as well

Security is always relative. There is no system that is invulnerable, so you need an appropriate amount of security that doesnt inconvenience your visitors so much that they dont want to come back, yet protects there data enough so that most people arent going to bother trying to hack through.

Striping tags is a good idea, however if you want to see if someone was trying to spam you then use the htmlentities [uk2.php.net] as this will just encode everything, so you can see it but it wont actually work like a tag. Then you can decide who you are going to punish that person >:)

Are you checking $_SERVER['HTTP_REFERER'] or using a hidden field with the page name? As HTTP_REFERER is easy to abuse. (im sure it is in your code but there is so much of it and im not at work...so dont want to read code...sorry)

captcha is good but just as there are technologies to automate generation of captcha there are also technologies out there to outomate breaking through them. So dont assume you will not get any spam just because of your captcha. It is just another thing to make 'most spammers' give up (goes back to relative security as above).

When you say email has been validated, what are you validating?
Email validation is one of those things that can annoy a lot of people. There is the full RFC spec for email addresses, or are you using your own validation expression? As if you are just testing for [a-zA-Z0-9_-] either side of an & with a few .'s in there then you may end up annoying people who have perfectly valid email but you tell them that they are not correct...
Im not actually sugesting validating to RFC 2882 or 882 as it involves checking the A or MX DNS records and this is probably not something that is worth doing for every person that signs up on the forum. It is worth thinking about how you are going to deal with these people though.

On 1 of my sites when email address is a bit more important I have the 'normal' test for emails, and if they fail this test they get an option to test to the full standards. There is no backup if there email fails the test to the standards, as unless they can point to something that I havent found there email is not valid so I dont care if it works on there system or not :P. On another site if peoples email fails the usual test then they can just click to say that they are sure there email is correct and they will be let through with an email that fails the 'normal' test. Neither of these may work for you, but it is something to think about.

mr_nabo

10:19 am on Dec 13, 2007 (gmt 0)

10+ Year Member



Thanks for both getting back to me.

I figured out that Yahoo blocked the server I was sending emails from because they-d received too many requests in one day, hence why the script wasn't appearing to send emails out. It works fine when sending to a non-free email address.

Slowly realising that email is a serious pain the ass to get right!

I'm validating the email addresses for a few strange characters, not much else. Tried it with a few unusual email addresses and it seems to work ok, but thank you for the advice on how to avoid annoying visitors.

HTTP referrer script is as follows:


// Get the referring URL
$referer = $_SERVER['HTTP_REFERER'];

// Get the URL of this page
$this_url = "http://".$_SERVER['HTTP_HOST'].$_SERVER["REQUEST_URI"];

// If the referring URL and the URL of this page match and if there's data coming from a form then do the mailing
if ($_POST & ($referer == $this_url)) {
echo '<p>Naughty person, don\'t try and spam people using this form!</p>';
exit;
}

I think my aim is really to seriously reduce the amount of spam rather than eradicate it entirely - the latter is impossible I think personally.

My biggest concern right now is how to get emails delivered to mailboxes like Gmail and Yahoo considering they don't even make it to the junk mailbox.. :$

How do you guys get around this issue? Or do you not have these types of problems?

PHP_Chimp

6:55 pm on Dec 14, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Unfortunately I cant help with the email not getting though to yahoo or others, as they are not accounts that I use for large volumes of mail (customers get there mails, but then they will only be receiving a few at maximum each day).

Can you not get a mail server from the domain? Partly as it looks a lot better to have an email address like me@example.com rather than me@yahoo.com. It also gives you a lot more flexibility as it is your mail server.

However if getting the refering page is something that you are wanting then you would be better using both $_SERVER['HTTP_REFERER'] - as this is quick, but easily spoofed.
AND a hidden field on that page. Dont put the page name in plain text, do something like md5 the page name as then you can check it against the md5($_SERVER['HTTP_REFERER']) and they should match. This should slow down bots from getting through.

[edited by: PHP_Chimp at 6:57 pm (utc) on Dec. 14, 2007]