In this tutorial I will be showing you how to build a PHP mailing list web app. In this web app, users will be able to sign up. Once they do they will be added to the database and an unsubscribe hash will be generated. Admins will be able to send emails and add [unsubscribe] within the email in order to show a way for the subscribers to remove themselves. Javascript will also be added to the sign up process to make it nicer for the users.
Live Demo
Username: alex
Password: password
Download
We are going to need two databases for this system. One for the admins and one for the subscribers. Here is the SQL code needed for the tables.
CREATE TABLE IF NOT EXISTS `subscribers` ( `id` int(30) NOT NULL auto_increment, `email` varchar(60) NOT NULL, `unsubscribeLink` varchar(35) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1 ; CREATE TABLE IF NOT EXISTS `users` ( `id` int(30) NOT NULL auto_increment, `username` varchar(50) NOT NULL, `password` varchar(40) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1 ; INSERT INTO `users` (`id`, `username`, `password`) VALUES (1, 'alex', '5f4dcc3b5aa765d61d8327deb882cf99');
After running that code you will have two tables one for subscribers that has an ID, email address and a unsubscribe fields (with ID as the primary key and set to auto increment). The other table for the users has an ID, username and password field (again with the ID as the primary key and set to auto increment). After that we insert into the ‘users’ table the values “alex” for the username and an MD5 hash of the word password. You can change these to what ever you want just make sure that the password is MD5 hashed or you will not be able to login later.
Create a directory “functions” and within that two files “function.php” and “config.php”. We will add information to the config file connecting to the database. This is what you need:
<?php
$dbhost = 'localhost'; // database host
$dbuser = 'USERNAME'; // database username
$dbpass = 'PASSWORD'; // database password
$db = 'DATABASE'; // the database
$conn = mysql_connect($dbhost, $dbuser, $dbpass) or die("Could not connect to the database"); // creat a connection or die
mysql_select_db($db) or die("I couldn't find the database"); // select the database or die
define("BASE_URL", "http://url-to-file/mail_list/"); // the URL to the file
define("REPLY_EMAIL", "noreply@yourdomain.com"); // the email address we want our mailing list to be from
If you load that page and don’t see anything you have successfully connected to your database. We now need to fill in the ‘functions.php’ file. Within ‘functions.php’ add
<?php
session_start(); // start session
require_once("config.php"); // require our config.php file
function reply($type, $message){ // function to reply to the javascript
$replying = array("error"=>"{$type}", "message"=>"$message");
echo(json_encode($replying)); // json encode the responce
}
function add_email_to_database($email){ // adding the email address to the datbase
// 1. We need to make sure its not already in
// 2. We need to make a unsubscribe hash
// 3. We need to add the user
$email = mysql_real_escape_string($email); // make sure it OK
$sql = "SELECT * FROM `subscribers` WHERE email = '{$email}' LIMIT 1"; // select all subsribers that has the email and only return (if there is) one
$qry = mysql_query($sql); // run the query
if( mysql_num_rows($qry) != 0){ // if that user was found they are not new so return false
return false;
}else{ // user was not found
$unsubLink = ""; // create empty varible
$unsubLink .= rand(1111, 99999); // generate random number and add it to the empty varible
$unsubLink .= rand(1111, 99999);
$unsubLink .= $email; // attach the email address
$unsubLink = md5($unsubLink); // md5 it
$unsubLink .= rand(1111, 99999); // then attack a random number
// insert the values
$sql = "
INSERT INTO `subscribers` (
`id` ,
`email` ,
`unsubscribeLink`
)
VALUES (
NULL , '$email', '$unsubLink'
);
";
mysql_query($sql); // run the query
return true; // return true as we added the user
}
}
function loggedIn(){ // check if we are logged in
if($_SESSION['loggedIn'] != 1){ // if we are not
return false;
}else{ // if we are
return true;
}
}
[/sourceode]</pre>
That is all we need for both of these files.
<h2>Sigh up page</h2>
This page will allow the users to sign up, it will added them to the database after some validation all happening with some AJAX. Create an index.php page and add:
[sourcecode language="php"]
<?php
session_start(); // start the session
$message = $_SESSION['message']; // check if we have a message to display
$_SESSION['message'] = ""; // clear the message for next time
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Mailing List Web App</title>
<!-- Start of CSS -->
<link rel="stylesheet" type="text/css" href="css/reset.css" />
<link rel="stylesheet" type="text/css" href="css/main.css" />
<!-- Start of JS -->
<script type="text/javascript" src="js/jquery.js"></script>
<script type="text/javascript" src="js/scripts.js"></script>
</head>
<div id="wrap">
<h1>Join my list!</h1>
<!-- If we have a message, display it -->
<?php if(strlen($message) > 0){ ?><h2 class="stat"><?php echo '<br />'. $message ?></h2><?php } ?>
<br />
<form action="./add.php" method="POST" id="subscribe">
<label class="label" for="email">Email</label>
<input type="text" value="you@you.com" size="20" id="email" name="email" />
<input type="submit" id="submit" value="Sign Up!" />
</form>
<p class="message"></p>
<br /><br />
<a class="small" href="admin">(admin)</a>
</div>
</body>
</html
Now create a CSS directory and add a reset CSS file (you can find them online, though this is optional) and a file main.css. Then add this styling:
@charset "UTF-8";
/* CSS Document */
/* UTULITIES */
.clear{clear: both;}
.push{height: 30px;}
/* END */
/* ORDER PAGE CORRECTLY */
*{margin: 0; padding: 0;}
html{overflow-y: scroll;position: relative;}
body{background-color: #e1e1e1; font-family: "Lucida Grande", Verdana, Arial, sans-serif; width: 100%; height: 100%;}
/* END */
h1{
font-size: 30px;
font-weight: bold;
margin-bottom: 20px;
color: #D0D3D3;
padding-bottom: 8px;
border-bottom: 1px solid #B4B6B6;
}
#wrap{
background-color: #888888;
width: 500px;
margin: 0 auto;
padding: 20px;
}
form{text-align: center;}
.label{color: #C3C5C5;font-size: 20px;}
#email, #password, #username{margin-top: -2px;font-size: 18px;background: none;border: none;border-bottom: 1px dotted black;color: #DBDEDE;}
.message{color:white;padding-top:20px;text-align:center;}
#login{padding-top: 10px;}
#create{text-align: left;}
.input{
font-family: "Lucida Grande", Verdana, Arial, sans-serif;
background:none repeat scroll 0 0 #E3E5E5;
border:1px solid #9A9C9C;
display: block;
font-size:16px;
padding:5px;
color: #3F4040;
}
.input:hover, .input:focus{background: #EAECEC;border: 1px solid #575858;}
.note{color:white;font-size:13px;}
.log{text-decoration: none; color: white;}
.small{text-decoration: none; color: white;font-size: 15px;}
.small:hover{color: black;}
.stat{text-align: center; color: white;}
This javascript file will listen for a submit on the form then post the data to our adder php file using jQuery/AJAX.
$(function() {
function pulse(item){ // an animation to plus an item
$(item).animate({"opacity": 0.5}, 200)
.animate({"opacity": 1}, 200)
.animate({"opacity": 0.5}, 200)
.animate({"opacity": 1}, 200)
.animate({"opacity": 0.5}, 200)
.animate({"opacity": 1}, 200)
.animate({"opacity": 0.5}, 200)
.animate({"opacity": 1}, 200)
.animate({"opacity": 0.5}, 200)
.animate({"opacity": 1}, 200)
.animate({"opacity": 0.5}, 200)
.animate({"opacity": 1}, 500);
}
$('#submit').removeAttr('disabled'); // when we load the page make sure this button is OK
$('.message').css({"display": "none"}); // hide the message class
var emailsVal = $('#email').val(); // get the current value of #email
$("#email").focus(function(){ // when the input is clicked
if($(this).val() == emailsVal){ // if the value is the defult value
$(this).val(''); // clear the box
}
});
$('#subscribe').submit(function(e){ // when clicked
$('#submit').animate({'opacity': '0.4'}).attr({'disabled': 'disabled'}); // fade out/deactivet submit button
e.preventDefault(); // prevent defult
$.ajax({ //ajax
type: 'post', // post the data
dataType: 'json', // data type
url: 'add.php', // url of the file to post to
data: 'email=' + $('#email').val(), // data to post
success: function(e){ // on success
if(e.error == true){ // if we set an error
pulse('#email'); // pule the email box
$('.message').html(e.message).slideDown(); // display the message
$('#submit').animate({'opacity': '1'}, function(){ // fade back in the submit box
$(this).removeAttr('disabled'); // remove the disabled attr so its clickable
});
}else{ // if we set didn't set an error
$('#subscribe').slideUp(); // slide up the subscribe box
$('.message').html(e.message).slideDown(); // slide down the message
}
}
});
$(this).ajaxError(function(){
// alert("THERE WAS AN AJAX ERROR, SORRY ABOUT THAT"); // optional, to say if there was a AJAX error
});
return false; // return false (stop form from posting)
}); // end of AJAX
});
Create a file “add.php” where the javascript will post to. Within we will need to validate and then add the user. Also return a JSON encoded response for the awaiting JS script. This is the needed code:
<?php
require_once("functions/functions.php"); // include the functions and the config file
$email = $_POST['email']; // get the email
if (!preg_match('/^[a-z0-9]+([_\.-][a-z0-9]+)*@([a-z0-9]+([.-][a-z0-9]+)*)+\.[a-z]{2,}$/i', $email)) { // make sure it valid
$error = "Email not valid"; // set a message
reply(1, $error); // set an error
die(); // die and stop running the script
}
if($email == "you@you.com"){ // if its you@you the user just clicked submit and although its valid it won't be a users email
$error = "Thats not your email!";
reply(1, $error);
die();
}
if( add_email_to_database($email) ){ // if we added the user
reply(0, "Thanks! You are now in the know."); // set no error
}else{
reply(1, "That email is already in the know."); // else, the user was found alreay
};
That is all that we need to allow the user to subscribe! Now create a directory “admin” and add these files “index.php”, “login.php”, “logout.php” and “poster.php”. In the index file we will post to a login form. I am going to build the login/out script first as I know what I will be needing.
Open the login.php file and add
<?php
require_once("../functions/functions.php");
// get/clean values
$username = mysql_real_escape_string(trim($_POST['username']));
$password = mysql_real_escape_string(trim($_POST['password']));
// something was entered
if(strlen($username) == 0 || strlen($password) == 0){ // if no username of password was entered
$_SESSION['message'] = "Please enter a username and a password"; // set a message
header("Location: ". BASE_URL ."/admin"); // direct to the admin page
die(); // die/stop script
}else{
$password = md5($password); // hash the password
}
$sql = "
SELECT * FROM users WHERE username = '{$username}' AND password = '{$password}' LIMIT 1;
"; // search for users with that username/password
$qr = mysql_query($sql); // run query
if( mysql_num_rows($qr) == 1 ){ // if the user was found
$user = mysql_fetch_assoc($qr); // get values
$_SESSION['loggedIn'] = 1; // set logged in session
$_SESSION['username'] = $user['username']; // you may want their username
$_SESSION['time'] = $_SERVER['REQUEST_TIME']; // incase you want to time out a user
$_SESSION['message'] = "You have been logged in"; // set message
header("Location: ". BASE_URL ."/admin"); // redirect the user
die();
}else{
$_SESSION['message'] = "Didn't find a username and password with that information.";
header("Location: ". BASE_URL ."/admin");
die();
}
Now open logout.php and add this small bit of simple code to log the user out:
<?php
require_once('../functions/functions.php');
session_destroy(); // destroy all information
session_start(); // start a new session just for the message
$_SESSION['message'] = "You have been logged out"; // say we have been loggged out
header("Location: " .BASE_URL."/admin"); // relocate to the admin page
That is all we need to logout users.
Open the index.php file where we will add code to check if we are logged in, if we are we will show a form to email people, if not, we will show a login form submitting the the login.php file we made above.
<?php
require_once('../functions/functions.php');
$loggedIn = loggedIn(); // run login function
// checking for message/sessions content
if( isset($_SESSION['message']) ){ // if we have a message
$message = $_SESSION['message']; // set a local varible
$_SESSION['message'] = ""; // clear the session
}
if( isset($_SESSION['subject']) ){ // if we have a recovered subject
$subject = $_SESSION['subject'];
}else{
$subject = "";
}
if( isset($_SESSION['messageArea']) ){ // if we have a recovered message
$messageArea = $_SESSION['messageArea'];
}else{
$messageArea = "";
}
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Mailing List Web App || ADMIN</title>
<!-- Start of CSS -->
<link rel="stylesheet" type="text/css" href="../css/reset.css" />
<link rel="stylesheet" type="text/css" href="../css/main.css" />
</head>
<div id="wrap">
<?php if(!$loggedIn){ //user is not logged in ?>
<h1>Please, login</h1>
<?php if($message) echo "<h3 class='message'>".$message."</h3>"; ?>
<form action="login.php" method="POST" id="login">
<label class="lable" for="username">Username</label>
<input type="text" value="alex" size="20" id="username" name="username" />
<br /><br />
<label class="lable" for="password">Password</label>
<input type="password" value="" size="20" id="password" name="password" />
<br /><br />
<input type="submit" id="submit" value="Log me in!" />
</form>
<p class="message"></p>
<?php }else{ // user is logged in ?>
<h1>Send A Message</h1>
<?php if($message) echo "<h3 class='message'>".$message."</h3>"; // display any messages ?>
<form action="poster.php" method="POST" id="create">
<label for="subject" class="label">Subject</label><br /><br />
<input class="input" name="subject" id="subject" type="text" value="<?php echo $subject; // echo the varible ?>" />
<br />
<label for="messageArea" class="label">Message</label><br /><br />
<textarea class="input" name="messageArea" id="messageArea" rows="15" cols="46" wrap="wrap"><?php echo $messageArea; ?></textarea>
<br />
<input type="submit" value="Send message" /><br />
<small class="note">Note: Add [unsubscribe] in the email to add an unsubscribe link.</small>
</form>
<br /><br />
<a class="log" href="<?php echo BASE_URL ?>/admin/logout.php">Logout</a>
<?php } ?>
</div>
</body>
</html>
This will now create a nice way to login, and post emails. We just need the scrip to send all the emails. Open poster.php and we will make it.
<?php
require_once('../functions/functions.php');
if($_SESSION['loggedIn'] != 1){
// if the user is not logged in, redirect them and add the message to
// tell them they must be logged in
// helps with unwanted people running your script by posting to it.
$_SESSION['message'] = "You must be logged in.";
header("Location: ". BASE_URL ."/admin");
die();
}
$message = $_POST['messageArea'];
$subject = $_POST['subject'];
if(strlen($message) == 0 || strlen($subject) == 0){
// if no information was added in either fields, save what was intered in a session and redirect them
$_SESSION['subject'] = $subject;
$_SESSION['messageArea'] = $message;
$_SESSION['message'] = "Please fill in both the subject and the message.";
header("Location: " .BASE_URL."/admin");
die();
}
// grab all the subscribers
$sql = "
SELECT * FROM subscribers;
";
$qr = mysql_query($sql);
// if we don't have any
if(mysql_num_rows($qr) == 0){
$_SESSION['message'] = "You currently have no subscribers";
header("Location: " .BASE_URL."/admin");
die();
}
// go through all the subscribers
while( $user = mysql_fetch_array($qr)){
// set a message
$_SESSION['message'] = "Your emails are being sent...";
// redirect the user (no point in them waiting for all the messages to send...)
header("Location: " .BASE_URL."/admin");
$newMessage = ""; // set a clear varible
// search for the [unsubscribe] tag and replace it with a URL for the user to unsubscribe
$newMessage = str_replace(
"[unsubscribe]",
BASE_URL."/unsubscribe/".$user['unsubscribeLink']."&email=".$user['email'],
$message
);
// replace all special characters
$newMessage = htmlspecialchars($newMessage);
// replace new lines with break tags
$newMessage = str_replace( "\r\n",
"<br />",
$newMessage
);
// content type
$headers = 'MIME-Version: 1.0' . "\r\n";
$headers .= 'Content-type: text/html; charset=iso-8859-1' . "\r\n";
$headers .= "From: ".REPLY_EMAIL."\r\n"; // who the reply is to
mail($user['email'], $subject, $newMessage, $headers); // send the email to the user
}
Only one small thing left to do… Build the unsubscribe page which is being sent in the email. For this we need a directory called “unsubscribe” and inside that two files. A .htaccess file to make the URL slightly cleaner and the index.php file.
Open the .htaccess and add
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?hash=$1 [L]
This will make the first variable the hash on the index page. Open the index page and this final bit of code:
<?php
require_once('../functions/functions.php');
$hash = mysql_real_escape_string($_GET['hash']); // get the hash, you don't really need to make sure its clean unless you want to add this to a diffrent database table etc.
$email = mysql_real_escape_string($_GET['email']); // get the email
if(strlen($hash) < 1 || strlen($email) < 1 ){ // make sure they are set
$_SESSION['message'] = "The code is not valid - please contact support";
header("Location: ".BASE_URL );
die();
}
// make sure email is avlid
if (!preg_match('/^[a-z0-9]+([_\.-][a-z0-9]+)*@([a-z0-9]+([.-][a-z0-9]+)*)+\.[a-z]{2,}$/i', $email)) {
$_SESSION['message'] = "The code is not valid - please contact support";
header("Location: ".BASE_URL );
die();
}
$sql = "
SELECT * FROM subscribers WHERE email = '$email' AND unsubscribeLink = '$hash' LIMIT 1;
"; // search for that user
$qr = mysql_query($sql); // run
$rows = mysql_num_rows($qr); // get the number or rows with that information
if($rows == 1){ // if it was found delete it
$sql = "DELETE FROM `subscribers` WHERE `email` = '$email' AND `unsubscribeLink` = '$hash' LIMIT 1";
mysql_query($sql);
$_SESSION['message'] = "You have been unsubscribed successfully";
header("Location: ".BASE_URL );
die();
}else{ // if not tell them to contact support for manual removal
$_SESSION['message'] = "You where not found - please contact support";
header("Location: ".BASE_URL );
die();
}
That is now all complete and you should have a working mailing list app. Hope that you have found this interesting and learnt a few things.
Twitter
Follow me on Twitter to keep up to date!
RSS Feed
Keep up with all of our updates by subscribing to our RSS feed!
FaceBook
Join our group on Facebook and become a fan of us!