PDA

View Full Version : CGI/Website forms help required - WARNING: TOTAL BEGINNER!! Sel/M3ntal/Anyone else?


thomasp
30 Mar 2006, 21:00
Hi All,

As you may be aware from previous website designing threads that I've created, I am designing a website for a friend's new business.

Now, my friend wants a page on the website where visitors can "sign up" for an e-mail-based newsletter by filling out boxes on a webpage and hitting a submit button. Such boxes might be "Name", "E-mail Address", "Company", etc. Once the submit button has been clicked, these details need to be e-mailed from the webserver to the "Newsletter Manager's" inbox so as the relevant details can be added to an address book (and probably a paper one ;))

I've been doing a little digging on t'internet and have found that this is possible through Common Gateway Interfaces, or CGI to you acronymy people. However, I have also found out that the webservers need to support Perl something.something. Since we have no idea if our website hosts offer this feature, I need to ask them some questions, but I don't really know what are good questions to ask about this!!

What kind of things do I need to know from the hosts if I want to run CGI scripts from their server? Aside from the obvious one "Can I run CGI scripts?"...


And now general questions to you for my benefit :)

Is it relatively easy coding CGI scripts, and do lots of people offer auto-mailer scripts? I've found this one (http://www.jmarshall.com/easy/cgi/mailer.pl.txt) online, but it looks very confusing! Are there any good tutorials on CGI out there?


Sorry if this post sounds a bit dis-jointed - this is all new territory to me! I'd just like a simple mailer script which collects inputted data from a form and sends it to a specified e-mail address.

Cheers :)

Plutonic
31 Mar 2006, 00:51
CGI can be coded in either perl or C, and in my own oppinion are 100% horrible to work with. Asking if you have CGI support would probably work, although many hosts have a formmail script already installed.

If you have access to it I would use PHP to do it, sending email with PHP can be done in about... well, one line i think. Infact, here it is:


mail("email address", "subject", "your message here", "From: $fullname <$myemail>\r\nContent-Type: text/html;");


I'm sure ASP can do it too but that costs money :p

Finding out what the server has installed would be the obvious start.

Pickleworm
31 Mar 2006, 02:09
CGI can be coded in either perl or C, and in my own oppinion are 100% horrible to work with. Asking if you have CGI support would probably work, although many hosts have a formmail script already installed.


CGI can be done in just about any language capable of printing. (even utterly hellish languages like INTERCAL. Don't believe me? Check this out. http://muppetlabs.com/~breadbox/intercal/ins/insstart.html) However, form/environment variables are not accessible from all languages (I don't think), so clearly some language are more popular than others (Perl or C being the most popular, but Python is up there too, Google uses it).

