Tutorials, PHP & MySQL

Part 1 (Newsletter Tutorial Part 1 The Signup) looked at setting up a database table to store email address and names and creating a signup for to collect the data.

Part 2 is going to cover sending out a newsletter in with a HTML and plain text version so everyone can read it no matter what mail client they are using, and giving the user the option to unsubscribe if they wish to.

This tutorial is concentrating in sending out emails as such there's no login area covered, but it's recommended you should have your script to send emails stored somewhere secure so only people who should be able to access it can do.

Lets start with the form, all we need is a field for the subject and a field for the message, you can put HTML into the message as we will filter it out for the text email later

<form action="" method="post">
<p><label>Subject:</label><input type="text" name="subject" size="50" value=""/></p>
<p><label>Message:</label><textarea name="bodymsg" cols="80" rows="10"></textarea></p>
<p><label>&nbsp;</label><input type="submit" name="submit" class="button" value="Send"/></p>
</form>

Now we know what the form looks like lets process the form, as always we first check to see if the form has been submitted then collect the subject and message from the form.

I'm included some very basic validation that check the length of the subject and message, if no errors have been generated then carry on.

<pre lang="php">

if(isset($_POST['submit'])){

//collect data from form and remove any tags and make safe for database entry
$subject = $_POST['subject'];
$bodymsg = $_POST['bodymsg'];

//validation
if (strlen($subject) < 2) {
    $error[] = 'Sorry the subject is too short.';
}

if (strlen($bodymsg) < 2) {
    $error[] = 'Sorry the content is too short.';
}

// if no errors continue
if(!isset($error)){

Next get all entries from the newsletter table and loop through them find out how many results they are (mysql_num_rows) and add the records to an object (mysql_fetch_object).

//Select user from database
$q = mysql_query("SELECT * FROM newsletter ")or die(mysql_error());
$n = mysql_num_rows($q);
while($r = mysql_fetch_object($q)){

Next we set boundaries that will be used to send out an HTML and plain text version, make sure to change [email protected] to an address you want to send emails from.

//create a boundary string. It must be unique so we use the MD5 algorithm to generate a random hash
$random_hash = md5(date('r', time()));
//define the headers we want passed. Note that they are separated with rn
$headers = "From: [email protected]: [email protected]";
//add boundary string and mime type specification
$headers .= "rnContent-Type: multipart/alternative; boundary="PHP-alt-".$random_hash.""";

Next we turn on output buffering and set out the plain text email, we remove any html using a function called strip_tags and give the user the option to subscribe by giving them a link to an subscribe page, make sure you update the url to match your own. In the subscribe url we pass 2 parameters uid is the id of the user and e is the users email address.

<In the Content-Type: text/html; charset="iso-8859-1" section to remove any unwanted slashes with the use of the function stripslashes. Then we add the email content to a variable called $body.

//define the body of the message.
ob_start(); //Turn on output buffering
?>
--PHP-alt-<?php echo $random_hash; ?>
Content-Type: text/plain; charset="iso-8859-1"
Content-Transfer-Encoding: 7bit

<?php
echo strip_tags($bodymsg);
echo "Unsubscribehttp://www.theonepointwebdesign.co.uk/web-design-and-development-blog/demos/newsletter/unsubscribe.php?uid=$r->id&e=$r->email";
?>

--PHP-alt-<?php echo $random_hash; ?>
Content-Type: text/html; charset="iso-8859-1"
Content-Transfer-Encoding: 7bit

<?php
echo stripslashes($bodymsg);
echo "<p><a href="http://www.theonepointwebdesign.co.uk/web-design-and-development-blog/demos/newsletter/unsubscribe.php?uid=$r->id&e=$r->email">Unsubscribe</a></p>";
?>

--PHP-alt-<?php echo $random_hash; ?>--
<?
//copy current buffer contents into $message variable and delete current output buffer
$body = ob_get_clean();

Now we send out the emails using the mail function passing it the email address, subject, body and headers. the close the while loop and print out how many emails have been sent.

//send the email
$mail_sent = mail( $r->email, $subject, $body, $headers);
}
echo "emails sent: $n";

Next close the 2 if statements and show any errors if they are any.

}// close if error
}//close if submit


//show any errors
if (!empty($error))
{
        $i = 0;
        while ($i < count($error)){
        echo "<div class="msg-error">".$error[$i]."</div>";
        $i ++;}
}// close if empty errors

That's it for sending out emails here's the full script:

<?php

$error = array();

if(isset($_POST['submit'])){

//collect data from form and remove any tags and make safe for database entry
$subject = $_POST['subject'];
$bodymsg = $_POST['bodymsg'];

//validation
if (strlen($subject) < 2) {
    $error[] = 'Sorry the subject is too short.';
}

if (strlen($bodymsg) < 2) {
    $error[] = 'Sorry the content is too short.';
}

// if no errors continue
if(!isset($error)){

//Select user from database
$q = mysql_query("SELECT * FROM newsletter ")or die(mysql_error());
$n = mysql_num_rows($q);
while($r = mysql_fetch_object($q)){

//create a boundary string. It must be unique so we use the MD5 algorithm to generate a random hash
$random_hash = md5(date('r', time()));
//define the headers we want passed. Note that they are separated with rn
$headers = "From: [email protected]: [email protected]";
//add boundary string and mime type specification
$headers .= "rnContent-Type: multipart/alternative; boundary="PHP-alt-".$random_hash.""";
//define the body of the message.
ob_start(); //Turn on output buffering
?>
--PHP-alt-<?php echo $random_hash; ?>
Content-Type: text/plain; charset="iso-8859-1"
Content-Transfer-Encoding: 7bit

<?php
echo strip_tags($bodymsg);
echo "Unsubscribe http://www.theonepointwebdesign.co.uk/web-design-and-development-blog/demos/newsletter/unsubscribe.php?uid=$r->id&e=$r->email";
?>

--PHP-alt-<?php echo $random_hash; ?>
Content-Type: text/html; charset="iso-8859-1"
Content-Transfer-Encoding: 7bit

<?php
echo stripslashes($bodymsg);
echo "<p><a href="http://www.theonepointwebdesign.co.uk/web-design-and-development-blog/demos/newsletter/unsubscribe.php?uid=$r->id&e=$r->email">Unsubscribe</a></p>";
?>

--PHP-alt-<?php echo $random_hash; ?>--
<?
//copy current buffer contents into $message variable and delete current output buffer
$body = ob_get_clean();
//send the email
$mail_sent = mail( $r->email, $subject, $body, $headers);
}

echo "emails sent: $n";

}// close if error
}//close if submit


//show any errors
if (!empty($error))
{
        $i = 0;
        while ($i < count($error)){
        echo "<div class="msg-error">".$error[$i]."</div>";
        $i ++;}
}// close if empty errors

?>

<form action="" method="post">
<p><label>Subject:</label><input type="text" name="subject" size="50" value=""/></p>
<p><label>Message:</label><textarea name="bodymsg" cols="80" rows="10"></textarea></p>
<p><label>&nbsp;</label><input type="submit" name="submit" class="button" value="Send"/></p>
</form>
</pre>

<p>One Last area to cover and that's letting a user unsubscribe, create another page called unsubscribe.php in the same folder as send mail script and put the following script in, The script looks for the id and email address from an unsubscribe link then checks that against the database if there's a match then the user is deleted from the table.</p>

<pre lang="php">
<?php
//collect data from form and remove any tags and make safe for database entry
$id = strip_tags(mysql_real_escape_string($_GET['uid']));
$email = strip_tags(mysql_real_escape_string($_GET['e']));

//Select user from database
$q = mysql_query("SELECT id FROM newsletter WHERE id='$id' AND email='$email' ")or die(mysql_error());
$n = mysql_num_rows($q);
$r = mysql_fetch_object($q);

if($n == 1){

    //Delete user from newsletter table
    mysql_query("DELETE FROM newsletter WHERE id = '$r->id' ")or die(mysql_error());
    //inform user
    echo "<p>You've have successfully unsubscribed</p>";

} else {
    echo "<p>Sorry the link you've provided is invalid, or you have already unsubscribed.</p>";
}
?>

You should now have a fully working newsletter with the ability for people to sign up/unsubsribe and for you to send out emails.