Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
0% found this document useful (0 votes)
17 views

Newsletter System with PHP and MySQL

This document is a tutorial for creating an interactive newsletter system using PHP and MySQL, which includes features like subscription widgets and a mailing list. It outlines the necessary requirements, file structure, and step-by-step instructions for setting up the database, creating stylesheets, and implementing JavaScript for interactivity. The tutorial aims to help individuals and organizations build their audience by sending newsletters to subscribers effectively.

Uploaded by

William Smith
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
17 views

Newsletter System with PHP and MySQL

This document is a tutorial for creating an interactive newsletter system using PHP and MySQL, which includes features like subscription widgets and a mailing list. It outlines the necessary requirements, file structure, and step-by-step instructions for setting up the database, creating stylesheets, and implementing JavaScript for interactivity. The tutorial aims to help individuals and organizations build their audience by sending newsletters to subscribers effectively.

Uploaded by

William Smith
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 21

HTML CSS JavaScript jQuery PHP Python MySQL

Newsletter System with PHP and MySQL


Updated on October 11, 2022 by David Adams

In this tutorial, we'll develop an interactive newsletter system with PHP and MySQL, consisting of
subscription widgets, a mailing list, and an interface to send subscribers newsletters.

A newsletter system will enable you to send emails to your subscribers periodically, which could be product
promotions, social events, or engaging content. Whether you're an independent individual or a large
organization, the system will help you build your audience.

The Advanced package includes additional features and a download link to the source code.

Contents

1 Introduction
2 Getting Started
2.1 Requirements
2.2 What You Will Learn in this Tutorial
2.3 File Structure & Setup
3 Creating the Database
4 Creating the Stylesheet (CSS3)
5 Creating the Interactive Widget with JS
6 Subscription Handling with PHP
6.1 Database Connection with PDO
6.2 Subscribe
6.3 Unsubscribe
7 Developing the Newsletter Interface
7.1 Creating the Form
7.2 Implementing AJAX to Process the Form
7.3 Form Handling with PHP

1. Introduction
You can signiHcantly increase your audience by implementing an interactive subscription widget on your
website. It should be essential for any website that wants to increase growth.

With PHP, we can leverage the mail function to send emails to recipients, and the subscriber can
subsequently view the newsletter and respond accordingly.

2. Getting Started
Before we get started, we need to outline the foundation for our project and utilize the tools we'll be using.
We must effectively plan all aspects of our project before moving on to the development phase, otherwise
there could be dire consequences.

2.1. Requirements

Unfortunately, we can't just open up Notepad and start developing our project. There are essential
requirements that need to be met, such as we need a web server and code editor.

The following are required for our project:

Web Server Solution Stack Package — We recommend you download and install XAMPP.

PHP >= 5.5 — The latest version is included with XAMPP, and therefore you don't need to download it
separately.

MySQL >= 5.6 — The same as above.

Code Editor — We recommend Visual Studio Code.

Warning
! XAMPP should not be used for production purposes, but only for development purposes.

2.2. What You Will Learn in this Tutorial

Below will give you an idea of what you will accomplish while reading this article.

Form Handling — Design a form and process requests with PHP, while capturing data and storing it in
our MySQL database.

Interactive Widget Creation with JS — Design and develop an interactive subscription widget with
JavaScript.

AJAX Implementation — Implement code to process the subscription form in the background using
AJAX.

Utilizing PHP Mail — Design a user interface for our newsletters and send captured form data to a
speciHed email address.

Layout Design with CSS3 — Design multiple layouts with stylesheets.

2.3. File Structure & Setup

Let's start by creating all the Hles we will use for our project. Navigate to your webroot directory
(c:\xampp\htdocs, etc.) and create the below directory along with the Hles.

File Structure

\-- phpnewsletter
|-- style.css
|-- index.html
|-- newsletter.php
|-- subscribe.php
|-- unsubscribe.php
|-- main.php
Each Hle will consist of the following:

style.css — The stylesheet (CSS3) for our newsletter system, which is used to format our structured
content (HTML).

index.html — The index Hle will contain the chat widget implementation and AJAX code to process the
subscription form.

newsletter.php — Will contain the newsletter interface used by webmasters to send out newsletters to
speciHed subscribers.

subscribe.php — The subscribe Hle will insert a new subscriber in to our MySQL database. Validation
will be in place to ensure the subscriber doesn't already exist.

unsubscribe.php — The unsubscribe Hle will delete the subscriber from the database.

main.php — The main Hle will contain the database connection code.