Perl is reccomended for learning CGI, and there are plenty of free starting tutorials (This being just one: http://www.cgi101.com/). Tutorials such as these will also teach you about HTTP headers and the like, which I learned nowhere else, and can be used in PHP to make randomly-generated content such as images.

PHP is a quite popular alternative, and for good reason. While C and Perl WORK for CGI, they certianly weren't designed for it. PHP was, and likewise MySQL access, form data access and things like that are handled much easier in it. You can learn PHP and MySQL by reading the documentation on the sites (www.php.net and www.mysql.org , if I recall).

Edit: It appears that I had made an entire post without answering your questions. If you are planning on doing your CGI in C (You crazy person), I don't know what you should ask about. It would be much better do do CGI in a sort of interpreted language, like Perl or Python. Perl would be the better of the two, since many more servers offer Perl than Python (If you want Python, though, check out www.nearlyfreespeech.net). Ask them if they have Perl installed (or Python or whatever you decide on).

But if you are paying for a webhost, it's almost certain that they will have PHP, so that would probably be the best route to take.

M3ntal
1 Apr 2006, 05:28
in your web page:

<form method="post" action="email.php">
<input type="text" name="name" />
<input type="text" name="email" />
<input type="text" name="company" />
</form>

then create a new file called email.php and put this in, replacing any email addresses i've used with ones appropriate to your own use:

<?php
$destination = "newsletter@whatever.com";
$subject = "Newsletter Sign-up"
$content = "";
foreach($_POST as $key => $value) {
$content .= "$key: $value\r\n"
}

mail($destination, $subject, $content, "From: Newsletter Sign-up Page <server@whatever.com>\r\n");
?>

I haven't tested this code (just wrote it in here) so apologies if it is broken, but i think it should work. It should automatically be able to handle whatever fields you decide to add to the form due to the "foreach" loop, which just goes through every value that is posted to the script and sticks it in the email content.

You obviously don't know PHP, so i'll explain a few things:
All variables start with a $ sign. This means that anything with a $ in front of it is a variable, storing a value. You can see what these values are set to at the start.
The $_POST variable is an array that is built in to the PHP language, that is automatically assigned any posted form values at the start of the script. It is an associative array, meaning each value in it has a key. For example, the email address submitted on the form will be in $_POST['email'] - it uses the "name" parameter you specified in the <input> tag on the form page. If i were to put my own email address into the form and submit it, they key would be "email" and the value would be "m3ntal@clansfx.co.uk". This should help you understand that "foreach" loop a little better - the part in the normal brackets assigns these to the variables $key and $value, and it repeats the part in the curly brackets for every element in the $_POST array, ie every form field that was submitted.
The full stop operator appends the string on the right of it to the string on the left of it, and the way i've used it there is a shorthand equivalent to writing: $content = $content . "$key: $value\r\n"
The "\r\n" is two escape characters. The "\r" means a carriage return, and the "\n" means linefeed. It's the equivalent of hitting the enter key if you were to type out the strings manually.

With the three form fields you specified in your post, You might receive an email like this after i submitted my information to the form (assuming i didn't put anything in the "company" field):

From: "Newsletter Sign-up Page" <server@whatever.com>
To: <newsletter@whatever.com>
Date: 01/04/2006 05:28
Subject: Newsletter Sign-up

name: Liam Dobson
email: m3ntal@clansfx.co.uk
company:

EDIT: One further note, the email address that you use in the "From" part of the email (in my example, server@whatever.com) doesn't actually have to be a real email address. You can put whatever you want in there as long as it looks like a valid email address. This is how to spoof emails, btw ;).

thomasp
3 Apr 2006, 10:54
Hmmmm - PHP looks confusing :confused:

I might just ask the hosts if they provide a mailer script thingy and go from there...


Thanks for the replies so far :)

Macobsession
3 Apr 2006, 13:04
You can also do it with javascript.

You just need to make an email form. Theres various sites and such that offer free email forms. For example: bravenet.com
The just give you the basic java code which you can easily modify(mostly copy and pasting) and then it'll send the form to bravenet and breavnet will send it to your email.

SupSuper
3 Apr 2006, 14:46
Hmmmm - PHP looks confusing :confused:

I might just ask the hosts if they provide a mailer script thingy and go from there...


Thanks for the replies so far :)PHP is far from confusing. M3ntal just made it look confusing :p
Basically you just make a form with the fields you want, then use the mail() function to email those fields to whoever you want.

But if that doesn't suit you, you're bound to find a ready-to-use customizable e-mail form since they're so common.

M3ntal
3 Apr 2006, 15:32
It's far from confusing. Just copy and paste my code, change the email addresses in it to whatever you want, and change the contents of the <form> to whatever you want. Hell, tell me what fields you want in the form and what email address you want it sent to, and i'll write and attach the files. It'll take all of about 5 minutes.

thomasp
3 Apr 2006, 16:29
It's far from confusing. Just copy and paste my code, change the email addresses in it to whatever you want, and change the contents of the <form> to whatever you want. Hell, tell me what fields you want in the form and what email address you want it sent to, and i'll write and attach the files. It'll take all of about 5 minutes.
I think I understand it a bit better now - so the PHP code really doesn't need changing, it's just the form "source" on the original HTML page?

