Sending Mail In PHP Through SMTP
Sending mail is a common task for many applications today. Whether sending mail through a webform or as an automated tasks, sending mail can be simple using PHP and PEAR. Using the sendMail() function below, you can send HTML formatted mail through any smtp server.
Update March 11, 2009: Removed the demo since GoDaddy does not support external SMTP servers.
Update July 06, 2009: Updated variables for the usage example to be less confusing. Thanks to David for pointing this out.
This function requires the following PEAR classes: Mail, Mail_Mime, Net_SMTP and any of their dependencies. This function assumes that you have your pear include path set correctly. You can download the function here (right click -> Save Link As) or copy the code from below. Scroll down for some examples/documentation.
* Sends mail by connecting to an smtp server
*
* @param string $subject
* @param string $smtp_server
* @param string $smtp_username
* @param string $smtp_password
* @param string $html html portion of the message body
* @param string $text text portion of the message body
* @param string|array $to
* @param string $from
* @param array $cc
* @param array $bcc
* @return boolean|string
*/
function sendMail($subject, $smtp_server, $smtp_username, $smtp_password,
$html, $text, $to, $from, $cc = array(), $bcc = array()) {
// require pear classes
require_once 'Mail.php';
require_once 'Mail/mime.php';
// create the heaers
$to = is_array($to) ? $to : explode(',', $to);
$headers = array(
'Subject' => $subject,
'From' => $from,
'To' => implode(',', $to),
); // end $headers
// create the message
$mime = new Mail_mime("\n");
$mime->addCc(implode(',', $cc));
$mime->addBcc(implode(',', $bcc));
$mime->setTXTBody($text);
$mime->setHTMLBody($html);
// always call these methods in this order
$body = $mime->get();
$headers = $mime->headers($headers);
// create the smtp mail object
$smtp_params = array(
'host' => $smtp_server,
'auth' => true,
'username' => $smtp_username,
'password' => $smtp_password,
'timeout' => 20,
'localhost' => $_SERVER['SERVER_NAME'],
); // end $smtp_params
$smtp = Mail::factory('smtp', $smtp_params);
// send the message
$recipients = array_merge($to, $cc, $bcc);
$mail = $smtp->send($recipients, $headers, $body);
// check to make sure there was no error
if (PEAR::isError($mail)) {
return $mail->getMessage();
} // end if there was an error
return true;
} // end function sendMail()
Using this function is simple. Simply pass in the parameters as described below:
- $subject (required): Subject for the email message.
- $smtp_server (required): SMTP Server host (ie. smtp.hostname.com).
- $smtp_username (required): SMTP username.
- $smtp_password (required): SMTP password.
- $html (required): HTML version of the message body.
- $text (required): Text version of the message body.
- $to (required): String or array of email address to send the message to (string may be comma separated list).
- $from (required): Email address that the email is being sent from.
- $cc (optional): Array of Cc email addresses.
- $bcc (optional): Array of Bcc email addresses.
For example:
$subject = 'This is an HTML email.';
$smtp_server = 'smtp.hostname.com';
$from = $smtp_username = 'user [at] hostname [dot] com';
$smtp_password = 'password';
$html = 'This is an <strong>HTML</strong> <i>formatted</i> email!';
$text = strip_tags($html);
$to = 'email [at] example [dot] com';
$cc = array('foo [at] example [dot] com');
$bcc array('bar [at] example [dot] com', 'baz [at] example [dot] com');
// send the message
$result = sendMail($subject, $smtp_server, $smtp_username, $smtp_password, $html, $text, $to, $cc, $bcc);
// check to see if the message was sent properly
if ($result !== true) {
echo 'There was an error sending the message. ('.$result.')';
} // end if the message was not sent properly
else {
echo 'Message sent successfully.';
} // end else the message was sent properly



Comments
After I figured out that the code on top doesn't match the code on bottom (i.e. - $host should be $smtp_server, $username should be $smtp_username, and $password should be $smtp_password), I was still getting an error that said "SMTP: Invalid response code received from server 535" and found out that this was due to port filtering. My system was defaulting to port 25 which is now being filtered by almost all ISP's. I was able to get around the port limitation by changing the default port. I just found the port that my host uses (2626) for outgoing mail and changed the port to that by changing this piece of code:
$host = 'smtp.hostname.com';to this:
$host = 'smtp.hostname.com:2626';Hope it helps.
While the usage example doesn't need to use the same variable names as the function definition, I can see how this could be confusing. I have modified the code for the example to make it less confusing. Thank you for pointing this out, as well as bringing up the port issue.
James I. Armes
Web Applications Developer
http://www.jamesarmes.net
When I try pear smtp on my work's server, I get the exact same error as I get through your demo of:
"There was an error sending the message: Failed to connect to smtp.gmail.com:25 [SMTP: Failed to connect socket: Connection timed out (code: -1, response: )]"
... Is that what you get when you test it ??
Very good post, thanks a lot.
Nevermind.. I guess I somehow overlooked your "update" .. so is there no way around godaddy's limitation? So I can't use my work's exchange server for email instead ?? :(
Sorry it took me so long to respond, I've been away for the past week. Unfortunately, there is no way around GoDaddy's limitation. A quick socket test will prove this:
// the following will work just fine (port 80 = http)
fsockopen('<host name>', 80);
// however, the following results in "unable to connect to
// <host name>:25 (Connection timed out)"
// (port 25 = smtp)
fsockopen('<host name>', 25);
James I. Armes
Web Applications Developer
http://www.jamesarmes.net