PHP mail function

Revision as of 17:59, 25 January 2010 by BobS (talk | contribs) (Major grammar change, and some rewriting for clarity,)

Uniform Server 3.5-Apollo.

You may be using Uniform Sever either as a test environment or for learning PHP. What you will quickly discover is PHP’s mail() function does not work. That's strictly not true. It does work, but because of its limitations, it may be prevented from working. For instance a host may require authentication, which the function does not support. Or it could simply be a case of not being set-up correctly.

Starting point

I am assuming you are not running your own mail server and do not wish to install one. All you want to do is send emails to or via your ISP mail server (as a relay) using PHP, either to test your own scripts or to test third party ones. This article looks at ways to get you up and running.

Test Scripts

I try to make UniCenter as practical as possible hence provide scripts, and when things go wrong, throw in a few error messages. This write-up is no exception, I will be using two basic scripts, which are shown below.

  • mail.html --- Basic page containing a mail form.
  • mail.php --- Script that processes the above form information
mail.html mail.php
<html>
<head><title>Mail sender</title></head>
<body>
<form action="mail.php" method="POST">
<b>Email</b><br>
<input type="text" name="email" size=40>
<p><b>Subject</b><br>
<input type="text" name="subject" size=40>
<p><b>Message</b><br>
<textarea cols=40 rows=10 name="message"></textarea>
<p><input type="submit" value=" Send ">
</form>
</body>
</html>
<html>
<head><title>PHP Mail Sender</title></head>
<body>
<?php

# Retrieve the form data
$email      = $_POST['email'];
$subject    = $_POST['subject'];
$message = $_POST['message'];

# Sends mail and report success or failure
if (mail($email,$subject,$message)) {
  echo "<h4>Thank you for sending email</h4>";
} else {
  echo "<h4>Can't send email to $email</h4>";
}
?>
</body>
</html>

Produces a form similar to this:  

Above php code

The above basic code works as is, however it is inconvenient to use. Every time you run the form (mail.htlm) all the text fields require an entry.

I am lazy and it becomes a chore, especially if you only want to change one field and to ignore the others.

I have modified this basic script, it inserts default values for empty form text boxes. This new version is the one downloadable using the above link.

The modified script is shows below.

Top

A better mail.php script

A better mail.php test script. It adds default values to empty text fields. After saving this script, one minor change is required to personalise it for your own use.

Open the file mail.php and change it as follows:

mail.php

<html>
<head><title>PHP Mail Sender</title></head>
<body>
<?php

# Retrieve the form data
$email = $_POST['email'];
$subject = $_POST['subject'];
$message = $_POST['message'];

# Check if a $_POST value exists
# If not use defaults
if (empty($_POST['email'])){
  $email = "xxx@yyy.com";
}
if (empty($_POST['subject'])){
  $subject = "UniCenter test";
}
if (empty($_POST['message'])){
  $message = "A quick test from UniCenter";
}

# Sends mail and report success or failure
if (mail($email,$subject,$message)) {
  echo "<h4>Thank you for sending email</h4>";
} else {
  echo "<h4>Can't send email to $email</h4>";
}
?>
</body>
</html>

 

Comments

Locate the the email address highlighted in bold.

Change this to your email address as provided by your ISP.

For example, if your email address is fred123@xip.com, the line will look similar to this:

if (empty($_POST['email'])){
$email = "fred123@xip.com";
}

Change default subject and message if you wish.

Top

Running the test Scripts

Start UniServer and type the following into your browser address bar: http://localhost/mail.html

There is no need to enter any data into the text boxes. Just click on Send and with luck you will receive this error message:

error message

Warning: mail() [function.mail]: Failed to connect to mailserver at "localhost" port 25, verify your "SMTP" and "smtp_port" setting in php.ini or use ini_set() in W:\www\mail.php on line 24

Can't send email to fred123@xip.com Note: should display your real email address

This error message was expected. It highlights the problem we are trying to resolve. Our script produced the last line and the warning was produced by PHP.

PHP was looking for a mail server to use. It can’t find one so it gives up. The error message is actually very informative. It's telling us where the problem is and in what file.

Top

php.ini

Open file php.ini located in folder *\Uniform Server\udrive\usr\local\php. Search for this section: [mail function] (starts at around line 612)

php.ini section [mail function] Comments

