Jump to content

Cre8asiteforums Internet Marketing
and Conversion Web Design


Photo

The All New Form-to-Email Thread for Beginners


  • Please log in to reply
20 replies to this topic

#1 Ruud

Ruud

    Hall of Fame

  • Hall Of Fame
  • 4887 posts

Posted 30 August 2005 - 07:34 PM

Summary: What this is & isn't
[list]

[*] a script which takes the input of a form and emails it to you

[*] email address hard-coded: no spam abuse (but make sure you insert this)

[*] no validation: if someone wants to enter something which isn't an email address... their problem... If someone wants to submit an empty form: their problem
[list]
------------------------------------------------------------


OK, someone I respect a lot and whose presence here I welcome told me that, yes the stuff is hard to get sometimes.

So - here we go with a basic email form. It's basic but people won't be able to use it to spam-abuse the hell out of your setup.

What I mean with basic is that it does what it does - nothing more, nothing less. If you read through this and at any point think "this should be a function", "why doesn't he use OO?", "which design pattern is this, for crying out loud!", or wonder about security and validation -- then this thread is precisely and most exactly not meant for you.

This thread is for those who would like to get to know PHP, learn PHP, dive in. It's for those who need a place to start, a point of entry, and who would like that start to be a bit more useful than putting "hello world" on the screen.

Now, there are tens of ways of doing this. Maybe even hundreds. I stopped counting at 89 as I got bored. The way we're going to do it here is just one of those ways and not the way.

One of the ways we can do this is by putting the form as you would see it in the browser and the PHP which handles sending the email in one and the same file.

This is not that way.

Why?

The reason why I don't do it in this case is clarity. See what is what and what does what. (PHP geeks who cheated and kept reading anyway now mumble; "...and you should always seperate code from content". Don't pay attention to those; this is not their thread).

So, first thing we need is... a form. Right? Can't process a form without a form. Can't send email from the form if there isn't one.

So, first a form. A basic form:

<form action="emailthis.php" method="post">

<label>Your Name</label> <input name="the_name" type="text" />

<br />

<label>Your Email</label> <input name="the_email" type="text"  />

<br />

<label>Your Message</label>

<br />

<textarea name="message" cols="20" rows="10">

</textarea>

<br />

<input type="submit" value=" SUBMIT " />

</form>

There are several things of interest here, several things to note.

action="emailthis.php". This tells the form where the action is. Where is the "thing" that will do something with this form?

method="post". This could also have read method="get". You've all seen the get method in action when you see a URL with a query string: www.example.com/emailthis.php?name=ruud&email=ruud@example.com&message=hello

Post sends a similar serie of "stuff" but then hidden from view. Not private, not secret - just hidden from view.

All information which is passed as "get" is available in PHP in the $_GET array (more on array thingies later). All information which is passed as "post" is available in the $_POST array.

name="...". This makes it sooo much easier to tell PHP later on which input you want to process. (Go away geeks!).

So, let's step through this form and "execute" it.


The form comes up in a browser. You enter information. You hit SUBMIT. The browser goes to the page, goes to the file, specified in the action=. It "tells" that page everything that was posted from the form. It does so hidden from view (method="post") in our case.

The "stuff" has now arrived at your action file...

What action file?

Ah yes - the emailthis.php thingie. The one we don't have yet.

<?php



@mail('you@example.com','your subject line', $_POST['message'],"From: {$_POST['the_name']} <{$_POST['the_email']}>rn");



?>



Your message has been sent.

There. That wasn't so difficult, was it? And the beauty of the KISS principle is that your email address hardcoded right there (you@example.com) means no-one can mess around with your system to send spam. All they can ever possibly do is send spam to you - but why send you tons of spam?

Again, let's look at what we have here.

<?php. This tells the PHP interpreter that the fun starts here. What follows now is actual PHP code it should work with.

@. Has nothing to do with email. This is a way to suppress error messages in PHP. If for any reason the next command fails, instead of throwing an error in your face... you see nothing.

mail. The mail() function in PHP works with Linux only. On Windows you need to do other "stuff".

A function, whether one baked into PHP or one you write yourself, can take "arguments" or not. Think of arguments as variables (pieces of information) that you feed it when you ask the "thing" to do something.

A function without arguments is called like: thingie(). A function which takes a piece of text as argument can be called as: thingie('woohoo').

How do you know which, if any, arguments a function "takes"? And in what order to put them? Easy; from the extensive, searchable, and also downloadable, PHP manual.

Certain editors (programs to write code with) also have auto-complete and auto-suggest. They will prompt you with an argument list after several milli-seconds of hesitation on your side.

When I look at the entry for the mail() it tells me:

bool mail ( string to, string subject, string message [, string additional_headers [, string additional_parameters]] )