Do all webservers support PHP, or is it likely to be an "optional extra" that clients (those who own the websites) will have to pay extra to make use of? Or does it just depend on the hosting company?

M3ntal
3 Apr 2006, 17:42
Indeed, the only part of the PHP that needs changing is the email address next to "$destination =", which needs to be the email address the form info is to be mailed to. You can also change the other email address near the end of the script if you wish, but it serves no functional purpose other than to tell the recipient of the email where it came from, if you wish to.

The HTML form itself can be whatever you want it to be, as long as it submits to the email script - all fields will get put into the email, whatever they are.

As for PHP support, it really depends. I'd say that PHP comes as standard on most web servers, but i do know that NTL makes you pay extra for it.

thomasp
3 Apr 2006, 18:41
It appears that our hosts do "support PHP for server side scripting" (quoted from the e-mail), so I assume that means I can go ahead and attempt to get it to work!!

Cheers for the help - will let you know how I get on :D

thomasp
4 Apr 2006, 17:15
How can I get a page that says "Thanks for submitting your information..." after the user clicks "Submit"?

SupSuper
4 Apr 2006, 19:06
Before ?> put echo "Thanks for submitting your information...";
Or if you want the page to look like the others, just put in whatever HTML code you want after the PHP code on email.php

thomasp
4 Apr 2006, 19:15
Before ?> put echo "Thanks for submitting your information...";
Or if you want the page to look like the others, just put in whatever HTML code you want after the PHP code on email.php
Cheers for that.

However, the PHP code doesn't work :(

I get this error:

Parse error: syntax error, unexpected T_VARIABLE in /var/www/html/ifdnrg_sites/www.<the domain>newsletters/email.php on line 4


Code is identical to M3ntal's code earlier, apart from I've changed the two e-mail addresses. Below is the form code on the previous page

<form method="post" action="email.php">
Name: <input type="text" name="name" /><br>
E-mail Address: <input type="text" name="email" /><br>
Position: <input type="text" name="position" /><br>
School/Company: <input type="text" name="School/Company" /><br>
Special Areas of Interest: <input type="text" name="AreasOfInterest" /><br>
Check to test: <input type="checkbox" name="test" /><br>

<INPUT TYPE=SUBMIT VALUE="Submit" /> <INPUT TYPE=RESET />
</form>

M3ntal
4 Apr 2006, 19:45
My bad thomasp, i missed out semicolons off the end of lines 3 and 6 in my haste. Here's the correct code:

<?php
$destination = "newsletter@whatever.com";
$subject = "Newsletter Sign-up";
$content = "";
foreach($_POST as $key => $value) {
$content .= "$key: $value\r\n";
}

mail($destination, $subject, $content, "From: Newsletter Sign-up Page <server@whatever.com>\r\n");
?>

thomasp
4 Apr 2006, 20:08
Cheers - that works fine now :) M3ntal = a star :D

Just going to implement a few Javascript checks (like Email address = valid, and stuff like that) and tweak the layout a bit and that should be fine :D

thomasp
4 Apr 2006, 21:35
*Puts "Picky & Fussy" hat on*

I have a "few" checkboxes on the form. Currently, if they are checked, the e-mail returned has <name>: on, and if they are not checked, they don't appear on the e-mail. Is there any way to have <name>: off appear in the email if they are unchecked, without using radio buttons?

Error404
4 Apr 2006, 22:41
You wanna set some specific value to a field in case it hasn't been checked...is that it?

If it is, it's hell simple:
<?php
$destination = "newsletter@whatever.com";
$subject = "Newsletter Sign-up";
if($_POST['sample_checkbox']){ $foo_checkbox = $_POST['sample_checkbox'];}
else{ $foo_checkbox = "I didn't fill this one...";};

$content = "Sample checkbox: " . $foo_checkbox;


mail($destination, $subject, $content, "From: Newsletter Sign-up Page <server@whatever.com>\r\n");
?>

This' considering you have a <input type="checkbox" name="sample_checkbox" [...]>...

Got it?