After, we can go ahead and start XAMPP — follow the below instructions.

Open the XAMPP Control Panel

Next to the Apache module, click Start

Next to the MySQL module, click Start

If successful, the background color will change to green. If not, you might want to check your port
numbers to ensure they don't con_ict with the module ports.

Navigate to http://localhost/ in your browser — the XAMPP welcome page should appear.

3. Creating the Database


In this section, we'll create the MySQL database with phpMyAdmin (included with XAMPP) and execute a
SQL statement to create all the tables and columns.

The database will enable us to store all our subscribers and retrieve them when sending out newsletters.

Follow the below instructions:

Navigate to http://localhost/phpmyadmin/ in your browser

Click the Databases tab in the top navigation bar

Under the Create Database section, enter phpnewsletters as the database name

Select the utf8_general_ci collation

Click Create

Select the newly created database in the left-side panel

Click the SQL tab in the top navigation bar

Execute the below SQL statement

SQL ! Copy

CREATE TABLE `subscribers` (


`id` int(11) NOT NULL AUTO_INCREMENT,
`email` varchar(255) NOT NULL,
`date_subbed` datetime NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

If we click the subscribers table, it will look like the following in phpMyAdmin:
That's all we need to do for the database creation. If you would like to check the list of subscribers, you can
navigate to the Browse tab while viewing the subscribers table.

4. Creating the Stylesheet (CSS3)


The stylesheet will contain properties that will describe the presentation of the elements in our documents.
Basically, it will make our newsletter system more appealing.

Edit the style.css Hle and add:

CSS ! Copy

* {
box-sizing: border-box;
font-family: -apple-system, BlinkMacSystemFont, "segoe ui", roboto, oxygen, ubuntu, cantarell, "fira sans", "droid sans", "helvetica ne
font-size: 16px;
}
body {
margin: 0;
padding: 15px;
height: 3000px;
}
.newsletter-popup {
display: none;
justify-content: center;
align-items: center;
background-color: transparent;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 999999;
transition: all .3s ease;
}
.newsletter-popup .newsletter-popup-container {
position: relative;
display: flex;
flex-flow: column;
padding: 30px;
background-color: #fff;
box-shadow: 0 0 10px 0 rgba(0, 0, 0, 0.1);
width: 500px;
transform: scale(0.3);
transition: all .3s ease;
}
.newsletter-popup .newsletter-popup-container.open {
transform: scale(1);
}
.newsletter-popup .newsletter-popup-container h3 {
font-size: 20px;
font-weight: 500;
margin: 0;
padding: 10px 0 10px;
color: #4d5561;
}
.newsletter-popup .newsletter-popup-container h3 i {
display: inline-flex;
justify-content: center;
align-items: center;
width: 35px;
height: 35px;
border-radius: 50%;
background-color: #4d5561;
color: #fff;
margin-right: 10px;
}
.newsletter-popup .newsletter-popup-container p {
margin: 0;
padding: 15px 0;
color: #8d9092;
}
.newsletter-popup .newsletter-popup-container form {
display: flex;
padding: 15px 0 10px;
}
.newsletter-popup .newsletter-popup-container form input {
width: 100%;
padding: 10px;
border: 1px solid #ddd;
outline: none;
}
.newsletter-popup .newsletter-popup-container form input::placeholder {
color: #8d9092;
}
.newsletter-popup .newsletter-popup-container form button {
width: 200px;
appearance: none;
background-color: #4d5561;
font-weight: 500;
font-size: 14px;
color: #fff;
border: 0;
cursor: pointer;
}
.newsletter-popup .newsletter-popup-container form button:hover {
background-color: #424953;
}
.newsletter-popup .newsletter-popup-container .newsletter-popup-close-btn {
position: absolute;
right: 20px;
top: 20px;
text-decoration: none;
color: #ddd;
font-size: 30px;
line-height: 20px;
}
.newsletter-popup .newsletter-popup-container .newsletter-popup-close-btn:hover {
color: #c4c4c4;
}
.newsletter-popup .newsletter-popup-container .newsletter-msg {
padding: 5px 0;
}
.newsletter-popup.open {
display: flex;
background-color: rgba(0, 0, 0, 0.4);
}
.send-newsletter-form {
background-color: #fff;
width: 500px;
margin: 0 auto;
box-shadow: 0px 0px 5px 0px rgba(0, 0, 0, 0.2);
}
.send-newsletter-form h1 {
display: flex;
justify-content: center;
align-items: center;
margin: 0;
padding: 25px;
font-size: 20px;
text-align: center;
border-bottom: 1px solid #eceff2;
color: #6a737f;
font-weight: 600;
background-color: #f9fbfc;
}
.send-newsletter-form h1 i {
padding-right: 10px;
font-size: 24px;
}
.send-newsletter-form .fields {
position: relative;
padding: 20px;
}
.send-newsletter-form input[type="text"] {
margin-top: 15px;
padding: 15px;
border: 1px solid #dfe0e0;
width: 100%;
outline: 0;
font-size: 14px;
}
.send-newsletter-form input[type="text"]:focus {
border: 1px solid #c6c7c7;
}
.send-newsletter-form textarea {
resize: none;
margin-top: 15px;
padding: 15px;
border: 1px solid #dfe0e0;
width: 100%;
height: 150px;
outline: 0;
font-size: 14px;
}
.send-newsletter-form textarea:focus {
border: 1px solid #c6c7c7;
}
.send-newsletter-form input[type="submit"] {
display: block;
margin-top: 15px;
padding: 15px;
border: 0;
background-color: #cb5f51;
font-weight: bold;
color: #fff;
cursor: pointer;
width: 100%;
}
.send-newsletter-form input[type="submit"]:hover {
background-color: #c15b4d;
}
.send-newsletter-form input[type="submit"]:disabled {
background-color: #999999;
}
.send-newsletter-form .field {
display: inline-flex;
position: relative;
width: 100%;
padding-bottom: 20px;
}
.send-newsletter-form label {
font-size: 14px;
font-weight: 600;
color: #8e939b;
}
.send-newsletter-form .responses {
padding: 0;
margin: 0;
}
.send-newsletter-form .multi-select-list {
border: 1px solid #dfe0e0;
margin: 15px 0;
overflow-y: auto;
max-height: 150px;
}
.send-newsletter-form .multi-select-list label {
display: flex;
align-items: center;
padding: 15px;
border-bottom: 1px solid #f3f3f3;
}
.send-newsletter-form .multi-select-list label input {
margin-right: 15px;
}
.send-newsletter-form .multi-select-list label:last-child {
border-bottom: 0;
}

Feel free to customize the stylesheet to your own satisfaction.

5. Creating the Interactive Widget with JS


In this section, we'll effectively implement JavaScript code to create an interactive popup widget and include
AJAX code to process the subscription form.

The adversity of implementing an interactive chat widget on your website is to avoid annoyance to your
users. You wouldn't want your visitors to come to your website and be instantly bombarded with a newsletter
popup widget. Therefore, a better solution is to seamlessly open the popup when the user reaches a speciHc
point when scrolling down the page, which is what we'll implement shortly.

Edit the index.html Hle and add:

HTML ! Copy

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,minimum-scale=1">
<title>Newsletter</title>
<link href="style.css" rel="stylesheet" type="text/css">
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v6.1.1/css/all.css">
</head>
<body>

<h1>Newsletter</h1>

<p>Hello world!</p>

</body>
</html>

The above page is just a base for us to work with. You can add the widget to any webpage. The Font
Awesome library will enable us to add icons to the subscription widget.

After:

<p>Hello world!</p>

Add:

HTML ! Copy

<div class="newsletter-popup">
<div class="newsletter-popup-container">

<a href="#" class="newsletter-popup-close-btn">&times;</a>

<h3><i class="fa-regular fa-envelope"></i>Subscribe To Our Newsletter</h3>

<p>Join our subscribers list to get the latest news, updates, and special offers directly in your inbox.</p>

<form action="subscribe.php" method="post">


<input type="email" name="email" placeholder="Your Email" required>
<button type="submit">Subscribe</button>
</form>

<p class="newsletter-msg"></p>

</div>
</div>

The above code is the template for our popup widget, which contains the subscription form that's associated
with the subscribe.php Hle. In addition, we have included the email input element and submit button.

The name attribute attached to the email input element will re_ect the POST variables we declare in the
subscribe.php Hle. We will use it to capture the subscriber's email address.

Responses retrieved from the AJAX request will be stored in the newsletter-msg element.

Next up, we'll implement the AJAX code, so after the above code, add the following:

JS ! Copy

<script>
// Will prevent the popup from reopening when the close button is clicked
let keepClosed = false;
// Open the newsletter subscription popup
const openNewsletterPopup = () => {
// Update the style and element properties
document.querySelector('.newsletter-popup').style.display = 'flex';
document.querySelector('.newsletter-popup').getBoundingClientRect();
document.querySelector('.newsletter-popup').classList.add('open');
document.querySelector('.newsletter-popup-container').getBoundingClientRect();
document.querySelector('.newsletter-popup-container').classList.add('open');
};
const closeNewsletterPopup = () => {
// Revert the element properties
document.querySelector('.newsletter-popup').style.display = 'none';
document.querySelector('.newsletter-popup').classList.remove('open');
document.querySelector('.newsletter-popup-container').classList.remove('open');
// Keep it closed!
keepClosed = true;
};
! CodeShack
// Get the subscription form
const newsletterForm = document.querySelector('.newsletter-popup form');
// On submit event handler (submit button is pressed)
Packages Tutorials
newsletterForm.onsubmit = event => {
event.preventDefault();
// Bind the subscription form and execute AJAX request
Examples References Tools
fetch(newsletterForm.action, {
method: 'POST',
body: new FormData(newsletterForm)
}).then(response => response.text()).then(data => {
// Output the response
document.querySelector('.newsletter-msg').innerHTML = data;
});
};
// Close button onclick event handler
document.querySelector('.newsletter-popup-close-btn').onclick = event => {
event.preventDefault();
// CLose the popup widget
closeNewsletterPopup();
};
// Open the popup widget when the user reaches a specific point while scrolling down
document.addEventListener('scroll', () => {
// If you want to open the widget further down the page, increase the 400 value
if (window.scrollY >= 400 && !keepClosed) {
// Open the widget
openNewsletterPopup();
}
});
</script>
By using this website, you agree that we and our partners
Whenmay
the user
set cookies
reachesfor
a speciHc
purposes
point
suchwhile
as customising
scrolling down, the newsletter subscription popup will appear,
content and advertising. I Understand
content and advertising. I Understand
which will enable the user to input their email address and submit their details to the subscribe.php Hle. To
do that, we can leverage the scroll event handler and attach it to our document.

Upon form submission, we utilize the fetch() API to execute an AJAX request, meaning the form will
process in the background as opposed to being redirected to a new page. The former is more convenient in
modern web apps.

JS Tip
! You can easily bind an HTML form element to the fetch API using the FormData interface.

The openNewsletterPopup() and closeNewsletterPopup() functions are self-explanatory, one will


open the newsletter widget, and the other will close it.

If we navigate to our index.html Hle in the browser and scroll down to the near bottom, the newsletter
subscription widget should popup, like so:

http://localhost/phpnewsletter/index.html

M SubscribeToOurNewsletter

Joinoursubscriberslisttogetthelatestnews,updates,and
specialsoffersdirectlyinyourinbox.

YourEmail Subscribe

However, don't expect it to be fully functional as we have yet to implement the PHP code to process the form,
which we will do in the next section.

6. Subscription Handling with PHP


Now that we have created our subscription form, we need to implement server-side code to process it, which
is where PHP comes into play. Without PHP, our subscription form is redundant because PHP will enable us
to validate the email address and insert it into our MySQL database using the PDO interface.

6.1. Database Connection with PDO

Before we start coding the subscribe and unsubscribe Hles, we require a Hle that connects to our MySQL
database using the PDO interface. We'll connect to the database in all our other Hles, therefore it's
convenient to create an independent Hle and add the connection code.

Edit the main.php Hle and add:

PHP ! Copy
<?php
// Update the details below with your MySQL details
$DATABASE_HOST = 'localhost';
$DATABASE_USER = 'root';
$DATABASE_PASS = '';
$DATABASE_NAME = 'phpnewsletter';
try {
$pdo = new PDO('mysql:host=' . $DATABASE_HOST . ';dbname=' . $DATABASE_NAME . ';charset=utf8', $DATABASE_USER, $DATABASE_PASS);
// Output all connection errors. We want to know what went wrong...
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $exception) {
// If there is an error with the connection, stop the script and display the error.
exit('Failed to connect to database!');
}
?>

Make sure to update the database variables to re_ect your MySQL details.

6.2. Subscribe

The subscription process is fairly simple — we validate the captured email address and insert it into the
database, but only if it doesn't already exist. If we don't check that it exists, we would have multiple records
for the same subscriber and therefore wouldn't be coherent with our database structure.

Edit the subscribe.php Hle and add:

PHP ! Copy

<?php
include 'main.php';
// Ensure post variable exists
if (isset($_POST['email'])) {
// Validate email address
if (!filter_var($_POST['email'], FILTER_VALIDATE_EMAIL)) {
exit('Please provide a valid email address!');
}
// Check if email exists in the database
$stmt = $pdo->prepare('SELECT * FROM subscribers WHERE email = ?');
$stmt->execute([ $_POST['email'] ]);
if ($stmt->fetch(PDO::FETCH_ASSOC)) {
exit('You\'re already a subscriber!');
}
// Insert email address into the database
$stmt = $pdo->prepare('INSERT INTO subscribers (email,date_subbed) VALUES (?,?)');
$stmt->execute([ $_POST['email'], date('Y-m-d\TH:i:s') ]);
// Output success response
exit('Thank you for subscribing!');
} else {
// No post data specified
exit('Please provide a valid email address!');
}
?>

As we can see, we Hrst include our main Hle (which contains our database connection code), and then we
check whether the captured email variable exists or not. If it does, we can validate it and Hnally insert it into
our database using the PDO interface.

PHP Tip
! The PDO prepare method will prevent SQL injection but only if used correctly.

The whole concept is to add our subscribers to the database, so we can later retrieve them and send them
newsletters. Why manually input email addresses when we can retrieve them from the database and
populate a list? Therefore, the database is practical in such scenarios — it will save us valuable time and
effort.

6.3. Unsubscribe

The unsubscribe Hle will do the complete opposite of what we've just done with the subscribe Hle. Instead of
inserting a new subscriber into the database, we're deleting the subscriber.

Edit the unsubscribe.php Hle and add:

PHP ! Copy

<?php
include 'main.php';
// Ensure post variable exists
if (isset($_GET['email'], $_GET['code'])) {
// Validate email address
if (!filter_var($_GET['email'], FILTER_VALIDATE_EMAIL)) {
exit('Please provide a valid email address!');
}
// Check if email exists in database
$stmt = $pdo->prepare('SELECT * FROM subscribers WHERE email = ?');
$stmt->execute([ $_GET['email'] ]);
$subscriber = $stmt->fetch(PDO::FETCH_ASSOC);
if ($subscriber) {
// Verify code
if (sha1($subscriber['id'] . $subscriber['email']) == $_GET['code']) {
// Delete the email from the subscribers list
$stmt = $pdo->prepare('DELETE FROM subscribers WHERE email = ?');
$stmt->execute([ $_GET['email'] ]);
// Output success response
exit('You\'ve successfully unsubscribed!');
} else {
exit('Incorrect code provided!');
}
} else {
exit('You\'re not a subscriber or you\'ve already unsubscribed!');
}
} else {
exit('No email address and/or code specified!');
}
?>

In the above code, we're checking if an additional parameter has been speciHed, which is the code
parameter. The code parameter will add an extra layer of security when removing the subscriber from the
database as it requires a unique hashed string based on the email and ID columns in the database.

We're leveraging GET requests as opposed to POST requests because it enables us to specify parameters in
the URL (unsubscribe.php?email=email&code=code, etc.). It's essential because we'll include the
unsubscribe link in the newsletter template, so the basic structure for our unsubscribe link will appear similar
to the following:

<a href="https://codeshack.io/unsubscribe.php?email=david@codeshack.io&code=d864fa1be1a44abae7e4cfe9d0903cbea163d0fc">Unsubscribe</a>

We will implement code to automatically generate the unsubscribe URL in the next section.

7. Developing the Newsletter Interface


The newsletter interface will be more sophisticated than the other Hles as it comprises three phases, which
include creating the newsletter form with HTML, implementing AJAX to process the form, and handling the
form with PHP.

The interface will enable us to send a newsletter (in HTML format) to selected recipients (subscribers). We
wouldn't want to burden our mail server, and therefore we'll implement tactics to send the newsletter to
individual recipients at a set interval, for example, every 5 seconds.

7.1. Creating the Form

We need to create a layout that we can use to send newsletters to our subscribers, so let's get started!

Edit the newsletter.php Hle and add:

PHP ! Copy
<?php
include 'main.php';
// NOTICE: THE FOLLOWING PAGE IS UNRESTRICTED AND THEREFORE WE SUGGEST YOU IMPLEMENT RESTRICTIONS BEFORE GOING PRODUCTION
// Get all subscribers from the database
$stmt = $pdo->prepare('SELECT * FROM subscribers');
$stmt->execute();
$subscribers = $stmt->fetchAll(PDO::FETCH_ASSOC);
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,minimum-scale=1">
<title>Send Newsletter</title>
<link href="style.css" rel="stylesheet" type="text/css">
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v6.1.1/css/all.css">
<style>
html {
background-color: #F8F9F9;
background: linear-gradient(0deg, #f9f8f8 0%, #f9f8f8 80%, #cb5f51 80%, #cb5f51 100%);
padding: 30px;
height: 100%;
}
</style>
</head>
<body>

<form class="send-newsletter-form" method="post" action="">

<h1><i class="fa-regular fa-envelope"></i>Send Newsletter</h1>

<div class="fields">

<label for="recipients">Recipients</label>
<div class="multi-select-list">
<?php foreach ($subscribers as $subscriber): ?>
<label>
<input type="checkbox" class="recipient" name="recipients[]" value="<?=$subscriber['email']?>"> <?=$subscriber['e
</label>
<?php endforeach; ?>
</div>

<label for="subject">Subject</label>
<div class="field">
<input type="text" id="subject" name="subject" placeholder="Subject" required>
</div>

<label for="template">Email Template</label>


<div class="field">
<textarea id="template" name="template" placeholder="Enter your HTML template code here..." required></textarea>
</div>

<div class="responses"></div>

</div>

<input id="submit" type="submit" value="Send">

</form>

</body>
</html>

First and foremost, we execute code to retrieve all our subscribers from the database and subsequently
populate them using the foreach loop.

The form consists of three elements, one being the list of recipients that we can select (comprises of
checkboxes), the second being the subject of the newsletter, and the last being the newsletter template
(HTML). In addition, we have the form method set to POST , so we can capture the form data upon
submission.
If we navigate to the newsletter.php Hle, we should see the following form:

http://localhost/phpnewsletter/newsletter.php

You can ignore the list of recipients as they're added for testing purposes, but you can get a general idea of
what to expect.

7.2. Implementing AJAX to Process the Form

We can leverage AJAX to send our newsletter to selected recipients at a set interval. We have already
covered the basics of AJAX requests, and therefore you should have a basic understanding of what's going
on.

After:

</form>

Add:

HTML ! Copy

<script>
// Retrieve the form element
const newsletterForm = document.querySelector('.send-newsletter-form');
// Declare variables
let recipients = [], totalRecipients = 0, recipientsProcessed = 0;
// Form submit event
newsletterForm.onsubmit = event => {
event.preventDefault();
// Retrieve all recipients and delcare as an array
recipients = [...document.querySelectorAll('.recipient:checked')];
// Total number of selected recipients
totalRecipients = recipients.length;
// Total number of recipients processed
recipientsProcessed = 0;
// Clear the responses (if any)
document.querySelector('.responses').innerHTML = '';
// Temporarily disable the submit button
document.querySelector('#submit').disabled = true;
// Update the button value
document.querySelector('#submit').value = `(1/${totalRecipients}) Processing...`;
};
// The below code will send a new email every 3 seconds, but only if the form has been processed
setInterval(() => {
// If there are recipients...
if (recipients.length > 0) {
// Create form data
let formData = new FormData();
// Append essential data
formData.append('recipient', recipients[0].value);
formData.append('template', document.querySelector('#template').value);
formData.append('subject', document.querySelector('#subject').value);
// Use AJAX to process the form
fetch(newsletterForm.action, {
method: 'POST',
body: formData
}).then(response => response.text()).then(data => {
// If success
if (data.includes('success')) {
// Increment variables
recipientsProcessed++;
// Update button value
document.querySelector('#submit').value = `(${recipientsProcessed}/${totalRecipients}) Processing...`;
// When all recipients have been processed...
if (recipientsProcessed == totalRecipients) {
// Reset everything
newsletterForm.reset();
document.querySelector('#submit').disabled = false;
document.querySelector('#submit').value = `Submit`;
document.querySelector('.responses').innerHTML = 'Newsletter sent successfully!';
}
} else {
// Error
document.querySelector('.responses').innerHTML = data;
}
});
// Remove the first item from array
recipients.shift();
}
}, 3000); // 3000 ms = 3 seconds
</script>

In the above code, we are basically iterating all the selected recipients and executing an AJAX request every
3 seconds, but only when the form has been submitted. To do that, we select all the recipients with the
:selected selector and subsequently remove the recipient from the array when it has been processed.

JS Tip

! The setInterval() method executes a function at speciHed intervals, meaning the code will be repeatedly executed
every X milliseconds. In our case, the function will execute every 3 seconds.

The recipientsProcessed variable will determine how many recipients have been processed and we can
update the label accordingly, but only if the response from the AJAX request is successful.

7.3. Form Handling with PHP

In the Hnal step, we will implement code to process the form and utilize the mail function to send our
newsletter to selected recipients.

Prepend the following code to the newsletter.php Hle (placed at the top):
PHP ! Copy

<?php
include 'main.php';
// NOTICE: THE FOLLOWING PAGE IS UNRESTRICTED AND THEREFORE WE SUGGEST YOU IMPLEMENT RESTRICTIONS BEFORE GOING PRODUCTION
// Get all subscribers from the database
$stmt = $pdo->prepare('SELECT * FROM subscribers');
$stmt->execute();
$subscribers = $stmt->fetchAll(PDO::FETCH_ASSOC);
// Process form
if (isset($_POST['recipient'], $_POST['subject'], $_POST['template'])) {
// From address
$from = 'Your Company Name <noreply@yourdomain.com>';
// Email Headers
$headers = 'From: ' . $from . "\r\n" . 'Reply-To: ' . $from . "\r\n" . 'Return-Path: ' . $from . "\r\n" . 'X-Mailer: PHP/' . phpversi
// Determine the subscriber
$subscriber = null;
foreach ($subscribers as $s) {
if ($s['email'] == $_POST['recipient']) {
$subscriber = $s;
}
}
// Make sure subscriber exists
if ($subscriber) {
// Update the unsubscribe link
$unsubscribe_link = 'https://yourwebsite.com/unsubscribe.php?email=' . $subscriber['email'] . '&code=' . sha1($subscriber['id'] .
// Replace the placeholder
$template = str_replace('%unsubscribe_link%', $unsubscribe_link, $_POST['template']);
// Send email to user
if (mail($_POST['recipient'], $_POST['subject'], $template, $headers)) {
exit('success');
} else {
exit('Failed to send newsletter! Please check your SMTP mail server!');
}
} else {
exit('Invalid recipient!');
}
}
?>

The $subscribers associative array will populate the list of recipients using the foreach loop that we
implemented previously.

Because we're going to submit the form data to the same Hle, we have implemented the isset() function
to check whether the captured data exists or not. If it exists, we can process the form and send the
newsletter using the mail() function.

Did You Know?


! For the mail() function to work correctly, you need a working SMTP mail server.

Don't forget to update the $from variable to re_ect your business name and email address. Do NOT remove
the symbols next to the email address. Also, the $unsubscribe_link variable must re_ect your domain
name and point to your unsubscribe Hle. To add the unsubscribe link to the template, simply place
%unsubscribe_link% in your newsletter HTML template.

We can Hnally test the implementation — if all goes well, the number of recipients processed will appear
above the form button. If not, you might want to check that you have a working SMTP mail server installed
and conHgured correctly.

Conclusion
You should now have a basic understanding of the fundamentals involved when creating a newsletter
system. The whole concept of a newsletter system is to manage subscribers and leverage the in-built mail
function to send newsletters.

You may be wondering if the code is production ready — the short answer is NO. You would need to
implement restrictions to the newsletter Hle, otherwise it'll be exposed to the public, and anyone with a
browser can access it and execute form requests.

If you have enjoyed this tutorial, don't forget to share it on social media and/or purchase the advanced
package — it'll greatly help support us and create more quality content!

Enjoy coding!

If you would like to support us, consider purchasing the advanced newsletter & mailing system below as it
will greatly help us create more tutorials and keep our website up and running. The advanced package
includes improved code and more features.
Sale
ADVANCED BUNDLE (SAVE 53%)

$ 20.00 $ 119.00 255.00


view more details view more details

Source Code ! Secure Login & Registration System !

Interactive Subscription Widgets ! Shopping Cart System !

Secure Newsletter & Mailing System ! CRUD Application !

Automate Newsletters ! Ticketing System !

Create Campaigns ! Gallery System !

Scheduled Tasks (Cron Job) ! Event Calendar System !

PHPMailer Integration ! Poll and Voting System !

Sample Templates ! Commenting System !

AJAX Integration ! Review System !

Improved Code ! Contact Form !

Admin Panel ! Live Support Chat System !

Responsive Design (mobile-friendly) ! Newsletter & Mailing System !

SCSS File ! Access to future scripts !

Commented Code !

Free Updates & Support (minor issues) !

User Guide !

Extra: Tutorial Source Code !

PayPal PayPal
Download Download

Stripe Stripe
Download Download

Crypto Crypto
Download Download

! ! ! "
ABOUT AUTHOR

David Adams
Enthusiastic website developer, I've been designing and developing web
applications for over 10 years, I enjoy the creativity I put into my projects
and enjoy what others bring to the awesome web. My goal is to help
newcomers learn the ways of the web.

mailing list newsletter system php tutorials

← Live Support Chat with AJAX, PHP and MySQL File Upload Progress Bar with JS and PHP →

Read RELATED
ReadPOSTS Read

Live Support Chat with AJAX, PHP Shopping Cart System with PHP Poll and Voting System with PHP
and MySQL and MySQL and MySQL

9 Comments !
1 Login

Join the discussion…

LOG IN WITH
OR SIGN UP WITH DISQUS ?

Name

Sort by Newest % 1 ⥅

Moti Mo − ⚑
a month ago

Hey David, happy to see this script on your page :-) Maybe I will buy this advanced package. How about a demo
like your shoppingcart? Which features you plan in future? Thanks, Timo
△ ▽ Reply
David Adams > Moti Mo − ⚑
a month ago

Hi Timo, Glad to have you back here! Unfortunately, I don't have a demo for it, but you can check out all the
features and screenshots here: https://codeshack.io/packag...

Regarding future features, as it's a new addition to the advanced packages, I haven't got any new plans at the
moment, but if you can think of some, feel free to let me know and I'll consider them. :-)
△ ▽ Reply

Teun Bevers − ⚑
a month ago
Hi David, with the paid package would it be possible in any way to have multiple access roles/accounts and send
mail from different aliases on the same domain. For example send mail from info@domain.com but also from
support@domain.com to subscribers. Let me know, thanks
△ ▽ Reply
David Adams > Teun Bevers − ⚑
a month ago
Hi @Teun Bevers,

Possibly, but you would have to change the code to send from sender's email address or from an additional
column stored in the accounts table. Currently, the from address is based on a predefined constant in the config
file:

$mail->setFrom(mail_from, mail_from_name);

If you bind the account details to the function, you can send from the sender's email instead:
$mail->setFrom($account['email'], mail_from_name);

△ ▽ Reply

Ivan Toscano − ⚑
2 months ago
Very nice, David. Interesting as usual. I know developers who would write tons of code, using tangled and complex
functions, to do basically the same thing. You're able to make things look simple, and this is an important skill for a
developer, I think. It's a pleasure to follow your work.
△ ▽ Reply
David Adams > Ivan Toscano − ⚑
2 months ago

Thanks, Ivan! I appreciate the kind words.


△ ▽ Reply

Fred Bonani − ⚑
3 months ago
Good to see the newsletter project and I have been playing around with it. Maybe I am being optimistic but I am
hoping that my list of subscribers will grow to the point that the list displayed in one column is going to stretch the
newsletter template quite a bit. Can the subscriber list be displayed in two or three columns at the top of the
newsletter and if so what would be the code change involved. I realize that the newsletter template would have to
be widened, but that is easily handled.
△ ▽ Reply
David Adams > Fred Bonani − ⚑
3 months ago
Are you referring to the list of recipients on the send newsletter page? If so, I've included code that if the
element exceeds the max height, a vertical scrollbar will appear.
△ ▽ Reply
Fred Bonani > David Adams − ⚑
3 months ago

Was not aware of that, thanks for the response.


△ ▽ Reply

✉ Subscribe ) Privacy ⚠ Do Not Sell My Data

Code in Node.js, Java, Python,


and other open-source
languages.

ADS VIA CARBON

Search blog ... !



Become a Subscriber
Stay up to date and join our newsletter to
receive the latest updates.

Email Address

Subscribe

FOLLOW US

! ! "

RECENT POSTS

File Upload Progress Bar with


JS and PHP

Newsletter System with PHP


and MySQL

Live Support Chat with AJAX,


PHP and MySQL

TAGS

tutorials php mysql programming

javascript snippets ajax css form

php class html login freebies

scripting pdo mysqli shopping cart

registration register columns

live support chat database modals

snippet survey form python jquery

voting system progamming mvc

newsletter system table

commenting system javascript class

sessions express hotel reservation form

poll system progress bar crud

gallery system event calendar sort

review system cookie js pagination

node.js content locker [ask contact

ticketing system \le upload template

mailing list
" CODESHACK.IO FOLLOW US

Packages Tools About Us


! !
Tutorials Live Code Editor Contact Us

Examples JSON Sorter Privacy Policy

References Resend a Receipt Terms

© 2022 CodeShack. All Rights Reserved. By using this website you accept the terms and conditions.

You might also like