- bool: the 1st entry tells you what this function returns, what it gives back or results in, when it works. This one says bool. Boolean. It returns either TRUE or FALSE. Some functions will have array here: those return an array. Etc.

- mail: the name of the function ... but you already knew that.

- ( : the function list starts here.

- string: what type of argument is this? a number? In this case it is a string

- to: what is the meaning, the context, of this argument? This one is the "to" string. In other words: this part takes the email address you want to receive email at as an argument - and you should write it as a string (between ' or between ")

- [: the arguments between the [ ] brackets are optional. That also means that the other ones aren't optional: you have to use the other ones....

?>. This tells the PHP interpreter that the code, at least for now, stops here.

$_POST['message']. Ah yes, remember? Stuff going as "post" could be caught in the $_POST array. Stuff in the "get" we can fetch in our $_GET array.

Arrays can have many dimensions, or layers if you want, forming a matrix. Cool as the matrix may be, it maybe doesn't help you to picture the "thingie".

So, imagine a simple array as a street with houses. The houses have numbers, starting from 0: 0, 1, 2,3 etc. People live in those houses and they're happy to proclaim that by using name plates on their doors: the_name, the_email, message, Smith, etc.

If I want to "speak" to Smith I can give the address as: $street['smith']. Or, if I know the number he lives on I could say: $street[3]. In both cases I get to talk with the one inside.

Oh dang! I get Mr. Smith. And I wanted to talk to his daughter Jane instead :D ... Hm, let's try again: $street['smith']['jane']. Ah, there you are! Now I... Sorry? If I can knock on her door? Erm, sure... $street[3][2] (0 = mr smith, 1 = mrs. smith, 2 = jane). I can mix and match too: $street['smith'][2]... etc.

.....

Anyway. I know from reading the HTML form that all our "stuff" is in this "post thingie". So to get to it I ask for the right thing from that "post thingie": $_POST['the_name'], $_POST['the_email'], $_POST['message'].

{ ... }. Curly braces! How cute! ... They serve a purpose though (no seriously, they do).

PHP knows that $street is a variable, a container with stuff inside, because of the $ thingie in front. It knows that 'This is a street' is just a string. 'This is a $street' is also just a string. But "This is a $street" is a string which contains a variable. The difference here is the single vs. double quotes. When PHP encounters double quotes it always looks inside to see if anything is a variable. If so, it will replace that variable name with the actual value of it. (Notice those geeks who won't go away? they're now jumping up and down because they want you to know that that is why, if there is no variable inside a string, you should always use single quotes. It's really, really important to them. They write applications the size of a continent and saving milliseconds is very, very important to them).

So the... Curly braces? Dang, yes.. OK, so what has all this got to do with curly braces? Well, PHP is kind of stupid when it comes to figuring out which variable you mean. The curly braces around the variable name help it understand where the variable begins and ends.

That's it... You now have a basic, minimal form to email. Want to do more, learn more, tweak, adjust? ... Wait for the rest... or starting tweaking, messing, trying, experimenting.

#2 Tim

Tim

    Honored One Who Served Moderator Alumni

  • Hall Of Fame
  • 3094 posts

Posted 30 August 2005 - 07:37 PM

Ruud.. what a great post, thanks :D. I've made it into a sticky.

#3 Ruud

Ruud

    Hall of Fame

  • Hall Of Fame
  • 4887 posts

Posted 30 August 2005 - 08:00 PM

So you tried this and, dang yes, it works. You receive your own message! Coolness.

We at cre8asiteforums are always gla.... WHAT THE HELL IS THIS?!

See that?!?!

Hi,

Did you know that on her blog you-know-who recently wrote:

"Wayyyyy!!!" ?


....

I'm sorry, either this person is an idiot (valid option) or there is something horribly wrong.

Why in the world would there be a backslash before those quotes?!

It's a long story. Some of the PHP geeks on the side (no, your other side) are actually sobbing right now. Some of them are eager, I mean eager, to go into details with you.

Please use a side room as details are those things we don't have time for right now. We gotta get this fixed!


The given points of reality:
[list]

[*] this is not your mistake

[*] this is not my mistake (I told you geeks to stay away!)

[*] this is not your browser's mistake (don't even go there, ILoveJackDaniels)

[*] this can be fixed

[*] this looks like this by the time it is in your emailthis.php thingie
[list]

So by now you're thinking.

"If the content is like that but I don't want to receive it like that... I somehow have to rip it out.. delete it... destroy it..."

You're right!

"Ha! ... I have to... somehow step through that... what did he call it? string... until I see a ... and then somehow remove it... How do I do that? ... First the stepping through every character... Wait, they have a name for such repetitive actions: a loop..."

You're wrong...

These slashes that get magically added can be removed with a PHP function called stripslashes.

"Oh you gotta be kidding me! That's almost too easy!"

It is, isn't it?

So, all we have to do is modify our code a little bit.

Like this:

@mail('you@example.com','your subject line', stripslashes($_POST['message']),"From: {$_POST['the_name']} <{$_POST['the_email']}>rn");


Try it... No more "it works now!" ...

#4 Ruud

Ruud

    Hall of Fame

  • Hall Of Fame
  • 4887 posts

Posted 30 August 2005 - 08:18 PM

"Sorry to bother you but..."

No bother. Glad to help.

"... Grreat ... Erm, about this subject line: I'm bored."

Bored?

"Huh huh. Bored. I don't even open my email program anymore. I am very popular and tons of people use my email form. And now my inbox is full with 'your subject line' emails :("

Ah... I see... You would like to have a custom subject line, right?

":)"

OK...

What I thought is this... I mean, I'm not sure as I don't know PHP. All the geeks have left the building... so forgive me if I'm wrong... but...

Look at this:

<input name="the_name" type="text" />


... and then in that emailthis thingie:

@mail('you@example.com','your subject line', stripslashes($_POST['message']),"From: {$_POST['the_name']} <{$_POST['the_email']}>rn");


Couldn't we use something like that??

Lemme try that... hand me the... yes, that file yes... thanks...

..kayyy... let me squeeze that in jjjust like that...

<label>Subject</label> <input name="subject" type="text" /><br />

Ah yes... much better....

Now what was that about arrays and stuff again? Well, whatever, I see $_POST used everywhere with exactly the same name as in the form, so let's try that:

@mail('you@example.com',$_POST['subject'], stripslashes($_POST['message']),"From: {$_POST['the_name']} <{$_POST['the_email']}>rn");


<stands back and admires work>

Wow - that's actually pretty....

#5 bragadocchio

bragadocchio

    Honored One Who Served Moderator Alumni

  • Hall Of Fame
  • 15634 posts

Posted 30 August 2005 - 08:28 PM

Thanks, Ruud.

I think I'll give this a shot tonight. :D

#6 Ruud

Ruud

    Hall of Fame

  • Hall Of Fame
  • 4887 posts

Posted 30 August 2005 - 08:39 PM

.... hang on....

I mean:

HANG ON! ...

You mean I could add all kinds of extra's like that? Man, I feel like :propeller:

So, like, let's say I want to add "found your amazing site how" .. I can?

Hahahahha! :twisted:

<types madly>

<label>How I found your amazing site</label> <input name="how" type="text" />

So now what? Can I add it to the optional paramiles (I don't do this metric thing) ?

Nope.

No you can't.

You somehow have to add it to the message itself.

"Yes of course... Erm.... How?"

By using the . (= dot or full stop)

"Of course..."

Really. You can add strings together by putting a . in between.

$fullname = $name . $surname;

And if there is something you need to add just like that, like in this case a space between the name and surname, you can do that too;

$fullname = $name . ' ' . $surname . ' is crazy';

With that in mind, let's try this:

@mail('you@example.com',$_POST['subject'], stripslashes($_POST['message']) . "nHow they found me: " . $_POST['how'],"From: {$_POST['the_name']} <{$_POST['the_email']}>rn");


What that n is doing there? It's making a newline. And yes, from what you remember about PHP replacing variable names with their values in "...." strings, you could indeed also have done this:

@mail('you@example.com',$_POST['subject'], stripslashes($_POST['message']) . "nHow they found me: {$_POST['how']}","From: {$_POST['the_name']} <{$_POST['the_email']}>rn");


And yes, you're right again: you now can add any number of fields to your post, put them all on a newline in the email, prefix them all with something that helps you remember what it is anyway -- and have tons of fun.

#7 Ruud

Ruud

    Hall of Fame

  • Hall Of Fame
  • 4887 posts

Posted 30 August 2005 - 10:26 PM

FAQ

Well, with the thread just started they aren't very frequent yet -- but let's say I expect these.
[list]

[*] Can I add a dropdown?
- Yes. For the form nor the mailer is doesn't matter how the field has been filled; manually or via a dropdown.

[*] Can I add radio buttons?
- Yes. For the radio button checked the 'value' in the input element is passed (see w3schools about HTML forms)

[*] Can I add checkboxes?
- Yes. For the checked boxes the 'value' of the element is passed (see w3schools about HTML forms). Don't forget: to have only one checked, give all the same name. To have multiple checked, give them different names.

[*] I don't know what is coming from the form. Can I see it?
- Yes. Put this on top of your code:

<?php
echo '<pre>';
print_r($_POST);
echo '</pre>';

Now you can see every value passed by the form.

[*] I only want to receive email if they entered their name.
- No problem:

if (isset($_POST['the_name']) && !empty($_POST['the_name']) ) {
@mail('you@example.com','your subject line', stripslashes($_POST['message']),"From: {$_POST['the_name']} <{$_POST['the_email']}>rn");
}

! means not. && means AND. So the line reads IF this variable is present AND if it is not empty THEN email. The { } curly braces demarcate the beginning and end of the action if the condition is true.

If you know that || means OR then with some searching on the web you can extend this to do a whole lot of things...

[*] Can I put something else than 'Your message has been sent'?
- Yup. You can build a whole web page there instead.

[*] I don't want to mess with the layout of that emailthis file. Can I send them to another page?
- Yes:

header("Location: ' target='_blank'>http://www.example.com");[/b]
?>

[list]

Things you can do
[list]

[*] You can show the visitor what they submitted. The command to put things on the screen is echo.

[*] Using the IF-THEN logic you can combine the two files, the form and the mailer, into one file. IF name of submit button is not set THEN show form ELSE email

[*] If you would combine the two this way, you could in certain cases, when a user should correct an error, show the submitted values in their respective fields so they user would't have to type everything all again. echo $_POST['thingie'] would put it on the screen. Where would you put it in: <input name="thingie" type="text" value="..." /> ?

[*] Instead of using emailthis.php for layout, or send the user to another page, you could use a simple template idea. An HTML file for instance with placeholders for data like "Hi {NAME}". You could read the content of that template file (fread and use a simple string replace (str_replace) to replace these placeholders with your actual data.

[*] To achieve a similar effect or do other funky stuff, you could cache the output of the complete file/page before it gets send to the user: ob_start. Imagine what you could do....
[list]

Where to go
[list]

[*] The PHP Manual. The manual is annotated by many users. Reading their comments delivers additional insight, sometimes a nugget of code, and virtually always inspiration.

[*] Zend's PHP for Absolute Beginners

[*] A Few Common PHP Mistakes: you will make these.

[*] Introduction to PHP Objects: don't have to use it (right away) but read it so later on you know where and when the bell tolls.

[*] Tony Marston's PHP/MySQL pages: a wealth of information. Some of it might be over your head - but it is refreshing to read another take on many common PHP design ideas.

[*] Hotscripts.com: your goal here is to download, read, learn. How did they....?
[list]

#8 Ruud

Ruud

    Hall of Fame

  • Hall Of Fame
  • 4887 posts

Posted 30 August 2005 - 10:53 PM

Finally...

Finally you're programming.

Yes, you read that well. YOU are programming. Whether at home or at school, this is where we all started. Basic.

You've started to read, write, talk PHP. You're bound by its logic. It won't always seem logic to you - but there you have it.

I cannot but leave you with the encouragements of these respected posters:

And if I were to give anyone one piece of advice re. programming it would have to be - the computer is doing exactly what you told it to do, just maybe not what you actually wanted it to do...


To learn programming, you will require two things

(a) A requirement to do it

(B) Enthusiasm to learn it


As for not taking it all in, you only think this. Once you start to use a language properly, you'll see that that stuff wil come back to you. Not all at once obviously, but the more you read, it's still fresh in your memory.

Learning a new language requires time (thus experience) so be bold, and take another few steps forward


If you want to learn, you need something you want to do.
Pick a project. Learn how to do it. That way you will see a result.

...

Forget the small details, get something working, then learn more as you progress.


Finally, yes, it's more than possible to learn and use PHP in a year, and less. It's actually *harder* to learn it from a book, rather than sitting down and using it - I use the books as a reference (still) but the best way to learn these things - and not just PHP, but ASP, Javascript etc. - is to a) use it, B) ask questions, and c) experiment.


I am the living proof that somebody can learn PHP within a year (and I'm not writing PHP full time). I'm not saying I'm an expert at it but I can use PHP for the most common issues such as forms, mailing, working with variables, etc. There are probably still errors in my code or maybe there are more graceful ways to program but the code does what I want it to do.


I think you can pick up at least the basics of asp or php in a year....less really. I wouldn't say I was an expert. My code works - it does what I need it to. I'm sure I've a lot to learn about which way to do things is best and organising code. tho

You can have good html and bad html that to the end user appear to do the same thing. I'm not sure that my code isn't bad code that does the same thing as good code but in a less neat way.


"Courage" is a key word in programming, I think.

$_COURAGE ;

Courage to have a go in the first place.
Courage to admit you don't know something and start fishing in the mud.
Courage to put out a call for help, and the courage to accept help when given.
Courage to try out code, even if you don't understand it completely.
Courage to try to understand something you don't understand completely (everything makes sense eventually).
Courage to throw away something that doesn't work and start again.

And sometimes the most difficult one (for me)...

Courage to take someone else's code and learn how it works, instead of reinventing the wheel.



#9 kensplace

kensplace

    Time Traveler Member

  • 1000 Post Club
  • 1497 posts

Posted 31 August 2005 - 02:52 AM

Great stuff ruud.

10 PRINT "RUUD IS RIGHT!!!";
20 GOTO 10

RUN

RUUD IS RIGHT!!!RUUD IS RIGHT!!!RUUD IS RIGHT!!!RUUD IS RIGHT!!!
RUUD IS RIGHT!!!RUUD IS RIGHT!!!RUUD IS RIGHT!!!RUUD IS RIGHT!!!
RUUD IS RIGHT!!!RUUD IS RIGHT!!!RUUD IS RIGHT!!!RUUD IS RIGHT!!!
RUUD IS RIGHT!!!RUUD IS RIGHT!!!RUUD IS RIGHT!!!RUUD IS RIGHT!!!
RUUD IS RIGHT!!!RUUD IS RIGHT!!!RUUD IS RIGHT!!!RUUD IS RIGHT!!!
RUUD IS RIGHT!!!RUUD IS RIGHT!!!RUUD IS RIGHT!!!RUUD IS RIGHT!!!
RUUD IS RIGHT!!!RUUD IS RIGHT!!!RUUD IS RIGHT!!!RUUD IS RIGHT!!!
RUUD IS RIGHT!!!RUUD IS RIGHT!!!RUUD IS RIGHT!!!RUUD IS RIGHT!!!
RUUD IS RIGHT!!!RUUD IS RIGHT!!!RUUD IS RIGHT!!!RUUD IS RIGHT!!!

<BREAK AT LINE 10>
OK

Seriously, thats how I started, with a program like that (except mine said hello ken!) (yes on a zx81 ruud before you ask :) )

Dont ever fear learning, but if you are told to be careful, or to get help on a subject, or to research more into a certain aspect before going live on a website
then heed the warnings, or expect problems. Other than that, if you are just learning, then go for it, see what happens, then change your code to see what you can do with it, how much you can improve it.

But research what you are doing, to make sure you dont fall into any common pitfalls that beginners make, thankfully these days the internet has a great tool called google, that allows you to search for other peoples mistakes and learn from them! (How I wish I had access to the net, heck how I wish the net was around back then when I started to learn computing.....)

Bite the bullet :) get a few lines of code written, when you see a result on screen, and you understand WHY it did that, its a great feeling, and its a even better feeling when you can change that few lines of code to do something else.

From little acorns oak tree's grow - its the same with code.

#10 Adrian

Adrian

    Honored One Who Served Moderator Alumni

  • Invited Users For Labs
  • 5779 posts

Posted 31 August 2005 - 05:20 AM

From little Acorns, I moved to a PC :)