M3ntal
5 Apr 2006, 04:21
In other words, yes, but you'd need a bit of PHP knowledge.

How about you finish the form, send it me, and i'll just write you the script ;). It'll seriously take me about 5 minutes.

thomasp
5 Apr 2006, 10:38
In other words, yes, but you'd need a bit of PHP knowledge.

How about you finish the form, send it me, and i'll just write you the script ;). It'll seriously take me about 5 minutes.
That's OK, thanks :) I've spoken to the person who's going to be receiving the e-mails from the form, and they're quite happy with it as it is.

Thanks for all the help :)

thomasp
27 Oct 2006, 18:15
Sorry to bump this thread, but I've been asked by the website owners if there's a way to stop people submitting the form without entering any information.

I'm sure I saw somewhere you can get Javascripts that check whether certain things have been entered into a specific field (or just whether the fields contain any values), but I can't remember where I saw them!


Other than that, the form's been working perfectly well for 6 months :D

SupSuper
27 Oct 2006, 20:29
Just add an IF. Taking M3ntal's code:

<?php
$destination = "newsletter@whatever.com";
$subject = "Newsletter Sign-up";
$content = "";
foreach($_POST as $key => $value) {
$content .= "$key: $value\r\n";
}

// if "name_of_the_field_here" ISN'T blank, send mail
if ($_POST["name_of_the_field_here"] != "")
mail($destination, $subject, $content, "From: Newsletter Sign-up Page <server@whatever.com>\r\n");
?>

thomasp
27 Oct 2006, 23:07
Will that return an error message to the user saying they provided unsuitable data (or lack of)?

With the javascript ones I've seen (which irritatingly I can't remember where :mad: ), you get an error message saying that "x field needs to be completed" or something like that.

Pickleworm
27 Oct 2006, 23:22
Will that return an error message to the user saying they provided unsuitable data (or lack of)?

With the javascript ones I've seen (which irritatingly I can't remember where :mad: ), you get an error message saying that "x field needs to be completed" or something like that.

No, but you can get that with just a smidge of modification:


<?php
$destination = "newsletter@whatever.com";
$subject = "Newsletter Sign-up";
$content = "";
foreach($_POST as $key => $value) {
$content .= "$key: $value\r\n";
}

// if "name_of_the_field_here" ISN'T blank, send mail
if ($_POST["name_of_the_field_here"] != "")
mail($destination, $subject, $content, "From: Newsletter Sign-up Page <server@whatever.com>\r\n"); else echo "name_of_the_field_here field needs to be completed";
?>

AndrewTaylor
28 Oct 2006, 01:06
http://www.apathysketchpad.com/stuff/emailform.php

Been up there months. I'd have sent you the source if I'd seen this sooner.

M3ntal
28 Oct 2006, 19:01
thomasp, you need to give each of the form input fields that you wish to not be blank an ID, then you can reference them in javascript and check their contents. Here's an example of what i mean:

...
<script type="text/javascript">
<!--
function checkInput() {
var surname = document.getElementById('name');
var email = document.getElementById('email');

if(surname.value == "") {
alert('Please fill in the "surname" field');
surname.focus();
return false;
}

if(email.value == "") {
alert('Please fill in the "email" field');
email.focus();
return false;
}

return true;
}
-->
</script>
...
<form method="post" action="email.php">
...
<input type="text" name="surname" id="surname" />
<input type="text" name="email" id="email" />
...
<input type="submit" value="Send message" onclick="return checkInput();" />
</form>

The important parts here are the "id" attributes of those input tags, and the call to the javascript function "checkInput()" on the submit button's click event. That javascript function at the start there gets executed when someone clicks on the submit button, and due to the "return" part of that click event, the form only actually gets submitted if the function being called in the click event returns "true". The function itself uses the in-built DOM function "document.getElementById()" to grab the correct form input fields to check, hence the importance of giving the form fields an "id" attribute. It then uses an "if" statement for each of the form fields to make sure they have had something entered in them. If either of them is empty (name.value == "", email.value == "") it pops up an alert box, makes the empty field active (ie puts the cursor in it), and returns "false", stopping the form from submitting yet. If none of the fields are empty (ie all of the "if" tests fail and therefore get skipped) the "return true" statement gets reached, and the form is submitted.