[mail function]
; For Win32 only.
SMTP = localhost
smtp_port = 25

; For Win32 only.
sendmail_from = me@localhost.com

;For Unix only. You may supply arguments as well (default: ;"sendmail -t -i").
;sendmail_path = "/usr/bin/sendmail.exe -t"

; Force the addition of the specified parameters to be passed as extra parameters
; to the sendmail binary. These parameters will always replace the value of
; the 5th parameter to mail(), even in safe mode.
; mail.force_extra_paramaters =

These are the defaults settings. You can see that PHP is looking for an SMTP server on the localhost machine and will use port 25 to communicate with it.

There is no reason why this SMTP server should be local. In theory you can use anyone’s SMTP server for relaying your mail to the appropriate recipient. (It really is a shame, but spammers have killed off this open-relay mechanism.)

ISP’s now disable open relaying and check if you are a valid customer before allowing your email to be relayed through their SMPT servers.

There are two methods they use for validation:

  1. You must be directly connected to their system as a paying user (your normal ISP Internet connection).
  2. You are not directly connected to their system, so you need a name and password to access their SMTP server.

Top

Solution 1

Since we are not running our own SMTP server and because of validation, we are restricted to using our ISP’s SMTP server. To use this server, all that is required is to point PHP at it. To do this you need to known the name of this server. A quick way to find it is to check what settings you have in Outlook Express (or the mail client you are using).

For Outlook Express use:

  1. On the top menu Click on Tools and select accounts
  2. This brings up a new form, select the Mail Tab and click on the default account name, Click on properties
  3. A new menu is opened, Click on the Servers Tab
  4. The text box named Outgoing mails (SMTP) contains the name of the server. For example, smtp.xip.com

Alternatively check your ISP’s web site and look for "how to set up an email client." The SMPT server name will found there.

php.ini section [mail function] Comments

[mail function]
; For Win32 only.
SMTP = smtp.xip.com
smtp_port = 25

; For Win32 only.
sendmail_from = me@localhost.com

;For Unix only. You may supply arguments as well (default: ;"sendmail -t -i").
;sendmail_path = "/usr/bin/sendmail.exe -t"

; Force the addition of the specified parameters to be passed as extra parameters
; to the sendmail binary. These parameters will always replace the value of
; the 5th parameter to mail(), even in safe mode.
; mail.force_extra_paramaters =

SMTP:

Replace localhost with your ISP's SMTP server name. In this example I am using smtp.xip.com.

smtp_port:

Leave the port set to 25

sendmail_from:

When a recipient reads their email, this email address is displayed in their “from box”. If you expect a reply you should use a real email address. It does not have to be one provided by your ISP.

Replace me@localhost.com with a real email address in this example I am using fred123@xip.com

Top

Test Solution 1

Test1:

Start UniServer and type the following into your browser address bar: http://localhost/mail.html

Again there is no need to enter any data into the text boxes just click on Send you will receive this message:

  • A page is displayed with the following message:
  • Thank you for sending email

Login to your mail account and check if you received the message.

Test 2:

To check if your ISP relays to other SMTP servers. Send an email to a friend or to another account you own. Make sure your ISP is not hosting these accounts.

Run the test page http://localhost/mail.html. This time you will need to fill in the text boxes. Confirm that the emails are received and that completes the tests.

Top

Problems

In the real world things never run that smoothly. Something always throws a spanner in the works. If the above fails, use this checklist to see if it either resolves the problem or points to where the problem is:

  1. You need to be connected to the Internet (via your ISP) before running your PHP program.
  2. If your host requires authentication for outgoing mail you cannot use the PHP mail function because it does not support it.
  3. Your service provider may be using an alternative port and not 25 (unlikely) Note: Check what you use in Outlook Express to confirm 2) and 3)
  4. Make sure your firewall or antivirus program is not blocking php.exe Internet access (port25).

I think that covers most causes. You may be surprised that 1) is the prime candidate, especially when testing.

Top

Summary

The above solution is quick to implement and allows you to test email scripts and any third party scripts that use PHP’s mail function.

One real drawback with this solution is that it cannot be used if your service provider requires SMTP authentication.

I noticed on the forum that to over come this problem Olajide recommends using fake sendmail for Windows. For completeness I cover this on the next page solution 2.

Top


  Ric