Heh, I first learnt some basic QBASIC years ago as well. I'm no expert in any programming language now, I can do a few fiddly bits in PHP, I could probably manage some VB with a bit of a memory refresh, perhaps even some C/C++, but I can't really do any terribly useful in any of them (well, I did manage one would've useful thing, that never got used, in VB).

I've literally only just learnt some of the stuff Ruud's been posting in this thread in the last few days reading a book. I quite like books, well, some of them, I just find them handier at times.

Still, very cool little tutorial, I hope there will be others in the series :)

#11 Minna

Minna

    Gravity Master Member

  • Members
  • 225 posts

Posted 31 August 2005 - 01:30 PM

Well, this is Truly a Masterpiece! :flowers:

It makes dumbfounded.
Ingenious! Stunning! Awesome! Especially I love the interactive discussion mode, as the interactive touch is the thing for me! What a delight to see The Wise to climb down from the heights to the level of the mysterious curly brackets, those that comfort a puzzled beginner with their beaty and css-connection in the massive wall of So Difficult programming.
Ruud should be given a Nobel prize.
:smileclap:

#12 matthijs

matthijs

    Unlurked Energy

  • Members
  • 5 posts

Posted 26 September 2005 - 01:15 PM

Hi, don't want to spoil the fun, but this:
<?php