Ideally, i'd check the email address is actually a valid email address using a regular expression rather than just checking it isn't empty, but this is just an example ;).

If this is still too much to understand, send me your form page, tell me what fields you want it to check before it submits, and i'll make it do so - it'll only take me a few minutes.

thomasp
28 Oct 2006, 19:24
Cheers for that M3ntal :D

With regards to checking the validity of the e-mail address, I suppose you'd have to use wildcards: *@*.* - is this the correct way of doing it?

if(email.value == "*@*.*") {
alert('A valid e-mail address is required');
email.focus();
return false;


Ta for the help :)


One other question, if someone has Javascript turned off, will it just not perform the check, and submit the form anyway?

thomasp
28 Oct 2006, 20:08
One other question: I assume all the <script> stuff above goes in the <head> tag?

MadEwokHerd
29 Oct 2006, 11:44
*@*.* would match all valid (and possibly some invalid) email addresses, yes

I suspect that with javascript disabled it would submit the form without doing the check, but why not try yourself?

I also suspect the <script> will work in <head>, but again why not try yourself?

thomasp
29 Oct 2006, 11:55
I've chucked it in the <head> tag, and it works fine - haven't tried it with JS turned off (need to find out how to do that in Safari ;)). But, I can't get this wildcard thing to work:

<script type="text/javascript">
<!--
function checkInput() {
var name = document.getElementById('name');
var email = document.getElementById('email');
var school = document.getElementById('school');

if(name.value == "") {
alert('Please fill in the "Name" field');
name.focus();
return false;
}

if(email.value == "*@*.*") {
alert('Please fill in the "E-mail Address" field');
email.focus();
return false;
}

if(school.value == "") {
alert('Please fill in the "School/Company" field');
school.focus();
return false;
}


return true;
}
-->
</script>

If you just enter anything (eg "a") into the "email" field, it still submits the form, but I want it to have an error saying you haven't filled in the email field correctly.

I appreciate that using *@*.* would have some invalid e-mail addresses, but that's slightly more effort for someone to do - eg: "a@a.a", as opposed to just typing in "a"


Edit:

Turning JS off bypasses the "checks".

MadEwokHerd
29 Oct 2006, 12:46
I can't find anything about wildcard matching in javascript. It's actually conceivable that the language doesn't have it (python doesn't).

There are two alternatives here:
1. Use regular expressions.
2. Check the string some other way.

There's only one real choice here. I'll give you a hint: it doesn't involve regular expressions.

if ((email.value.indexOf("@") != -1) && (email.value.lastIndexOf(".") > email.value.indexOf("@"))) alert("Yay! A valid email");

I hate regular expressions. So much.

Edit: Oh you're doing negative checks. Well then.

if ((email.value.indexOf("@") == -1) || (email.value.lastIndexOf(".") < email.value.indexOf("@"))) alert("Boo! Invalid email");

SupSuper
29 Oct 2006, 13:45
Can't you use .search()?

var expr = /^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,3})$/;
if(email.search(expr) == -1) {
alert('Invalid E-mail Address');
email.focus();
return false;
}

AndrewTaylor
29 Oct 2006, 18:33
/^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,3})$/;

Surely that's *.*@*.*.*? That's very restrictive. Not one of my email addesses would pass that.

Edit: Actually, I think it's OK. But I'd test it before putting it on a site.
Edit:

Turning JS off bypasses the "checks".
The best way is to have a javascript check and a PHP fallback check.

M3ntal
29 Oct 2006, 21:06
This will match 99% of email addresses:

