SSL Part 2: PHP mail function

Revision as of 17:36, 24 November 2010 by Olajideolaolorun (talk | contribs) (Reverted edits by Upazixorys (Talk); changed back to last version by Ric)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

PHP mail function problem
Signed Certificate Project
Uniform Server 3.5-Apollo

With your e-mail server working I suppose one of the first things to try is PHP’s mail function. A very simple looking function with the power to make you rip your hair out when you discover it does not work.

The truth is it does work, in reality it’s a lack of understanding, which this page attempts to address. When I used this function for the first it failed imagine my surprise when I discovered it required a mail server. Even after acquiring a mail server it persistently refused to work.

Most problems are solvable however first you need to understand what the failure mechanism is. The following examples use our mail-sever as describe on the previous two pages to investigate PHP’s mail function and server interaction.

Basic PHP mail function

All examples use a variant of the following script running on Uniform Server 3.5-Apolo. I assume you have set-up your email client with a “postmaster” account ( see previous page)

mail_test_1.php
<html>
<head><title>Mail Test 1</title></head>
<body>

<?php
$to_email = "postmaster@mpg123.no-ip.org";  
$subject  = "Mail Test 1";              
$message  = "Basic PHP mail function";

if (mail($to_email,$subject,$message)){
 echo '<br>Mail accepted for delivery<br>';
}
else{
 echo 'There was an error. Mail not accepted for delivery';
}
?>
</body>
</html>

Test 1:

Run script: Type into your browser http://localhost/mail_test_1.php
Result: Mail accepted for delivery
Email client: From: me@localhost.com
  Subject: Mail Test 1

The script clearly works, mailed was delivered to our recipient “postmaster” perhaps what is a little surprising is where the mail came from me@localhost.com!

That e-mail address does not exist, either in our script or e-mail server. A recipient wanting to reply clearly would have a problem.

The address is automatically added by PHP. Address used is that set in the php.ini file located in folder *\Uniform Server\udrive\usr\local\php.

Line 617: sendmail_from = me@localhost.com

Suppose you want all your PHP e-mail scripts to reply to a single address changing the php.ini file to that address would achieve the result required. To see this in action change the line in php.ini to sendmail_from = me2@localhost.com run the above script again. This is a small change to illustrate a point and not a practical solution.

Note: The above is extremely important you need to think of the combined script and php.ini as a mini-smtp server. It will only relay (deliver) mail to the local server (Line 614: smtp_port = 25) and to a single account defined by (Line 617) sendmail_from = me2@localhost.com.

Top

Basic PHP mail function - Problem

The above demonstrates our script and mail server are working. This next test I am sure you will be familiar with or at least the resulting error message. Change the script, replace to email address with your real e-mail address (as provided by your ISP)

mail_test_2.php
<html>
<head><title>Mail Test 1</title></head>
<body>

<?php
$to_email = "real_name@real_domain";  
$subject  = "Mail Test 2";              
$message  = "Basic PHP mail function";

if (mail($to_email,$subject,$message)){ // Line 10
 echo '<br>Mail accepted for delivery<br>';
}
else{
 echo 'There was an error. Mail not accepted for delivery';
}
?>
</body>
</html>

Test 2:

Run script: Type into your browser http://localhost/mail_test_2.php
Result:

Warning: mail() [function.mail]: SMTP server response: 550 Delivery is not allowed to this address. in W:\www\mail_test_1.php on line 10
There was an error. Mail not accepted for delivery

Error 550 means that this mail server does not allow relaying! The address (implied) on line 10 is your real e-mail address!

Test: Using the postmaster account you set-up in your client. send yourself an email (to your ISP email account).

The test demonstrates you can relay email through your email server, to your ISP and receive mail. Clearly the above error message is not referring to your real address.

Remember the importance of test 1! Its referring to that address from the mini-smtp server. The problem is our local mail server sees this as an external server.


The answer to the problem is on this page Internet IP ranges section 10 it defines what is allowed to relay through the server. I have reproduced the image below:

 

A quick and disastrous solution is to check the bottom box and allow external-to-external relaying.

This would be instant death for any e-mail server, not only would you be blacklisted but you open your server for every one to use where they can relay all unsavory stuff and spam.

Solution:

The solution is interesting all four selectable options have one thing in common accounts!

Does our mini-server me2@localhost.com have an account on our hMailServer of course not we never set one-up.

Do we have a domain localhost.com well we never set that up either.

You can set-up an account for me2@localhost.com in any domain however it is preferable to create a new domain just in case you delete the one it resides in killing off all your PHP scripts.

Creating a new domain and account see below:


 

Create new domain:

  1. Login to hMailServer
  2. Click Welcome (left menu)
  3. Click Add domain (right page)
  4. Domain name: Enter localhost.com
  5. Catch-all address: Enter me2 and localhost.com
  6. Click Save

 

Create new account:

For the catch-all address to become active it requires an account.

  1. Account address: Enter me2
  2. Password: Enter a password (me2pass)
  3. Click Save

Note: The password is required only to create the account it is never used by scripts.


Re-Run:

Repeat the original test:

Run script: Type into your browser http://localhost/mail_test_2.php
Result: Mail accepted for delivery Indicates mail was sent (Script is working!)
Mail Client:    Wait for the mail to be delivered. After a reasonable time refresh your e-mail client.
Result: From: me2@localhost.com
  Subject: Mail Test 2

Both hMailServer and PHP has been set-up correctly however that strange from address (me2@localhost.com) needs resolving. You have two options depending on your requirements.

1) Common address

If all your scripts expect all recipients to reply to a single address you can change php.ini and hMailServer to reflect that address.

2) Generic address

Solution one is specific and inflexibly however you have a server that is capable of relaying any standard e-mail. The real solution lies in PHP’s mail function and the use of its fourth parameter covered in the next section.

Top

Basic PHP mail function - Reply address

PHP's basic mail function allows you to specify a fourth parameter. This parameter is primarily used for inserting MIME types however it also allows you to specify a “from address”.

mail_test_3.php
<html>
<head><title>Mail Test 3</title></head>
<body>

<?php
$to_email = "real_name@real_domain";  
$subject  = "Mail Test 3";              
$message  = "Basic PHP mail function";
$from     = "fred@someone.com";

$headers ="From: ". $from . "\r\n";

if (mail($to_email,$subject,$message,$headers)){
 echo '<br>Mail accepted for delivery<br>';
}
else{
 echo 'There was an error. Mail not accepted for delivery';
}
?>
</body>
</html>

Test 3:

$from: Set this variable to the e-mail address you wish a recipient to reply to.
Note: The $headers string created must include \r\n to define a MIME boundary without it some mail clients may throw a wobbly!


Run script: Type into your browser http://localhost/mail_test_3.php
Wait a short time for the mail to be delivered and then read your e-mail.
Result: The from address will display fred@someone.com

Summary

I hope you found the above digression of interest; PHP’s basic mail function always seems to give new users grief. I faced the same problem because of a basic lack of understanding; thinking in terms of a mini-smtp server helps to visualise the problem. You may be interested in alternative solutions there are two covered on this page.

Enough of this lets continue with our quest for a signed certificate.

Top


  Ric