@mail('you@example.com','your subject line', $_POST['message'],"From: {$_POST['the_name']} <{$_POST['the_email']}>rn");



?>
is vulnerable to email injection attacks. Spambots will use your nice simple form to abuse your mailserver to email loads of spam to others. From your contactform, from your server. Maybe I haven't read the whole thread good enough and missed some additional info, then sorry. But I saw this thread was pinned, and unless it's the purpose to get less-informed people to learn how to use vulnerable scripts, maybe some info should be given about this problem.

#13 Ruud

Ruud

    Hall of Fame

  • Hall Of Fame
  • 4887 posts

Posted 26 September 2005 - 05:40 PM

Oh absolutely. I should have done a follow-up right away.

Someone can use his knowledge of how email headers are formed to enter information in form fields which will help to add BCC and/or CC email addresses. Not what we want, right?

We saw that each line in an email header should end with rn. We could use that knowledge to our advantage to spot additional headers.

I prefer to look for the tell-tale signs of BCC and CC itself. Face it, we didn't put them in there, don't want them, and the only people trying to use them are bad people, right? Right.

So how can we look for the occurrence of a string in another string? One way would be to use strpos. But that does a case sensitive search. BCC is not bcc, not bCc, not bcC etc. That would amount to a nice serie of IF-THEN comparisons, wouldn't it?