/^[a-zA-Z0-9._%-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$/

This will match 100% of email addresses:

/^(?:(?:\r\n)?[ \t])*(?:(?:(?:[^()<>@,;:\\".\[\] \x00-\x1F]+(?:(?:
(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.
|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t]
)*(?:[^()<>@,;:\\".\[\] \x00-\x1F]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=
[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(
?:(?:\r\n)?[ \t])*))*@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \
x00-\x1F]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\
[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])
*(?:[^()<>@,;:\\".\[\] \x00-\x1F]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[
\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*
))*|(?:[^()<>@,;:\\".\[\] \x00-\x1F]+(?:(?:(?:\r\n)?[ \t])+|\Z|(
?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*
"(?:(?:\r\n)?[ \t])*)*\<(?:(?:\r\n)?[ \t])*(?:@(?:[^()<>@,;:\\".
\[\] \x00-\x1F]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\
]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?
[ \t])*(?:[^()<>@,;:\\".\[\] \x00-\x1F]+(?:(?:(?:\r\n)?[ \t])+|\
Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[
\t])*))*(?:,@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \x00-\x1F
]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]
\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()
<>@,;:\\".\[\] \x00-\x1F]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@
,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*)*:(?
:(?:\r\n)?[ \t])*)?(?:[^()<>@,;:\\".\[\] \x00-\x1F]+(?:(?:(?:\r\
n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?
:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[
^()<>@,;:\\".\[\] \x00-\x1F]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()
<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\
r\n)?[ \t])*))*@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \x00-\x
1F]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[
\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^
()<>@,;:\\".\[\] \x00-\x1F]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<
>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*\>(
?:(?:\r\n)?[ \t])*)|(?:[^()<>@,;:\\".\[\] \x00-\x1F]+(?:(?:(?:\r
\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(
?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)*:(?:(?:\r\n)?[ \t])*(?:(?:
(?:[^()<>@,;:\\".\[\] \x00-\x1F]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\
["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:
(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \
x00-\x1F]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"
(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*))*@(?:
(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \x00-\x1F]+(?:(?:(?:\r\n)?
[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(
?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \x
00-\x1F]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[
([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*|(?:[^()<>@,;:\\".\[\]
\x00-\x1F]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))
|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)*\<(
?:(?:\r\n)?[ \t])*(?:@(?:[^()<>@,;:\\".\[\] \x00-\x1F]+(?:(?:(?:
\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*
\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\
[\] \x00-\x1F]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]
]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*(?:,@(?:(?:\r\n)
?[ \t])*(?:[^()<>@,;:\\".\[\] \x00-\x1F]+(?:(?:(?:\r\n)?[ \t])+|
\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?
[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \x00-\x1F]
+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\
r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*)*:(?:(?:\r\n)?[ \t])*)?(?:[^(
)<>@,;:\\".\[\] \x00-\x1F]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>
@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\
n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \x00-\x
1F]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\
"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*))*@(?:(?:\r\
n)?[ \t])*(?:[^()<>@,;:\\".\[\] \x00-\x1F]+(?:(?:(?:\r\n)?[ \t])
+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n
)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \x00-\x1
F]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\
]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*\>(?:(?:\r\n)?[ \t])*)(?:,\s
*(?:(?:[^()<>@,;:\\".\[\] \x00-\x1F]+(?:(?:(?:\r\n)?[ \t])+|\Z|(
?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*
"(?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[
\] \x00-\x1F]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]
))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*))*
@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \x00-\x1F]+(?:(?:(?:\r
\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\]
(?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\
] \x00-\x1F]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]])
)|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*|(?:[^()<>@,;:\\".
\[\] \x00-\x1F]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\
]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)
*\<(?:(?:\r\n)?[ \t])*(?:@(?:[^()<>@,;:\\".\[\] \x00-\x1F]+(?:(?
:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\
\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\
\".\[\] \x00-\x1F]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".
\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*(?:,@(?:(?:\
r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \x00-\x1F]+(?:(?:(?:\r\n)?[ \t
])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r
\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \x00-\
x1F]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\
[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*)*:(?:(?:\r\n)?[ \t])*)?(?
:[^()<>@,;:\\".\[\] \x00-\x1F]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["
()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?
:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \x0
0-\x1F]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?
:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*))*@(?:(?
:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \x00-\x1F]+(?:(?:(?:\r\n)?[
\t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:
\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \x00
-\x1F]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([
^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*\>(?:(?:\r\n)?[ \t])*))*
)?;\s*)$/

MadEwokHerd
29 Oct 2006, 21:15
I was sure someone would post a simple, straightforward regular expression to prove that there was nothing wrong with them. I was wrong.

Also, M3ntal: + is a valid character in an email address (http://www.jacobsen.no/anders/blog/archives/2002/08/24/email_addresses_with_a_are_valid.html).

M3ntal
30 Oct 2006, 00:13
Sorry:

/^[a-zA-Z0-9._%-+]+@[a-zA-Z0-9.-+]+\.[a-zA-Z]{2,4}$/

There is nothing wrong with regular expressions, they are the best (easiest and most accurate) way to solve most parsing tasks that i have come across. The one above also won't handle email addresses with .museum at the end, but like i said, 99%.

That super long one apparently matches RFC 822 exactly, although i haven't tested it properly. Also, you don't particularly want to match RFC 822 exactly, as it allows email addresses such as me@home that would only work on an internal network.

MadEwokHerd
30 Oct 2006, 03:43
Dots in the domain name are ok to check because you can be sure an address won't work if it doesn't have any.

A superset of the emails that might work should pass the validation process, not a subset. Otherwise, it's broken. It will cause problems for people whose emails do not pass; they will not be able to enter their addresses into the form.

Also, apostrophes (') are valid in the local part of email addresses. I know from working at a data entry job that there are people whose emails contain apostrophes.

M3ntal
30 Oct 2006, 11:42
Well, in that case just go with this then:

/^[^@]+@[^@]\.[a-zA-Z]+$/

bloopy
30 Oct 2006, 21:20
http://en.wikipedia.org/wiki/Email_address lets you know which symbols can be in email addresses.

AndrewTaylor
31 Oct 2006, 11:37
Dots in the domain name are ok to check because you can be sure an address won't work if it doesn't have any.

A superset of the emails that might work should pass the validation process, not a subset. Otherwise, it's broken. It will cause problems for people whose emails do not pass; they will not be able to enter their addresses into the form.

This is very true. There's nothing you can do -- including sending out a probe email -- that will 100% prove an address is real. If people want to get past it, they will. Just make sure people can't accidentally type nothing, or the complete wrong thing.

thomasp
31 Oct 2006, 14:15
Wow - that's a lot of complicated JavaScript!

How easy is it to do in PHP (I think Andrew mentioned that earlier)? The e-mail check, that is.

AndrewTaylor
31 Oct 2006, 14:26
Well, there's not that much JavaScript:


<script language="JavaScript">
function check()
{
var expr = '/^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,3})$/';
if(email.search(expr) == -1) {
alert('Invalid E-mail Address');
email.focus(); // You don't really need this line and it might not be very compatible, but it's a nice touch when it works.
return false;
}
</script>
<form onSubmit="check()" ...


The PHP code is almost identical, but phrased differently and put on the next page.

M3ntal
2 Nov 2006, 16:39
focus() is fine, it's part of the W3C DOM, and supported by every main browser. You're correct that it doesn't need to be there though.

AndrewTaylor
3 Nov 2006, 10:40
focus() is fine, it's part of the W3C DOM, and supported by every main browser.
It's not the function I was unsure about, just that in my experience referencing objects in forms and HTML is different in a lot of browsers. This might work across the board, though:


<script language="JavaScript">
function check(form)
{
var expr = '/^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,3})$/';
if(email.search(expr) == -1) {
alert('Invalid E-mail Address');
form.email.focus();
return false;
}
</script>
<form onSubmit="check(this)" ...

SupSuper
3 Nov 2006, 10:56
Well he already had this line before:
var email = document.getElementById('email');
So I don't see why that wouldn't work.

AndrewTaylor
3 Nov 2006, 14:54
Oh, so he had. I'd not spotted that. I tend to do Javascript by copy-pasting and by repeated testing until it works. It's not very systematic, but it works pretty well. I shall bow to your probably-superior knowledge on this one.

M3ntal
4 Nov 2006, 02:09
Yeah, there are some inconsistencies in the DOMs of different browsers (such as IE creating blank child nodes for every carriage return within a tag, thus referring to child nodes by index is highly incompatible), which is why i tend to give all my unique tags an ID attribute and use getElementbyId().

SupSuper
4 Nov 2006, 20:15
I always wondered, if you have ID, what's the NAME attribute for? Because I think there's a getElementByName() too.

Error404
4 Nov 2006, 22:49
The NAME attribute is only used for communication with SERVER-SIDE scripts nowaday. So you'll likely only have to use it whithin the <form> tags to reference the fields for a possible SERVER-SIDE to rescue the values from them. ;)

SupSuper
5 Nov 2006, 00:27
I know that, I was asking if you can't also use NAMEs for JavaScript stuff instead of IDs?

M3ntal
5 Nov 2006, 17:54
There is a getElementsByName, notice the "s" there. It returns an array of all elements in a document with the given name in HTML 4, and just those within a form in XHTML. Do not use it, as it will soon be deprecated (ie, it won't work in future browsers). The W3C decided there was no need for seperate "name" and "id" attributes, and is due to do away with "name" altogether, and use "id" in its place for forms.

Error404
5 Nov 2006, 18:38
I'm pretty sure you can also reference it through the DOM tree... something like document.forms['form_name'].elements['field_name']. Although, like m3ntal said, it isn't recommended.

The name attribute will he history once the server-side language starts to acccept the id as reference for the form variables. So, for now, we wait... :)

M3ntal
7 Nov 2006, 11:47
It occured to me that you could verify email addresses in PHP by looking up their domain MX record. It should be a simple case of exec'ing an nslookup on the Linux command prompt and checking the result, assuming the web server runs Linux.

This way, you'd know not just if the address is valid, but also if it exists as well.

I'll have a go later on, unless someone wants to beat me to it ;).

MadEwokHerd
7 Nov 2006, 15:54
That sounds like overkill to me. At that point you might as well verify it by sending email to the address.

M3ntal
7 Nov 2006, 23:36
Hah, PHP actually has DNS lookup functions, so no need for the command-line 'exec' to nslookup.

Here's what i came up with, using the previously discussed javascript regex checking as well, and double checking in PHP before the DNS lookup. I used a regex that allows a superset of valid email addresses, as MadEwokHerd suggested. In all fairness, it only checks that an MX record for the domain exists, so non-existent emails such as "srrshsdfghehg@team17.com" can still pass the test.


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">

<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>
Email Checker
</title>
<link rel="stylesheet" href="style.css" type="text/css" />
<script type="text/javascript">
<!--
function checkInput() {
var email = document.getElementById('email');

if(email.value.search(/^[^@]+@[^@]+\.[a-zA-Z]+$/) == -1) {
alert('"' + email.value + '" is not a valid email');
email.focus();
return false;
}

return true;
}
-->
</script>
</head>

<body>
<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post">
<input type="text" name="email" id="email" />
<input type="submit" value="Check Email" onclick="javascript:return checkInput();" />
</form>
<p>
<?php
$email = $_POST['email'];
if(ereg('^[^@]+@[^@]+\.[a-zA-Z]+$', $email)) {
list($user, $domain) = split('@', $email);

if(checkdnsrr($domain)) {
echo "\"$email\" has a valid domain MX record:<br /><br />";
$dnsResult = dns_get_record($domain, DNS_MX);
foreach($dnsResult as $records) {
foreach($records as $key => $value) {
echo "$key: $value<br />";
}
}
} else {
echo "\"$email\" does not exist";
}
} else if($email != "") {
echo "\"$email\" is not a valid email address";
}
?>
</p>
</body>
</html>


Test it here:
http://katbox.iconrate.com/random/email_lookup.php