Full Version: Send Emails Using Php (SMTP Direct)
Dream.In.Code > Programming Tutorials > PHP Tutorials
no2pencil
Send Emails Using Php (SMTP Direct)

This is an alternative way to generate & send an email under php, rather than using the pre-defined mail() function.

Reasons:
In what situations would you not want to use something as simple as the mail function?

1.) Your php/web server does not offer mail.
On our internal network, the mail server exists on a server other than the web server.
Therefore, mail() will fail to send since
a.) port 25 is blocked
b.) sendmail is disabled

2.) Your mail server doesn't use the default port 25 for sending email.
If you are running a server on non-commercial service, you know what I'm talking about =-)
This can, however, be changed via the php.ini configuration file.

3.) Because you can.
It allways feels good (maybe even better) when you know the how's & why's to your equipment & software. So why just send an
e-mail when you can build one?!

4.) Your sendmail_from value needs to change on the fly.
Maybe you host multiple accounts, & one sendmail_from value is not enough. Maybe you are hosting something much more
advanced & this single setting just isn't enough.
Auto-responders, Auto-forwards, the list is endless.

The setup:
Since I use qmail as my MTA (mail transfer agent) that's the example you'll get. Please refer to the documentation that came with
your MTA, should you be setting up something different.

1st, we need to define the function to use instead of mail().
CODE

<?php

function authgMail($from, $namefrom, $to, $nameto, $subject, $message) {


As you can see, we've allready got a few more arguments than mail() has to offer.

authgMail <- my chosen function name, you can alter this as you please. Just make sure that it isn't a keyword or existing function.

Now to setup those values...
CODE

$smtpServer = "192.168.xxx.xxx";   //ip address of the mail server.  This can also be the local domain name
$port = "25";                     // should be 25 by default, but needs to be whichever port the mail server will be using for smtp
$timeout = "45";                 // typical timeout. try 45 for slow servers
$username = "sales@mydomain.com"; // the login for your smtp
$password = "myPA$$";            // the password for your smtp
$localhost = "127.0.0.1";       // Defined for the web server.  Since this is where we are gathering the details for the email
$newLine = "\r\n";             // aka, carrage return line feed. var just for newlines in MS
$secure = 0;                  // change to 1 if your server is running under SSL


Those should be the only values that you need to change to match your own internal settings.
The rest is the functionality of the server & those values. The variable $smtpResponse is going to let you know what's going on.
You can use it to show you every step along the way, or just show errors reported back from the mail server.
Now, lets build that e-mail!

CODE

//connect to the host and port
$smtpConnect = fsockopen($smtpServer, $port, $errno, $errstr, $timeout);
$smtpResponse = fgets($smtpConnect, 4096);
if(empty($smtpConnect)) {
   $output = "Failed to connect: $smtpResponse";
   echo $output;
   return $output;
}
else {
   $logArray['connection'] = "<p>Connected to: $smtpResponse";
   echo "<p />connection accepted<br>".$smtpResponse."<p />Continuing<p />";
}

//you have to say HELO again after TLS is started
   fputs($smtpConnect, "HELO $localhost". $newLine);
   $smtpResponse = fgets($smtpConnect, 4096);
   $logArray['heloresponse2'] = "$smtpResponse";
//request for auth login
fputs($smtpConnect,"AUTH LOGIN" . $newLine);
$smtpResponse = fgets($smtpConnect, 4096);
$logArray['authrequest'] = "$smtpResponse";

//send the username
fputs($smtpConnect, base64_encode($username) . $newLine);
$smtpResponse = fgets($smtpConnect, 4096);
$logArray['authusername'] = "$smtpResponse";

//send the password
fputs($smtpConnect, base64_encode($password) . $newLine);
$smtpResponse = fgets($smtpConnect, 4096);
$logArray['authpassword'] = "$smtpResponse";

//email from
fputs($smtpConnect, "MAIL FROM: <$from>" . $newLine);
$smtpResponse = fgets($smtpConnect, 4096);
$logArray['mailfromresponse'] = "$smtpResponse";

//email to
fputs($smtpConnect, "RCPT TO: <$to>" . $newLine);
$smtpResponse = fgets($smtpConnect, 4096);
$logArray['mailtoresponse'] = "$smtpResponse";

//the email
fputs($smtpConnect, "DATA" . $newLine);
$smtpResponse = fgets($smtpConnect, 4096);
$logArray['data1response'] = "$smtpResponse";

//construct headers
$headers = "MIME-Version: 1.0" . $newLine;
$headers .= "Content-type: text/html; charset=iso-8859-1" . $newLine;
$headers .= "To: $nameto <$to>" . $newLine;
$headers .= "From: $namefrom <$from>" . $newLine;

//observe the . after the newline, it signals the end of message
fputs($smtpConnect, "To: $to\r\nFrom: $from\r\nSubject: $subject\r\n$headers\r\n\r\n$message\r\n.\r\n");
$smtpResponse = fgets($smtpConnect, 4096);
$logArray['data2response'] = "$smtpResponse";

// say goodbye
fputs($smtpConnect,"QUIT" . $newLine);
$smtpResponse = fgets($smtpConnect, 4096);
$logArray['quitresponse'] = "$smtpResponse";
$logArray['quitcode'] = substr($smtpResponse,0,3);
fclose($smtpConnect);
//a return value of 221 in $retVal["quitcode"] is a success
return($logArray);
}



Ok, that wasn't so bad... Now we can use php to error check the values passed in from a form, to verify that the server is not going
to get some bogus value, or empty records & freak out.
CODE

$err=0;  // so far, so good
$err_msg="";

if($_POST['name_']!="") { echo $_POST['name_']."<br>"; }
else {
  $err=1;
  $err_msg="You must include your name";
}

if($_POST['day_phone_']!="") {echo $_POST['day_phone_']."<br>"; }
else {
  $err=1;
  $err_msg="You must include a daytime phone number.";
}
if($_POST['add_']!="") { echo $_POST['add_']."<br>"; }
else {
  $err=1;
  $err_msg="You must include your address.";
}
if($_POST['city_']!="") { echo $_POST['city_']."<br>"; }
else {
  $err=1;
  $err_msg="You must include the city.";
}
// Check for the existence of an AT symbol inside the email.
if (strpos($_POST['email'],"@")) { echo $_POST['email']."<br>"; }
else {
  $err=1;
  $err_msg="You must include a current email address.";
}
if($_POST['email']!="") { echo $_POST['email']."<br>"; }
else {
  $err=1;
  $err_msg="You must include your e-mail address.";
}

echo $err_msg;

if($err<=0) {
  $from="sales@mydomain.com";
  $namefrom="Internal Sales Dept. of mydomain.com";
  $to = "internal_user@mydomain.com";
  $nameto = "internal_user";
  $subject = "Email from My Domain";
  $message = "Email from My Domain";
  // this is it, lets send that email!
  authgMail($from, $namefrom, $to, $nameto, $subject, $message);
}
else {
  echo "<p /> This form was not filled out correctly, please correct any mistakes.";
}

?>


In Conclusion:
As you can see, it very easy to send an email using php & connecting directly to your smtp server.
In addition you can add more receivers by either adding their addresses, comma separated, to the $to variable, or by adding cc: or bcc: headers.
If you don't receive an email using this script, then you may have installed PHP incorrectly, you may not have permission to send emails, or you may have misconfigured your MTA.
Before running this script, verify that your current MTA is working. That way you can trouble shoot this script, knowing that your MTA is set to recieve incomming connections.

ahmad_511
Thanks.
It's Clear, Simple, quick, and ...
I love it.
yuzz
Hi! Nice article, only one question: Isn't using an IP address in the HELO wrong? I thought it had to be a hostname (FQDN)?
no2pencil
QUOTE(yuzz @ 19 Nov, 2007 - 11:16 AM) *

Hi! Nice article, only one question: Isn't using an IP address in the HELO wrong? I thought it had to be a hostname (FQDN)?

When the mail recipient receives the email, they will either resolve the FQDN to an ip address, or accept the ip address. If the recipients mail server issues a reverse DNS lookup, it'll use the IP address (resolved or given) to lookup the FQDN. I'm sure for security sake, that it's possible to not accept email from a server issues an IP Address in the HELO. The example I used here is sending the email inside the network, so it isn't an issue. Good point though, I'll continue to check into it further.
Allaboutdatingsites
Hello, Really Great Tutorial. I am wondering if you could give an example of how to "set" the bcc header? You mentioned it at the end of the article but I don't have a clear understanding of how to do it and the five different ways I have tried don't work. I do have it working as written, though I had to use EHLO rather than the HELO listed in the post, something about the AUTH requirement... Thanks in advance for any pointers on how to get the bcc piece to work.

Warmest regards,

allaboutdatingsites
muhammad0105

icon_up.gif that's really nice tutorial and helped me loads. however i am more interested in tutorial which help me in retrieving mails from mail server using imap functions. also provide tutotial about 'user agen' and MTA. biggrin.gif thankyou
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Invision Power Board © 2001-2008 Invision Power Services, Inc.