So what oh what do we do? We dig, my friend, we dig. We dig around PHP.net. PHP is such a rich language you never seem to be able to get all functions into your head. And the commented manual is a pleasure to browse; goodies, golden nuggets, aha!-moments.

What does or click-journey bring us today? Ah, look! stristr. It does a case insensitive search. Excellent!



Erm… We do have quite a number of $_POST values to go through, don't we? I mean, everything is good and nice - but programming is meant to safe time too, right?

Well, that too we can fix. We can loop through all those $_POST's and check the same things time and time again.

foreach ($_POST as $value) {

 if (stristr($value,'bcc:') !== FALSE || stristr($value,'cc:') !== FALSE) header("Location: http://www.honeypots.net/");

}

Wow - whaddawedoing here?!

foreach is a special, and handy, way to loop through an array. The way we have written it here we get to address each time we used $_POST as the variable $value. Way handier than addressing each $_POST in the form of $_POST['email'] etc., isn't it?

Then every time we look at a $_POST variable this way, we ask PHP to have a look-see: does the string BCC exist somewhere in there? Does the string cc exist somewhere in there? And please, don't pay attention to case.

"Hmm, ooohkay…. But those two ||?"

That reads OR in PHP.

"Ah…"

Yup, take my word for it - it does.

Now, if it finds what we're looking for we do a redirect to honeypots.net, one of the sites dedicated to finding out more about hackers by setting up special systems online meant to draw hackers and script kiddies :)

Put this code in front of you @mail … and off you go to a guilt free email form life.

#14 matthijs

matthijs

    Unlurked Energy

  • Members
  • 5 posts

Posted 27 September 2005 - 02:03 AM

Hi Ruud,
thanks for your reply. You like writing don't you? :)
However, if I may I would like to continu this thread a bit with the following.

I think filtering only for cc and bcc is not enough.

As one can read in the excellent write up http://securephp.dam...Email_Injection, it's possible to inject other types of nasty content, like:

haxor@attack.com%0AContent-Type:multipart/mixed;%20boundary=frog;%0A

or

email@anonymous.xxx%0ATo:email1@who.xxx

which leads to unwanted content and extra emails being sent...

That forces us to also filter for newlines /n /r and the string content-type.

Luckily for us, some knowledgable people have been busy with this as well, and have written the following solutions:
http://www.nyphp.org...r_injection.php

function safe( $name ) {

   return( str_ireplace(array( "r", "n", "%0a", "%0d", "Content-Type:", "bcc:","to:","cc:" ), "", $name ) );

}



and/or



foreach( $_POST as $value ){

  if( stripos($value,'Content-Type:') !== FALSE ){

    mail('admin@somehwere.com','Spammer Bot Attempt',$_SERVER['REMOTE_ADDR']);

     exit("{$_SERVER['REMOTE_ADDR']} Has been Recorded");

  }

}

There are many many variations on these functions, for example:

function _isInjection($text) {

        $text = strtolower($text);

        if (preg_match('#(contents*-s*disposition)|(bcc:)|(cc:)|(contents*-s*transfers*-s*encoding)|(mimes*-s*version)|(multiparts*/s*mixed)|(multiparts*/s*alternative)|(multiparts*/s*related)|(replys*-s*to)|(xs*-s*mailer)|(xs*-s*sender)|(xs*-s*uidl)#is',$text))

        { return true; }

        else

        { return false;}

    }
thanks to Andrew from http://leftjustified.net

So my advice would be to include a bit more in the filtering. Ruuds code will probably work in 99% of the cases, because these bots do indeed try to cc or bcc loads of email adresses. But one never knows which other bot will show up tomorrow, injecting other types of unwanted stuff.....

#15 Ruud

Ruud

    Hall of Fame

  • Hall Of Fame
  • 4887 posts

Posted 27 September 2005 - 11:15 PM

Yup Matthijs (Nederland? Belgie? ZA?), I love to convey my love for programming and PHP. And I hope you too!

