A reader recently asked how I handle the subscribe/unsubscribe mechanism for the thickbook newsletter, and how that ties in with actually sending a message to all the recipients of the mailing list. It's a good question, and an easy enough thing to do, but first let me stress that this isn't any tricky thing I made up because I'm super cool -- if anything, I use this method only because I'm lazy. See, there's a ton of mailing list software out there that one can install on a system, and there are other, more cohesive sets of scripts that you can get to do the same thing. But, like I said, I was lazy one day and didn't want to download and install anything, so I made a couple of really simple pages that did what I needed them to do. Hopefully, someone will learn something from them.
First, there's the subscribe/unsubscribe script, and all it does is add or delete records from a database table. Call it "manage.phtml" or something like that. Required on the backend is a database of some sort, on which a "subscribers" table can be created. Majority rules in a democracy, so I'll use MySQL as the example database. You can use whatever database you normally use, just substitute the correct database connectivity functions from the PHP manual.
In my subscribers table, I use two fields: email_addr and date_added. You can have as many fields as you want, or can delete the date_added field. In this example, I'm just going to show you what I do, and you can modify as appropriate. In my subscribers table, the email_addr field is the unique field, meaning that you can't add another record that has exactly the same e-mail address. This alleviates duplicate subscriptions, and also makes it a simple and reliable method for deleting records when users want to unsubscribe.
So, let's create the subscribe/unsubscribe form (manage.phtml or whatever you want to call it). I use the same file for both subscribing and unsubscribing, as well as the form action itself, so this may get a little complicated. I'll go from top to bottom, then put all the pieces together in the form of a long chunk of code. Hang in there, though -- it's not all that painful.
At the top of the script, open the database connection and prepare the date stamp. Getting this out of the way at the beginning always alleviates a little stress for me.
// connect to db
$db = mysql_connect("servername", "username", "password")
or die ("Couldn't connect.");
mysql_select_db("yourDB", $db) or die ("Couldn't select db.");
// get a date stamp
$add_date = date("Y-m-d");
The next step is to figure out just which action needs to be performed, since this script is used for essentially four different functions: show the form, or subscribe, or unsubscribe, or print a response to an action. I use a variable called "op" to determine which OPeration (get it? "op"?) to perform. The value of this variable is set in a hidden form field.
The value of $op that we're looking for is "ds". This isn't some complicated programming abbreviation -- I made it up, and it stands for "do something". So, the first thing the script should do is look for the value of $op that equals "ds". This value will ONLY have been sent if the form has been submitted already. So, if the value of $op is not "ds", then the user hasn't seen the form and thus it should be shown:
You'll notice that I've put the text inside a variable called $text_block. By putting the text in a variable, all I then have to do later in the script is echo the value of the variable $text_block, inside the master HTML template. It's a personal choice, and you can echo your text whenever or however you like.
The action of this form is $PHP_SELF, which means, as you can imagine, that it will reload itself as the submit button is pressed. Then, you'll see that this form has three fields: one hidden field, giving a value of "ds" to $op, one text field, called "email", where the user will place his or her email address, and finally a radio button set called "action", from which the user will decide which action (subscribe or unsubscribe) should be performed.
After the form is submitted, $op will equal "ds", and the value of $action will contain either "sub" or "unsub". So, we continue the if... statement from above, since upon submission, it will be skipped ($op == "ds"). The next else if... statement is executed if the value of $op is "ds" AND the value of $action is "sub" (subscribe). This code checks that the e-mail doesn't already reside in the subscribers table, then inserts it if it does not and prints a response, regardless.
else if (($op == "ds") && ($action == "sub")) {
// check they're not already subscribed,
// then subscribe them or return message
$check = "select email_addr from subscribers
where email_addr = \"$email\"";
$check_result = mysql_query($check)
or die("Can't execute check e-mail address.");
$check_num = mysql_num_rows($check_result);
if ($check_num == 0) {
// if $check_num is 0, then no match was found,
// and the user should be subscribed
$sql = "insert into subscribers
values(\"$email\", \"$add_date\")";
@mysql_query($sql) or die ("Couldn't insert email.");
$text_block = "
<P>Thanks for signing up!</p>
";
} else {
// if $check_num is not 0, then the user is
// already subscribed, and you should let
// them know it.
One more step: what to do if the value of $action is "unsub" (unsubscribe) instead of "sub". Well, it's just as simple as above, so extend the else if... statement for one more block, which will check that the e-mail is in the subscribers table before removing it, then removes it and prints a response, regardless.
else if (($op == "ds") && ($action == "unsub")) {
// check they're already subscribed,
// then unsubscribe them or return message
$check = "select email_addr from subscribers
where email_addr = \"$email\"";
$check_result = mysql_query($check)
or die("Can't execute check e-mail address.");
$check_num = mysql_num_rows($check_result);
if ($check_num == 0) {
// if $check_num is 0, then no match was found,
// and the user cannot be unsubscribed
$text_block = "
<P>Couldn't find your e-mail on the list!</p>
<P>You haven't been unsubscribed, because the
e-mail you entered is not in the database.";
} else {
// if $check_num is not 0, then the user is
// on the list, so can be unsubscribed.
$sql = "delete from subscribers
where email_addr = \"$email\"";
@mysql_query($sql) or die ("Couldn't delete email.");
// check they're already subscribed,
// then unsubscribe them or return message
$check = "select email_addr from subscribers
where email_addr = \"$email\"";
$check_result = mysql_query($check)
or die("Can't execute check e-mail address.");
$check_num = mysql_num_rows($check_result);
if ($check_num == 0) {
// if $check_num is 0, then no match was found,
// and the user cannot be unsubscribed
$text_block = "
<P>Couldn't find your e-mail on the list!</p>
<P>You haven't been unsubscribed, because the
e-mail you entered is not in the database.";
} else {
// if $check_num is not 0, then the user is
// on the list, so can be unsubscribed.
$sql = "delete from subscribers
where email_addr = \"$email\"";
@mysql_query($sql) or die ("Couldn't delete email.");
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<HTML>
<HEAD>
<TITLE>Subscribe/Unsubscribe</TITLE>
</HEAD>
<BODY>
<h1>Subscribe/Unsubscribe</h1>
<?php echo "$text_block"; ?>
</BODY>
</HTML>
Now that you have the subscribe/unsubscribe mechanism in place, I'll show you how I send a newsletter out, using just a simple little form and a mail script. ("while" loops are your friends!). First, just the simple form...call it "send_mail.html". The form action should be something like "do_send_mail.phtml", and the only fields I use are a text field for "subject" and a textarea for "newsletter". You can use as many form fields as you'd like, as long as you modify the form and script appropriately.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<HTML>
<HEAD>
<TITLE>Send a Newsletter</TITLE>
</HEAD>
<BODY>
<h1>Send a Newsletter</h1>
<FORM ACTION="do_send_mail.phtml" METHOD="post">
<P><strong>Give it a subject:</strong><br>
<input type="text" name="subject" size=30></p>
The last little bit is the action of the form, the script called "do_send_mail.phtml". This script first looks for a value of $subject and $newsletter, and redirects back to the form if either of those values are empty:
Now for the loop that sends the mail. First, use the mysql_fetch_array function (or similar function for your database type) to get each record as an array. It makes more sense if there's more than one field that you're grabbing, but I use it anyway because it's fast. The following statement steps through the result set and sends the e-mail using the mail() function, to each e-mail address on the list:
The value of $subject and $newsletter are what was entered in the previous form. Add an echo statement at the end of the script, so you know that it's finished, and that's all there is to it! The entire "do_send_mail.phtml" script looks something like this: