1.0 Introduction

There are many instances when you (as a web master/site owner) want to send your users an email, or allow the users send other users an email. Obviously you would want to code some permissions into that and enable the users to disable other users to send emails to them, otherwise it could get quite ugly.

The main purpose of this tutorial is to break down existing code into little bits and explain what each line does, so when you are using the code, you would be able to use it and actually understand what it's doing.

1.1 Copyright Notice

This class isn't my original, so I don't own this class. I got it as a simple PHP page and converted it into a class and edited it a bit... but I didn't create it from scratch.

2.0 SMTP Servers

Most hosts provide an SMTP server (and POP server) that is available for you to use for this very purpose. In most cases, the link to the SMTP server would look something like: smtp.myhost.com.

In most cases a normal port to SMTP would be 25 while a secure port to SMTP would be 465. If it's not those ports then the host should tell you which ports are the SMTP ports. (They will tell you the ports even if they are those ports).

2.1 SMTP Alternatives

If, for any reason your host does not provide you with an SMTP server for you to use, there are a few alternatives out there that you can use. The first one that comes to mind is gmail.

Gmail allows you to use their SMTP server to send email messages for free and without any hassle. By that, I mean you don't have to go to gmail and enable SMTP or anything like that... it's always there so all you need to do is fill out the information into the script and it would work. Below are the information that enables you to use their SMTP server:

SMTP server: smtp.gmail.com
Port: 587
Username: {your gmail email (e.i: myname@gmail.com)}
Password: {your password to your email}

There are others besides gmail that provide you with an SMTP server. One, for example, is SMTP.com, but as you can see, that is a bit more expensive alternative that gmail.com is.

3.0 The Class Initiation

I've wanted a simple class to enable me to have user's send to users, me send to users and then user's sending to me... I found a function that limited the email service to me sending to users and that's it. Obviously there must be something that I had to do, to increase the capabilities of that function.

The way I wanted to use that function is:

new mail($to, $subject, $message)

A one-liner, in my opinion, is a really big plus when it comes to this... a one liner that returns true if the message was sent or false if the message failed to be sent.

This enables me to wrap that one liner with an if() statement and return the user with the status of their message.

3.1 The Variable Declaration

There are a few variables declared in the class to make this class usable:

class mail {
    private $smtpServer = 'smtp.gmail.com';
    private $port = '587';
    private $timeout = 30;
    private $username = 'myname@gmail.com';
    private $password = 'mypassword';
    private $username_email = 'myreceivingemail@gmail.com';
    private $newline = "\r\n";
    private $localdomain = 'https://www.mysite.com';
    private $charset = 'windows-1251';
    private $contentTransferEncoding = false;

    // Do not change anything below
    private $smtpConnect = false;
    private $to = false;
    private $subject = false;
    private $message = false;
    private $headers = false;
    private $logArray = array(); // Array response message for debug
    private $Error = '';
    private $from = false;
}

Here are those variables broken down.

  • smtpServer
    • The SMTP server you would be connecting to and using to send messages
  • port
    • The port that you would be using to connect to the SMTP server
  • timeout
    • length of time (in seconds) that the script would try to connect before deciding it won't connect
  • username
  • password
    • The password to that email to enable the use of the SMTP server
  • username_email
    • This is the email that will receive the messages from the user... doesn't have to be from Gmail.
  • newline
    • This is how the script will make newlines in the error and debug messages.
  • localdomain
    • This is a link to your site.
  • charset
    • The character set (encoding I believe) that is used in that message
  • contentTransferEncoding
    • If set to true, it would put in the header that the content is encoded (I believe... don't think it would actually encode the content
  • smtpConnect
    • This would be holding the SMTP link identifier on success and false on failure. Would be used to determine the status of the connection (obviously)
  • to
    • The Email address to whom the message is addressed to.
  • subject
    • This would be the subject of the email being sent.
  • message
    • The actual body of the message.
  • headers
    • This will hold the headers to the message in the class... it's declared here as a holder to be used later on. Not meant to be changes and set to different headers here in the declaration.
  • logArray
    • This array would hold every response (sent?) and received within the script for debug. It would be printed into the source (not the page) for debug purposes (it would be the first thing between the HTML comments tag <!-- debug -->
  • Error
    • This variable would hold the errors that it came across and upon failure, it would print the errors for everyone to see.
  • from
    • This variable is used in the constructor function to figure out who is sending. If to_admin (in constructor function) is set to true then the from variable would be set to the user's email address... if the variable to_admin is set to false, then the from variable would be set to the admin's email address.

3.2 The Constructor Function

The constructor function is what brings everything to one place and enables you to use the features of the class.

function __construct($to, $subject, $message, $to_admin) {

The construct function declaration. Sets the dynamic variables that would be used throughout the entire class.

    $this->to = (($to_admin === true) ? $this->username_email : $to );

This is the line that determines the recipient of the email message. If $to_admin is true then it's to admin, otherwise it's not to admin.

    $this->from = (($to_admin === false) ? $to : $this->username_email );

This is the line that determines the sender of the email message. If $to_admin is set to true then it's not from the admin, otherwise it is. (This probably needs some editing to have it be correct when it's from user to user).

    $this->subject = &$subject;

Well, this be the subject of the message.

    $this->message = &$message;

And this here is the message of the message.

    // Connect to server
    if(!$this->Connect2Server()) {

Here is where we check the result of the connection attempt. Checking specifically for failure. If it's a success we don't need (shouldn't) echo anything.

        // Display error message
        echo '<pre>'.trim($this->Error).'</pre>'.$this->newline.'<!-- '.$this->newline;
        print_r($this->logArray);
        echo $this->newline.'-->'.$this->newline;
        return false;
    }

This is where we print the errors to the screen and the debug to the source code... we also return false to let you print a message to the user telling them that sending that message didn't work out.

    return true;
}

If the connection worked, and the if statement that checks for failure didn't trigger, then we return true to enable you to print a message to the user telling them that the message was sent successfully.

Below is the function in it's entirety.

public function __construct($to, $subject, $message, $to_admin) {
    $this->to_admin = $to_admin;
    $this->to = (($this->to_admin === false) ? $this->username_email : $to );
    $this->from = (($this->to_admin === false) ? $to : $this->username_email );
    $this->subject = &$subject;
    $this->message = &$message;

    // Connect to server
    if(!$this->Connect2Server()) {
        // Display error message
        echo '<pre>'.trim($this->Error).'</pre>'.$this->newline.'<!-- '.$this->newline;
        print_r($this->logArray);
        echo $this->newline.'-->'.$this->newline;
        return false;
    }
    return true;
}

3.3 Connecting to the SMTP Server

Now what we need to do is connect to the server.

private function Connect2Server() {

Here we initiate the function. We make this function private since only this class is supposed to have access to the function.

    // Connect to server
    $this->smtpConnect = fsockopen($this->smtpServer,$this->port,$errno,$error,$this->timeout);

Here we actually connect to the SMTP Server using the information provided in the variables declared.

    $this->logArray['CONNECT_RESPONSE'] = $this->readResponse();

Here we log the response/result of the attempted SMTP connection.

    if (!is_resource($this->smtpConnect)) {
        return false;
    }

If the connection failed, we return false. Returning something at this point stops the function from continuing and ends the script.

    $this->logArray['connection'] = "Connection accepted";

If we reached this point, it means that the SMTP server was successfully connected to... lets log it for debug purposes.

    // Hi, server!
    $this->sendCommand("HELLO {$this->localdomain}");
    $this->logArray['HELLO'] = $this->readResponse();

Here is where we introduce our site to the SMTP server and store the response from the SMTP server for debug purposes.

    // Let's know each other
    $this->sendCommand('AUTH LOGIN');
    $this->logArray['AUTH_REQUEST'] = $this->readResponse();

Here is where the script is requesting permission and initiate the username/password phase of the connection process. We are store the response for debug purposes.

    // My name...
    $this->sendCommand(base64_encode($this->username));
    $this->logArray['REQUEST_USER'] = $this->readResponse();

We are providing the SMTP server with our username, and store the response for debug purposes.

    // My password..
    $this->sendCommand(base64_encode($this->password));
    $this->logArray['REQUEST_PASSWD'] = $this->readResponse();

In this phase, we are sending the password, and then store the response for debug purposes.

    // If error in response auth...
    if (substr($this->logArray['REQUEST_PASSWD'],0,3)!='235') {
        $this->Error .= 'Authorization error! '.$this->logArray['REQUEST_PASSWD'].$this->newline;
        return false;
    }

Here is where we check the result of the login process. We store the error in the error variable and returning false, stopping the script.

    // "From" mail...
    $this->sendCommand("MAIL FROM: {$this->from}");
    $this->logArray['MAIL_FROM_RESPONSE'] = $this->readResponse();

Here we tell the SMTP server who the message is sent from and store the response for debug purposes.

    if (substr($this->logArray['MAIL_FROM_RESPONSE'],0,3)!='250') {
        $this->Error .= 'Mistake in sender\'s address! '.$this->logArray['MAIL_FROM_RESPONSE'].$this->newline;
        return false;
    }

Checking the result of the validation of the 'from' address. If the response isn't correct, we store the error in the error variable and return false, stopping the script.

    // "To" address
    $this->sendCommand("RCPT TO: {$this->to}");
    $this->logArray['RCPT_TO_RESPONCE'] = $this->readResponse();

Here we tell the SMTP server the address to whom the message was written to. Then we store the response for debug purposes.

    if(substr($this->logArray['RCPT_TO_RESPONCE'],0,3) != '250')
    {
        $this->Error .= 'Mistake in reciepent address! '.$this->logArray['RCPT_TO_RESPONCE'].$this->newline;
        return false;
    }

Here we are checking the result of the validation of the recipient's email address. Storing the error and returning false, stopping the script.

    // Send data to server
    $this->sendCommand('DATA');
    $this->logArray['DATA_RESPONSE'] = $this->readResponse();

Here we send the data and storing the response for debug purposes.

    // Send mail message
    if (!$this->sendMail()) return false;

Here we send the mail message... we check specifically for failure, and if it failed, returning false, which enables you to write your own failure message.

    // Good bye server! =)
    $this->sendCommand('QUIT');
    $this->logArray['QUIT_RESPONSE'] = $this->readResponse();

Here we are preparing to disconnect from the SMTP server. Storing the response for debug purposes.

    // Close smtp connect
    fclose($this->smtpConnect);
    return true;
}

Here we are actually disconnecting from the SMTP server. Since we got to this point, the mail was sent, and everything worked correctly, so we are returning true for success.

The reason we have the 'QUIT' command and then the disconnection, instead of just disconnecting, is the same reason why you press 'Shut Down' to turn your computer off, instead of just pulling the plug. (At least that's how I see it).

Now, here is that function in it's entirety.

private function Connect2Server() {
    // Connect to server
    $this->smtpConnect = fsockopen($this->smtpServer,$this->port,$errno,$error,$this->timeout);
    $this->logArray['CONNECT_RESPONSE'] = $this->readResponse();

    if (!is_resource($this->smtpConnect)) {
        return false;
    }
    $this->logArray['connection'] = "Connection accepted";
    // Hi, server!
    $this->sendCommand("HELLO {$this->localdomain}");
    $this->logArray['HELLO'] = $this->readResponse();
    // Let's know each other
    $this->sendCommand('AUTH LOGIN');
    $this->logArray['AUTH_REQUEST'] = $this->readResponse();
    // My name...
    $this->sendCommand(base64_encode($this->username));
    $this->logArray['REQUEST_USER'] = $this->readResponse();
    // My password..
    $this->sendCommand(base64_encode($this->password));
    $this->logArray['REQUEST_PASSWD'] = $this->readResponse();
    // If error in response auth...
    if (substr($this->logArray['REQUEST_PASSWD'],0,3)!='235') {
        $this->Error .= 'Authorization error! '.$this->logArray['REQUEST_PASSWD'].$this->newline;
        return false;
    }
    // "From" mail...
    $this->sendCommand("MAIL FROM: {$this->from}");
    $this->logArray['MAIL_FROM_RESPONSE'] = $this->readResponse();
    if (substr($this->logArray['MAIL_FROM_RESPONSE'],0,3)!='250') {
        $this->Error .= 'Mistake in sender\'s address! '.$this->logArray['MAIL_FROM_RESPONSE'].$this->newline;
        return false;
    }
    // "To" address
    $this->sendCommand("RCPT TO: {$this->to}");
    $this->logArray['RCPT_TO_RESPONCE'] = $this->readResponse();
    if(substr($this->logArray['RCPT_TO_RESPONCE'],0,3) != '250')
    {
        $this->Error .= 'Mistake in reciepent address! '.$this->logArray['RCPT_TO_RESPONCE'].$this->newline;
    }
    // Send data to server
    $this->sendCommand('DATA');
    $this->logArray['DATA_RESPONSE'] = $this->readResponse();
    // Send mail message
    if (!$this->sendMail()) return false;
    // Good bye server! =)
    $this->sendCommand('QUIT');
    $this->logArray['QUIT_RESPONSE'] = $this->readResponse();
    // Close smtp connect
    fclose($this->smtpConnect);
    return true;
}

3.4 The Function that Sends

This is the function that does the actual sending of the email message.

private function sendMail() {

Once again we create this function as private.

    $this->sendHeaders();

Here is where we initiate the function that creates and sends the headers of the mail message

    $this->sendCommand($this->message);
    $this->sendCommand('.');
    $this->logArray['SEND_DATA_RESPONSE'] = $this->readResponse();

Here we are sending the data and storing the response for debug purposes.

    if(substr($this->logArray['SEND_DATA_RESPONSE'],0,3)!='250') {
        $this->Error .= 'Mistake in sending data! '.$this->logArray['SEND_DATA_RESPONSE'].$this->newline;
        return false;
    }

Here we are checking the sending process for failure. If it failed we would store the error in the variable and return false, stopping the script.

    return true;
}

Since we got to this point, the message was sent successfully, so we are returning true for success

Here is that function in it's entirety.

private function sendMail() {
    $this->sendHeaders();
    $this->sendCommand($this->message);
    $this->sendCommand('.');
    $this->logArray['SEND_DATA_RESPONSE'] = $this->readResponse();
    if(substr($this->logArray['SEND_DATA_RESPONSE'],0,3)!='250') {
        $this->Error .= 'Mistake in sending data! '.$this->logArray['SEND_DATA_RESPONSE'].$this->newline;
        return false;
    }
    return true;
}

3.5 Reading the responses

We now need to create a function that reads the responses sent to us by the SMTP server.

// Function read response
private function readResponse() {

Once again... private function

    $data="";

We initiate the variable... can't add on to a variable without it being set first

    while($str = fgets($this->smtpConnect,4096))
    {
        $data .= $str;
        if(substr($str,3,1) == " ") { break; }
    }

We are looping through the response and retrieving the responses

    return $data;
}

We are returning all of the responses that we received from the SMTP server.

Here is the function in it's entirety.

// Function read response
private function readResponse() {
    $data="";
    while($str = fgets($this->smtpConnect,4096))
    {
        $data .= $str;
        if(substr($str,3,1) == " ") { break; }
    }
    return $data;
}

3.6 Sending our commands

Here is when we get bossy. We need a function to send our commands to the SMTP server.

// function send command to server
private function sendCommand($string) {
    fputs($this->smtpConnect,$string.$this->newline);
    return ;
}

We create a private function, and then send our command. Returning nothing since there is nothing to return.

3.7 Creating those Headers

Now we need to create the headers to be used in that message you sent.

private function sendHeaders() {
    $this->sendCommand("Date: ".date("D, j M Y G:i:s")." +0700");
    $this->sendCommand("From: <{$this->from}>");
    $this->sendCommand("Reply-To: <{$this->from}>");
    $this->sendCommand("To: <{$this->to}>");
    $this->sendCommand("Subject: {$this->subject}");
    $this->sendCommand("MIME-Version: 1.0");
    $this->sendCommand("Content-Type: text/html; charset={$this->charset}");
    if ($this->contentTransferEncoding) $this->sendCommand("Content-Transfer-Encoding: {$this->contentTransferEncoding}");
    return ;
}

Here is that private function that creates the headers. And returns nothing since there is nothing to return.

3.8 Destructing the class

Now what we need to do is destruct the class.

function __destruct() {
    if (is_resource($this->smtpConnect)) fclose($this->smtpConnect);
}

The purpose of this function is if in any case that the class is stopped before disconnecting from the SMTP server, we would disconnect it here.

3.9 The class in it's entirety

Here is this class in it's entirety (I'm not attaching it, since this forum has this advanced collapsing PHP code block).

Lets save this page as smtp_mail.php

<?php
class smtp_mail {
    private $smtpServer = 'smtp.gmail.com';
    private $port = '587';
    private $timeout = 30;
    private $username = 'myname@gmail.com';
    private $password = 'mypassword';
    private $username_email = 'myreceivingemail@gmail.com';
    private $newline = "\r\n";
    private $localdomain = 'https://www.mysite.com';
    private $charset = 'windows-1251';
    private $contentTransferEncoding = false;

    // Do not change anything below
    private $smtpConnect = false;
    private $to = false;
    private $to_admin = false;
    private $subject = false;
    private $message = false;
    private $headers = false;
    private $logArray = array(); // Array response message for debug
    private $Error = '';
    private $from = false;

    public function __construct($to, $subject, $message, $to_admin) {
        $this->to_admin = $to_admin;
        $this->to = (($this->to_admin === false) ? $this->username_email : $to );
        $this->from = (($this->to_admin === false) ? $to : $this->username_email );
        $this->subject = &$subject;
        $this->message = &$message;

        // Connect to server
        if(!$this->Connect2Server()) {
            // Display error message
            echo '<pre>'.trim($this->Error).'</pre>'.$this->newline.'<!-- '.$this->newline;
            print_r($this->logArray);
            echo $this->newline.'-->'.$this->newline;
            return false;
        }
        return true;
    }

    private function Connect2Server() {
        // Connect to server
        $this->smtpConnect = fsockopen($this->smtpServer,$this->port,$errno,$error,$this->timeout);
        $this->logArray['CONNECT_RESPONSE'] = $this->readResponse();

        if (!is_resource($this->smtpConnect)) {
            return false;
        }
        $this->logArray['connection'] = "Connection accepted";
        // Hi, server!
        $this->sendCommand("HELLO {$this->localdomain}");
        $this->logArray['HELLO'] = $this->readResponse();
        // Let's know each other
        $this->sendCommand('AUTH LOGIN');
        $this->logArray['AUTH_REQUEST'] = $this->readResponse();
        // My name...
        $this->sendCommand(base64_encode($this->username));
        $this->logArray['REQUEST_USER'] = $this->readResponse();
        // My password..
        $this->sendCommand(base64_encode($this->password));
        $this->logArray['REQUEST_PASSWD'] = $this->readResponse();
        // If error in response auth...
        if (substr($this->logArray['REQUEST_PASSWD'],0,3)!='235') {
            $this->Error .= 'Authorization error! '.$this->logArray['REQUEST_PASSWD'].$this->newline;
            return false;
        }
        // "From" mail...
        $this->sendCommand("MAIL FROM: {$this->from}");
        $this->logArray['MAIL_FROM_RESPONSE'] = $this->readResponse();
        if (substr($this->logArray['MAIL_FROM_RESPONSE'],0,3)!='250') {
            $this->Error .= 'Mistake in sender\'s address! '.$this->logArray['MAIL_FROM_RESPONSE'].$this->newline;
            return false;
        }
        // "To" address
        $this->sendCommand("RCPT TO: {$this->to}");
        $this->logArray['RCPT_TO_RESPONCE'] = $this->readResponse();
        if(substr($this->logArray['RCPT_TO_RESPONCE'],0,3) != '250')
        {
            $this->Error .= 'Mistake in reciepent address! '.$this->logArray['RCPT_TO_RESPONCE'].$this->newline;
        }
        // Send data to server
        $this->sendCommand('DATA');
        $this->logArray['DATA_RESPONSE'] = $this->readResponse();
        // Send mail message
        if (!$this->sendMail()) return false;
        // Good bye server! =)
        $this->sendCommand('QUIT');
        $this->logArray['QUIT_RESPONSE'] = $this->readResponse();
        // Close smtp connect
        fclose($this->smtpConnect);
        return true;
    }

    private function sendMail() {
        $this->sendHeaders();
        $this->sendCommand($this->message);
        $this->sendCommand('.');
        $this->logArray['SEND_DATA_RESPONSE'] = $this->readResponse();
        if(substr($this->logArray['SEND_DATA_RESPONSE'],0,3)!='250') {
            $this->Error .= 'Mistake in sending data! '.$this->logArray['SEND_DATA_RESPONSE'].$this->newline;
            return false;
        }
        return true;
    }

    // Function read response
    private function readResponse() {
        $data="";
        while($str = fgets($this->smtpConnect,4096))
        {
            $data .= $str;
            if(substr($str,3,1) == " ") { break; }
        }
        return $data;
    }

    // function send command to server
    private function sendCommand($string) {
        fputs($this->smtpConnect,$string.$this->newline);
        return ;
    }

    // function send headers
    private function sendHeaders() {
        $this->sendCommand("Date: ".date("D, j M Y G:i:s")." +0700");
        $this->sendCommand("From: <{$this->from}>");
        $this->sendCommand("Reply-To: <{$this->from}>");
        $this->sendCommand("To: <{$this->to}>");
        $this->sendCommand("Subject: {$this->subject}");
        $this->sendCommand("MIME-Version: 1.0");
        $this->sendCommand("Content-Type: text/html; charset={$this->charset}");
        if ($this->contentTransferEncoding) $this->sendCommand("Content-Transfer-Encoding: {$this->contentTransferEncoding}");
        return ;
    }

    function __destruct() {
        if (is_resource($this->smtpConnect)) fclose($this->smtpConnect);
    }
}
?>

4.0 Class Usage

Now we want a simple way to use that SMTP class.

if(new smtp_mail($to, $subject, $message, true))
{
    echo 'Your message has being sent successfully.';
}
else
{
    echo 'There was a problem sending the message';
    // Possibly log this for your reference
}

Simple, right?

5.0 The Form

Now we need the form to use that people are going to use to fill out to send their message.

Lets save this page as contact.html

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
    <head>
        <title>Contact Form</title>
        <style type="text/css">
            #contact_form {
                width: 100%;
            }

            .form_col {
                float: left;
                margin-left: 10px;
            }
        </style>
    </head>
    <body>
        <div id="contact_form">
            <form action="contact.php" method="post">
                <div class="form_col">
                    <p>Name:<br>
                    Email Address:<br>
                    To:<br>
                    Subject:<br>
                    Message:</p>
                </div>
                <div class="form_col">
                    <p><input type="text" name="name" size="30"> Required<br>
                    <input type="text" name="email" size="30"> Required<br>
                    <input type="text" name="to" size="30"> To Administrator <input type="checkbox" name="to2"><br>
                    <input type="text" name="subject" size="30"> Required<br>
                    <textarea name="message" cols="50" rows="10"></textarea><br>
                    <input type="submit" name="submit" value="Submit"> <input type="reset" value="Reset"> The Message is Required</p>
                </div>
            </form>
        </div>
        <p style="clear: both;"></p>
    </body>
</html>

That's just a nice styled form for you to use with this class.

5.1 The Form Processor

Now lets create a PHP page which processes the form above.

Lets save this page as contact.php

<?php
// Checking if the form was really submitted
if(isset($_POST['submit']))
{
    // We need to initiate the error array
    $error = array();

    // Here we are checking if their name was filled in.
    if(empty($_POST['name']))
    {
        // The name field was left empty
        $error[] = "You need to enter a valid name.";
    }

    // Checking if a valid email address was filled in.
    if(!preg_match("/(?:[a-zA-Z0-9_\'\^\&\/\+\-])+(?:\.(?:[a-zA-Z0-9_\'\^\&\/\+\-])+)*@(?:(?:\[?(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))\.){3}(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\]?)|(?:[a-zA-Z0-9-]+\.)+(?:[a-zA-Z]){2,}\.?)/", $_POST['email']))
    {
        // An invalid email address was filled in.
        $error[] = "You need to enter a valid email address.";
    }

    // We need to determine the recipient of the message
    if(isset($_POST['to_admin']))
    {
        // Even if the to field was given a different email address, this would over-ride that address and be sent to admin.
        $to_admin = true;
        $to = false;
    }
    elseif(preg_match("/(?:[a-zA-Z0-9_\'\^\&\/\+\-])+(?:\.(?:[a-zA-Z0-9_\'\^\&\/\+\-])+)*@(?:(?:\[?(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))\.){3}(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\]?)|(?:[a-zA-Z0-9-]+\.)+(?:[a-zA-Z]){2,}\.?)/", $_POST['to']))
    {
        // If the process reaches here, then the message would be sent to the address put in the to field
        $to_admin = false;
        $to = $_POST['to'];
    }
    else
    {
        // There was an error... it's not sent to the admin OR to anyone...
        $error[] = "You need a valid recipient's (to) email address.";
    }

    // Now we need to validate the subject of the message
    if(strlen($_POST['subject']) < 5)
    {
        // The message is under 5 characters.
        $error[] = "The subject needs to be greater then 5 characters";
    }

    // Validating the actuall message
    if(strlen($_POST['message']) < 5)
    {
        $error[] = "The message needs to be greater then 5 characters";
    }

    // Counting the number of errors there was in the form submittion
    if(count($error) > 0)
    {
        // There were errors... we can't send a message with errors in the form submittion.

        // Looping through each error and providing a good list of errors for the user.
        $errors = "<ol>";
        foreach($error as $er)
        {
            $errors .= "<li>{$er}</li>\n";
        }
        $errors .= "</ol>";

        echo $errors;
    }
    else
    {
        // There were no errors, lets submit the actual message
        if(new smtp_mail($to, $_POST['subject'], $_POST['message'], $to_admin))
        {
            echo "The mail was sent successfully.";
        }
        else
        {
            echo "There was a problem sending the message.";
        }
    }
}
?>

5.2 The Magic Function

This is not necessary, but this is what I always use so I'll suggest it here.

I always use the Magic function __autoload() to load classes. This saves me 1 line every time I want to use a class. This way, I don't have to include the PHP file that holds the class... it __autoload()s.

In order for it to work properly, the PHP file needs to be saved the same way that the class is named... so in this case, the class name is smtp_mail and it's saved as smtp_mail.php. So here is that function.

function __autoload($class_name) {
    if(file_exists('includes/' . $class_name . '.php'))
    {
        require_once 'includes/' . $class_name . '.php';
    }
}

What I have this function do is check if that page exist in the includes/ directory... this means, that when I start this class it would look for [/b]includes/smtp_mail.php[/b].

This means that the directory structure should look like the following:

  • includes/smtp_mail.php
  • contact.html
  • contact.php

Another thing that I would recommend doing is having a global page that would be included into every page all the time. Have a look at this tutorial to understand more on what I'm talking here.

In that configuration file, you would put this magic function. If that tip is to come into play here, then the directory structure would change to:

  • includes/smtp_mail.php
  • includes/config.php
  • contact.html
  • contact.php

So, if you look at the line where it would include the smtp_mail class (in contact.php):

        if(new smtp_mail($to, $_POST['subject'], $_POST['message'], $to_admin))

You see that it's instantiate a new object 'smtp_mail' without me including 'smtp_mail.php'. When the PHP parser gets to this line it would attempt to include 'includes/smtp_mail.php' to be able to instantiate the object. This is the beauty of magic functions.

If you don't want to use the magic function, simply include 'smtp_mail.php' into contact.php. Remember to include 'smtp_mail.php' right before the line that uses that function. (The PHP code block right above this).

include_once 'includes/smtp_mail.php';

6.0 Conclusion

It is (in most cases) invaluable to have a way to send email messages to your users, be it for newsletters or simply updates or whatever you need to send a message for, you now got a fairly advanced way of sending messages using an SMTP server.

This page was published on It was last revised on

Contributing Authors

0

7 Comments

  • Votes
  • Oldest
  • Latest
Commented
Updated

Must say this article is wonderful - sadly I am only a beginner yet even I can see that if I study it much benefit will come to me - so THANK YOU for your efforts and posting it for us all.

add a comment
0
SP
106 4
Commented
Updated

I don't think you quite understand the purpose of constructors and destructors in this tutorial. Constructors are called whenever a new object is created; their purpose is to initialize the data members and set up the object to be used by the caller. Never should you be returning anything from a constructor; the nature of the function is to return the object being created.

The other problem is that you're using object creation as a method call, when really you should be properly constructing the object and then allowing the caller to take action with it. Invoking the mail() functionality at instantiation time isn't right; I should be able to create an smtp_mail object and then choose when the mail is actually sent.

The purpose of a destructor isn't to take action "in case the class is stopped"; classes cannot "stop" or "go" (threads and processes can, but that's a different topic). The purpose of the destructor is to clean up after the object when it is either directly deleted or goes out of scope (or in the case of managed languages, when it gets garbage collected).