Instead of talking the reader through your code it would be great if you were the one doing that. A follow-up post where you show how you would use the code in the mail script. And, might I add, an excellent opporunity to shortly touch upon the idea of a function?

#16 matthijs

matthijs

    Unlurked Energy

  • Members
  • 5 posts

Posted 28 September 2005 - 02:30 AM

Ruud,
Off course I'm willing to throw some light on how one can use the code snippets I gave. Although a small disclaimer should be made: I don't consider myself a php-expert. It just happens that most of my sites were attacked the last weeks, which forced me to considerably extend my knowledge on this erea :P

So I'll give it a shot, and any further suggestions are more than welcome.

We'll start at the beginning: we recieve a bunch of data from the form in the form of the POST array. The first thing we do is declare our function:

function safe( $name ) {

   return( str_ireplace(array( "r", "n", "%0a", "%0d", "Content-Type:", "bcc:","to:","cc:" ), "", $name ) );

}

after that, we are ready to recieve our POST data. The first thing we want to do is check for any nasty content. We start simple:

if (isset($_POST['submit'])) {



$to           =   'myname@domain.com';

$from       =   $_POST['name'];

$email      =   $_POST['email'];

$message =   stripslashes($_POST['message']);

$subject    =   stripslashes($_POST['subject']);



$from        = safe($from);

$email       = safe($email);

$subject     = safe($subject);

$message  = safe($message);



$message = $from . ' said: ' . "rn";

$message .= $message;

$headers = "From: $email";



mail($to,$subject,$message,$headers);



}

This way, all unwanted content, like newlines (n, r), content-type, bcc,cc, to, is stripped out of the POST variables before going into the mail() function. So we're sure no extra email addresses are injected.

However, an email is still sent. And with those bots trying again and again, you'll get tired of receiving those fake mails, long before the bots are. Also, it would be neater to stop an attempt immediately, and receive a message if an attempt is made.

So we can also use the other function I gave earlier.

function isInjection($text) {

        $text = strtolower($text);

        if (preg_match('#(contents*-s*disposition)|(bcc:)|(cc:)|(contents*-s*transfers*-s*encoding)|(mimes*-s*version)|(multiparts*/s*mixed)|(multiparts*/s*alternative)|(multiparts*/s*related)|(replys*-s*to)|(xs*-s*mailer)|(xs*-s*sender)|(xs*-s*uidl)#is',$text))

        { return true; }

        else

        { return false;}

    }

This time, every POST value is compared (with preg_match) to the unwanted content, and if a match is found, the function returns true. If no match is found, the function isInjection returns false.
Next we get the POST vars, and do a foreach loop with the function for each var:

foreach( $_POST as $value ){ 

 if( isInjection($value) !== FALSE ){

    mail('admin@somehwere.com','Spammer Bot Attempt',$_SERVER['REMOTE_ADDR']);

     exit("{$_SERVER['REMOTE_ADDR']} Has been Recorded");

  } 





}


If for any $value the function not false (!==), we mail ourselves that an injection attempt is made, and exit the complete script. Off course, if you get tired of those warning mails, you could leave out the mail piece. However, personally I find it quite satifying to see those warning mails popping up in my mailbox, giving me the satisfaction of knowing that another attempt has failed :)

Anyway, maybe it's good to end with a complete mailscript.

<?php

function isInjection($text) {

        $text = strtolower($text);

        if (preg_match('#(contents*-s*disposition)|(bcc:)|(cc:)|(contents*-s*transfers*-s*encoding)|(mimes*-s*version)|(multiparts*/s*mixed)|(multiparts*/s*alternative)|(multiparts*/s*related)|(replys*-s*to)|(xs*-s*mailer)|(xs*-s*sender)|(xs*-s*uidl)#is',$text))

        { return true; }

        else

        { return false;}

    }



// if the submit button is hit..

if(isset($_POST['submit'])) {



foreach( $_POST as $value ){ 

 if( isInjection($value) !== FALSE ){

    mail('myadmin@mail.com','Spammer Bot  Attempt',$_SERVER['REMOTE_ADDR'],'From: mydomain');

     exit("{$_SERVER['REMOTE_ADDR']} Has been Recorded");

  } 

}



// if everything is ok, continue 

$to           =   'myname@gmail.com';

$from       =   $_POST['name'];

$email      =   $_POST['email'];

$message    =   stripslashes($_POST['message']);

$subject    =   stripslashes($_POST['subject']);





$message = $from . ' said: ' . "rn" . $message;

$headers = "From: $email";



mail($to,$subject,$message,$headers);

echo 'thanks for contacting us!';

}

?>



<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<html>

<head>

<title>Untitled</title>

</head>

<body>

<form action='<?php echo "$_SERVER[PHP_SELF]"; ?>' method='post' id='contactform'>	



 <fieldset>

  <div><label for='naam' title=' Uw naam '>naam:</label> 

  <input class='text' type='text' name='naam' id='naam' value='' size='28' />

  </div>

	

  <div><label for='email' title=' Uw e-mail '>e-mail:</label>

  <input class='text' type='text' name='email' id='email' value='' size='28' />

  </div>

  

   <div><label for='onderwerp' title=' Onderwerp '>onderwerp:</label>

  <input class='text' type='text' name='subject' id='onderwerp' value='' size='28'  />

  </div>

  

  <div><label for='bericht' title=' Uw bericht '>bericht:</label> 

  <textarea name='message' id='bericht' cols='70' rows='4' ></textarea>

  </div>

  

  <div id='buttons'><input type='submit' name='submit' value='Verstuur' class='but' /></div>



	</fieldset>



</form>

</body>

</html>

(p.s. never mind the dutch language in the form)
And finally, there are even more things you could filter for, like stripping out any html. There's a php function for that too: strip_tags. You use it the same way as the other functions.
$message=strip_tags ($message);
So if you want to prevent html coming through. However, I think most email-clients nowadays strip out any html themselves, or you can choose to show it or not.

That's it. Hope it's all clear, and I didn't make too many typo's ;) And feel free to correct me, add suggestions, better ways etc.


And Ruud, indeed from Nederland!

#17 manager

manager

    Time Traveler Member

  • 1000 Post Club
  • 1331 posts

Posted 15 January 2006 - 07:32 PM

Hi Ruud and Matthijs

I write to re-open the subject so we can arrive at a complete secure form to email script

To very quickly summarise the relevant posts; (not to criticise your sterling efforts) :)

- Ruud provided a form to email script with lots of advice (an excellent lecture).
- Some week’s later; matthijs replied that the script was insecure
- Ruud posted adjustments to the script.
- In respponse;Matthijs posted his complete script.

I have done some testing,
The script by matthijs does not: attempt to validate emails, empty fields, or enforce required fields. So whilst it maybe secure? It could be argued that it’s not very practical.

I couldn’t follow the first example. Aint got the brains; maybe some bright person could cobble it together and post a complete secure working script, wasn't that; the aim of this post ? :)

Trev

#18 matthijs

matthijs

    Unlurked Energy

  • Members
  • 5 posts

Posted 19 January 2006 - 05:22 AM

Hi Trev,
saw your post today. You are absolutely correct, the examples can be further improved. I'll put together a more thorough example in the next days and post it here. Further validating of the fields would be a good addition.

Matthijs

(of course, to anyone: feel free to post your contributions)

[edit: ] Sorry to not have posted yet. I started today but I don't have time to finish it. I would like to do it right and include some explanation etc so need some more time. Promise to return. But first a week holiday.

Edited by matthijs, 27 January 2006 - 11:30 AM.


#19 bearmugs

bearmugs

    Mach 1 Member

  • Members
  • 261 posts

Posted 19 May 2006 - 01:34 PM

Is it possible to program a Windoze computer into thinking it actually can get the job done. It seems they're all born with this inferiority complex. LOL

10 for r=1 to 50
20 print "I am a brilliant windoze computer"
30 next r

<BREAK> syntax error: invalid argument "brilliant windoze computer"

John EH! :rofl:

#20 hypnoticvibe

hypnoticvibe

    Whirl Wind Member

  • Members
  • 75 posts

Posted 10 January 2007 - 01:48 AM

This is awesome info and well written! It's broken down so extremely well that even I'm following it - lol. I can't seem to understand 1 part in the first post though:
"From: {$_POST['the_name']} <{$_POST['the_email']}>rn");
I don't understand what purpose < and > are serving. Also, rn as well. I know \r\n starts a new line (I think) but I'm not following how putting them side by side as just rn is working.
Could someone explain?
Thanks.

Edited by hypnoticvibe, 10 January 2007 - 02:10 AM.


#21 Guest_joedolson_*

Guest_joedolson_*
  • Guests

Posted 10 January 2007 - 12:23 PM

"From: {$_POST['the_name']} <{$_POST['the_email']}>rn");


The From header in a mail command can accept two parts: it requires an email, but can also accept a word or name which will be associated with the email. In this case, it's taking the name and associating it with the email. Imagine it like this:

From: John Smith <john.smith@smithfactory.com>

Taking away the PHP and displaying just what will be sent, it's pretty clear what's going on: you've probably seen this kind of thing many times in your own mail client, since this same format is used in a wide variety of situations. It's just providing a separate display name to be associated with the sending email address.

No idea why the "rn", though.

:)



RSS Feed

0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users