I also see bits of HTML and calls to various output functions littered throughout the class, which tightly couples the class to whatever application the user plans to use it in. It would be better to allow the user to read/update results via accessors and mutators such that the application using this class can output the data as it sees fit.

For this class to be useful in an application, it should conform to an interface that would allow me to use it like this:

<?php

$myMailer = new SmtpMailer(new SmtpMailerCredentials(...));

// a class such as SmtpMailerCredentials could help
// organize and decouple the non-essential aspects of
// the mail from the mailer class

// don't assume only one recipient
$myMailer->addToAddress("someone@domain.com");
$myMailer->addToAddress("someoneelse@domain.com");

// ...and don't assume everyone will be on the "to" line!
$myMailer->addCcAddress("athirdperson@domain.com");

$myMailer->setSubject("This is a test message");
$myMailer->setBody("This is the body of the message.");

// do some other stuff. perhaps add this mailer 
// object to a queue of mail to be sent, or do
// whatever else I need to do before the email goes out

// now I choose exactly when to send the mail
$mailer->send();

?<
add a comment
0
BO
443 9
Commented
Updated

Thanks for the review Spork. I kind of remember creating the class from a jumble of code written as one function (I might have mistaken this class for another). I just found it in my class depository directory on my computer and since it works perfectly for me (I can only make beginner classes work 🤣 I'm not so advanced 😟 ) so I decided to make a walk-through tutorial.

I'll fix it up soon though to comply with your suggested interface and changing some bits of code to fix the problems that you posted. Thanks for the heads up.

add a comment
0
Commented
Updated

Very nice tutorial, can i send attachments this way and how can i block certain extensions? Thanks

add a comment
0
Commented
Updated

Reviewing this article from Bogey still makes me realize how lucky we are to have Members like Bogey and Spork and others (nameless) who care enough about others to write such a WELL - CONSTRUCTED and clear article.

If you have the time might you also consider - including - how to use the above code and INSERT - a capability to run this as

  1. a CRON job
  2. to send 1 email every 10 seconds
    and/or (which ever is the lesser - important as server needs change from one Host Co to another)
  3. a maximum of ... emails per hour

REASON - there are many, many users who are continually with problems around these 3 items and as yet I have not seen such a CLEAR EXPLANATION of a way to get around the problems as many complain their cron stops (at say 500 emails in the first hour) when say their job is to send 5,000 emails - their plight is how to re-start without doing/sending the first 500 emails a second time.

Would appreciate your ideas on how to fix these sorts of issues and thank you so much for the explanations of EACH segment - you are a great teacher and example for us "newbies"

add a comment
0