PHP Newsletter Script

So I’m trying to develop my own newsletter script (mostly just for fun), and I seem to have gotten stuck at a certain point and can’t get any further. So what I’m trying to do is get the users i’m going to be sending to, in table “tblnewsletter”, and then check the mailings table named “tblnewslettermailings” for the ID that was called in the URL from the admin panel. I can’t seem to get anywhere from there. Here’s my code.

[php]if(isset($_GET[‘process’]) && $_GET[‘process’] == “send”) {
$id = $_GET[‘email’];
if (mysqli_connect_errno()) { echo “Failed to connect to MySQL: " . mysqli_connect_error(); }
$query = mysqli_query($con,“SELECT * tblnewsletter”);
while($row = mysqli_fetch_array($query)) {
$to = $row[‘email’];
$headers = “Reply-To: Administrator [email protected] \r\n”;
$query2 = mysqli_query($con,“SELECT * tblnewslettermailings where id = '”.$id.”’");
while($row2 = mysqli_fetch_array($query2)) {
$subject = $row2[‘subject’];
$body = $row2[‘body’];
}
mail($to,$subject,$body,$headers);
echo $id."
";
echo $to."
";
echo $headers."
";
echo $subject."
";
echo $body."
";
}
//mysqli_query($con,"UPDATE * tblnewslettermailings WHERE id = “.$id.”);

mysqli_close($con);
//header(‘Location: /sadmin/sendnewsletter?action=sent’);
}
[/php]

$con and all the other variables you see are defined outside the script I’ve included. Please keep in mind this is only a development script, so excuse any improper coding.

==================================
Edit:
Anything $row is from tblnewsletter
Anything $row2 is from tblnewslettermailings

I really haven’t look how you handle you database connection (I am also a little rusty with mysqli for I been using PDO), but I would suggest only using one array. Since you are using a associate array $row[‘email’] for example, you really don’t need $row2 in my opinon. Secondly look into using PHPMailier https://github.com/Synchro/PHPMailer or another mailer system, in my opinion it will make your life easier and offers better security. In addition you can really send out a nice looking newsletter for people who allow HTML in their emails. Just a suggestion though. You might even consider down the road to put the newsletter in a pdf format and send them the pdf thus skipping MySQL all together. Well, for the newsletter itself anyways. ;D Ooops, let me backtrack a little. While it’s feasible to use one array, it might make it simpler to use two; however, I would give the arrays better names. $newsletter and $subscribers?

Normally, I love to see someone solve their project with their own code, this time I think Strider is correct in steering you to PHPmailer as it will do everything you want. Also, he is 100% on using names for arrays that make sense. Row and Row2 mean nothing to anyone reading your code. Follow what Strider suggests.

Now with that said… If you want to get this code working, you parse thru all of the Query2/Row2 but, you only process the last item in that list. Your WHILE ends after loading the BODY. So, not sure why you would want to do that. Perhaps you meant the ending brace “}” to be after the mail command not before it so all of the subjects/bodies are sent out…

Hope that helps…

I didn’t want to use PHPMailer, because I’m trying to design my own coding (and further my skills), can’t learn much when you use someone elses code… I have it working, and mailing out correctly, however (and I’ve redone my code), it’s sending all of the emails to one recipient, instead of one to each of them. Any ideas?

[php]// send newsletter
if(isset($_GET[‘process’]) && $_GET[‘process’] == “send”) {
// email template id
$id = $_GET[‘id’];
echo "Got Email ID ".$id;

// get subscribers
$subscribers = mysqli_query($con,"SELECT email, firstname, lastname FROM tblnewsletter") or die(mysql_error());
echo "<br>Connected to DB<br>";
while($row = mysqli_fetch_array($subscribers)) {
$recipent = $row['email'];
$recipent_name = $row['firstname']." ".$row['lastname'];
echo "Connected to TBLNEWSLETTER<br>";	
		// get email template
		$template = mysqli_query($con,"SELECT * FROM tblnewslettermailings WHERE id='".$id."'") or die(mysql_error());
		while($temp = mysqli_fetch_array($template)) {
		$data = array();
		$name = $temp['name'];
		$subject = $temp['subject'];
		$body = $temp['body'];	
		echo "Connected to Getting Emails<br>";
		array_push($data, $row["email"]);
			foreach($data as $emails){
			// actually send email
			$from = "Administrator <[email protected]>";
			$replyto = $from;
			$headers = 'From: ' . $from . "\r\n" . 'Reply-To: ' . $replyto . "\r\n" . 
				'X-Mailer: PHP/' . phpversion();
		
			$to = $email;
			$msgbody = 'Test';				
			
			mail($to, $temp['subject'], $msgbody, $headers);
			echo "Message Sent to $email.<br>";
			}						
	 } 
}

}
mysqli_close($con);
[/php]

Good for you! I am always happy to see someone learning and working hard on solving a programming challenge! Now, one thing about your coding style… It is hard to follow your code because of your indentation style. Whenever you use a IF, FOR or WHILE clause, you should indent everything inside the clause. This makes it easier to see what is happening inside the loop. So, a simple WHILE would be like this:
While(something) {
Code…
Code…
}

And, you can see it jump out at you while reading it… Currently you indent at new routines, but, not at the important ones, so hard to see where the error is…

Let’s look at it reformatted a bit…
[php]
// send newsletter
if(isset($_GET[‘process’]) && $_GET[‘process’] == “send”) {
// email template id
$id = $_GET[‘id’];
echo "Got Email ID ".$id;

	// get subscribers
	$subscribers = mysqli_query($con,"SELECT email, firstname, lastname FROM tblnewsletter") or die(mysql_error());
	echo "<br>Connected to DB<br>";

	while($row = mysqli_fetch_array($subscribers)) {
		$recipent = $row['email'];
		$recipent_name = $row['firstname']." ".$row['lastname'];
		echo "Connected to TBLNEWSLETTER<br>";

		// get email template
		$template = mysqli_query($con,"SELECT * FROM tblnewslettermailings WHERE id='".$id."'") or die(mysql_error());
		while($temp = mysqli_fetch_array($template)) {
			$data = array();
			$name = $temp['name'];
			$subject = $temp['subject'];
			$body = $temp['body'];
			echo "Connected to Getting Emails<br>";
			array_push($data, $row["email"]);
			foreach($data as $emails){
				// actually send email
				$from = "Administrator <[email protected]>";
				$replyto = $from;
				$headers = 'From: ' . $from . "\r\n" . 'Reply-To: ' . $replyto . "\r\n" . 'X-Mailer: PHP/' . phpversion();
				$to = $email;
				$msgbody = 'Test';
				mail($to, $temp['subject'], $msgbody, $headers);
				echo "Message Sent to $email.<br>";	
			}
		} 
	}
}
 mysqli_close($con);

[/php]
In looked at this version, it appears your error is around the “foreach($data as $emails){” area.
You parse thru all of the templates for your emails and store email addresses from the outside WHILE.
Then, you send out mail to each of the emails you pushed into the $data array. So, each pass thru the
templates, you would be sending to all the email addresses so, it would just keep becoming a larger
number of addresses mailed to. That logic does not make sense. I think it is close, but…
Take a peek at how that section flows and see if you can fix it. If not, let us know and we will help
further. (You did say you wanted to learn and do it yourself… LOL ) Good luck, let us know…

I’ve been at it since last night, if I haven’t gotten it yet, then I’m not sure what more I can do on my own, and google doesn’t seem to be helping me at all.

As for the formatting, I’m not sure why it’s showing up like that on here, but my indentation is “proper” on my coding software. maybe there are hidden spaces my software doesn’t see or something.

I know the error is at or near the foreach, but I can’t seem to get it working properly. But it’s working. So again, I just need a push in the right direction on how to get that foreach (or an alternative) to work properly.

Well, the spacing can be because of using spaces instead of tabs or the other way around…

So, let’s walk thru your code…

Step one: Grab the subscribers from the database

Next, loop thru all of them…

           In that loop, grab all email templates using the ID argument

           (NOTE:  for each subscriber, you load and reload and reload all of the templates...   Hmmm?)

            Now, loop thru the templates... (While placing data from the prior loop into an array)

                       Finally, this inner loop takes data from the $data array which was entered in loop two
                       from data in loop one and now you loop thru that data???  Not sure what that does?

So, in looking at this “flow” of your routines, it is a bit messy. It would be a better flow if it was done more
like this: (Just general terms…)

Step one: Grab all subscribers and put into an array (already done.)

Step two: Grab all templates and put into an array

Loop thru all of the subscribers

        Loop thru all of the templates

               Send emails to using each template and subscriber...

So, I am not clear why you have all of that “array_push” code in there. I mean, you already pull all of the
subscribers and email-templates, why create another array? Does not make sense to me.

Perhaps you should list what you want the process to do so we can understand what the pushing is
all about… Not sure if this helps, but, hope so…

that was a code I found on StackOverflow. I assumed it needed to be in there with a tag i pulled from the website. But if it doesn’t thats fine. Here’s what I am trying to do:

I am passing variables like the email template id, and the “send” command through the URL. Since the only people who’ll be able to send are those with “admin” privs (so i’m not worried about security, since i already have an admin panel setup)

Anyway, the ID of the template should be selected through the query for: $template above.

That will select the template details (name, subject, body, etc), and those will be added to the mail function. Then for the email of the body, i’m going to have it include a PHP file that has the email template in HTML form with the $body tag called, so it will input the information in the $temp[‘body’] column into the body of the email.

All the research i’ve done shows it will work this way, however I’m not sure if this is the most effective way to go about this.

Well, you are almost there…

Just change the inside loop to not use that $data array.

So, basically, just reformat it a little to do it the second way without pulling and pushing data into that array.

Should work… So, try again and post your new version…

I still can not figure out how to send emails to each recipient independently. I am about to give up (lol) after coming so far. I just can’t find a way to send them out one at a time (or stagger them).

Here’s my updated code:

[php]
// send newsletter
if(isset($_GET[‘process’]) && $_GET[‘process’] == “send”) {
// email template id
$id = $_GET[‘id’];
echo "Got Email Template ID ".$id;

// get subscribers
$emails = array();
$names = array();
$subscribers = mysqli_query($con,"SELECT email, firstname, lastname FROM tblnewsletter") or die(mysql_error());
echo "<br>Connected to DB<br>";
while($row = mysqli_fetch_array($subscribers)) {
$emails[] = $row['email'];
$names[] = $row['firstname']." ".$row['lastname'];
}	
echo implode($emails);
// get email template
$template = mysqli_query($con,"SELECT * FROM tblnewslettermailings WHERE id=".$id." LIMIT 1") or die(mysql_error());
while($temp = mysqli_fetch_array($template)) {
$name = $temp['name'];
$subject = $temp['subject'];
$body = $temp['body'];	
echo "Got Template<br>";
}
		

	// actually send email
	$from = "Administrator <[email protected]>";
	$replyto = $from;
	$headers = 'From: ' . $from . "\r\n" . 'Reply-To: ' . $replyto . "\r\n" . 
		'X-Mailer: PHP/' . phpversion();
	$headers .= "MIME-Version: 1.0" . "\r\n";
	$headers .= "Content-type:text/html;charset=UTF-8" . "\r\n";
	$to = implode($emails, ', ');
	$msgbody = 'HEADER<br>'.nl2br($body).'<br>FOOTER';				
		
	mail($to, $subject, $msgbody, $headers);
	echo "Message Sent to ".implode($emails, ', ')."<br>";

}
mysqli_close($con);
[/php]

I am able to pass the body of the email, and the name of one person to the template I created, but it will just send multiple copies to the first person in the database table (the lowest id). At this point I have no idea what to do, or how to change any of this (most of this is way over my head and this is the first time i’ve attempted something this in-depth). I’m seriously about to give up. I’m willing to take any help I can get at this point since I can see the horizon of competition, but I just cant get up the last hill…that crafty son of a…

Okay, you are very close to the finish…

First, let’s make a few minor changes and explain how data from the database is used.
(You wanted to learn, so…)

The section where you pull your subscribers and place the data into arrays to use is really
a waste of processing time. Since the QUERY to the database places all of the data into one
array already and then you want to use that list as your major loop, it really makes no sense
to place them into another two arrays. So, let’s drop those and make the subscriber list your
outside-major loop. So, this:

while($row = mysqli_fetch_array($subscribers)) {
$emails[] = $row[‘email’];
$names[] = $row[‘firstname’]." ".$row[‘lastname’];
}
echo implode($emails);

Would just be the first line only. We will loop thru all of the subscribers and just use the info
where we need it inside the rest of the code. ( The ending brace } would be moved to the bottom. )

As far as how to stuff names into email templates, that can be tricky. There are two ways to handle it.
You can hard code your “salutation” in this procedure by just echo’ing out " Dear " . $row[“name”]; " or
something similar and then actually place the rest of the email after it. Or you can ENCODE your name
inside the template and replace it with the data as needed. to do this, you would place a code such as
" " inside the email template. Then, you would use a string-replace command to
swap that code with the real name. Which way is best. Well, if you have the name used in different
places inside the email template, then the second was is best. If it always is in the same place and
not important, the first way is faster and easier. In the code below I will use the first version.

So, the process is, again, simple. We will just parse thru all of your subscribers which are loaded into
an array by the QUERY. Next, I think I was confused about the number of email templates. In your
first posts, you mentioned many emails with the ID number. Now you are talking about only one of
them. So, I will assume you have one email template to send out to each subscriber. So, that is easy.
We only need one loop then, the subscriber loop. Less code…

Here is a new version for you to test. Note it is smaller than the last one. Sorry for the spacing, it does
seem we are using different editors and I have to redo the indents each time… Anyway, check this one
out and let us know the results…

Note that I took out the extra displays and added some comments. Also, you send one email at a time
not one large email with multiple email addresses. This way, it gets past the spam filters on servers.
[php]
// Send newsletter
if(isset($_GET[‘process’]) && $_GET[‘process’] == “send”) {

	// Get email template id and get it from database
	$id = $_GET['id'];
	$template = mysqli_query($con,"SELECT * FROM tblnewslettermailings WHERE id=".$id." LIMIT 1") or die(mysql_error());
	$temp = mysqli_fetch_array($template);
	$name = $temp['name'];
	$subject = $temp['subject'];
	$body = $temp['body'];
	
    //  Get subscribers
	$subscribers = mysqli_query($con,"SELECT email, firstname, lastname FROM tblnewsletter") or die(mysql_error());

	//  Set up the parameters that do not change for the email...
	$from = "Administrator <[email protected]>";
	$headers = 'From: ' . $from . "\r\n" . 'Reply-To: ' . $from . "\r\n" . 'X-Mailer: PHP/' . phpversion();
	$headers .= "MIME-Version: 1.0" . "\r\n";
	$headers .= "Content-type:text/html;charset=UTF-8" . "\r\n";

	//  Loop thru all subscribers sending the email
	while($row = mysqli_fetch_array($subscribers)) {
   		$to = $row['email'];
   		$msgbody = 'Dear ' . $row['firstname'] . " " . $row['lastname'] . ",<br />' . nl2br($body) . '<br />';
		mail($to, $subject, $msgbody, $headers);
		echo "Message Sent to ".$to."<br />";
    }
 
 	mysqli_close($con);
}

[/php]
Note also that I moved a lot of the emails set up code to before the loop. No need to keep repeating
that part over and over for all of the subscribers. Just do it once.

Let us know how this version works for you. Should be done… Unless you wanted to move the name
of the subscriber inside your email. Like if you wanted to use a like like this one:
Dear John… … Do not forget, John, that… …
In other words if you have a need to embed the name in more than one place in the letter…
(Another project maybe… Along with converting to an HTML email with graphics and borders, etc…)

I’ve commented out my existing code, and added the one you posted, and got this error

Parse error: syntax error, unexpected 'Message' (T_STRING) in FILENAME on line 66

On line 66 is:

echo "Message Sent to ".$to."<br />";

When I remove that line, I get this error:

Parse error: syntax error, unexpected end of file in FILE on line 70

Line 70 is “?>”

Thank you for rewriting it. I’ll note this style in the future and start implementing it into my coding style.

Well, I do not see anything wrong with that line. Therefore, it must be one of the parms given to the
“mail” function.

To debug that, you need to place this line JUST BEFORE the mail command.
So, change this line: mail($to, $subject, $msgbody, $headers);

To this version and see which parm is bad!
[php]
echo "
to: " . $to . "
subject: " . $subject . "
body: " . $msgbody . “
headers:” . $headers . “
”;
die("Verify the above data is correctly formatted!);
mail($to, $subject, $msgbody, $headers);
[/php]
This will display the first email’s data and you can check and see which is giving you an error.
My guess is that you have some invalid data inside one of them. Let us know…
We are close to your solution…

I get a completely white screen (display errors is enabled). So I’m not sure what would be causing this now.

Well, that is telling us that one of your parms is bad. So, you need to test each one at a time.

First, try:

die("to: " . $to);

Look at that and it should be the first email address. If okay, try this one:

die("subject: " . $subject);

etc… FInd the one that is bad and we will fix it…

Even adding those in there. I’m still getting a white screen, regardless of what I change or comment out, here’s the code to confirm I’ve done as you said:

[php]// Send newsletter
if(isset($_GET[‘process’]) && $_GET[‘process’] == “send”) {

  	// Get email template id and get it from database
  	$id = $_GET['id'];
	$template = mysqli_query($con,"SELECT * FROM tblnewslettermailings WHERE id=".$id." LIMIT 1") or die(mysql_error());
  	$temp = mysqli_fetch_array($template);
  	$name = $temp['name'];
 	$subject = $temp['subject'];
 	$body = $temp['body'];
	
     //  Get subscribers
 	$subscribers = mysqli_query($con,"SELECT * FROM tblnewsletter") or die(mysql_error());

	//  Set up the parameters that do not change for the email...
		$from = "Administrator <[email protected]>";
		$headers = 'From: ' . $from . "\r\n" . 'Reply-To: ' . $from . "\r\n" . 'X-Mailer: PHP/' . phpversion();
		$headers .= "MIME-Version: 1.0" . "\r\n";
		$headers .= "Content-type:text/html;charset=UTF-8" . "\r\n";

	//  Loop thru all subscribers sending the email
 	while($row = mysqli_fetch_array($subscribers)) {
   		$to = $row['email'];
   		$msgbody = 'Dear ' . $row['firstname'] . " " . $row['lastname'] . ",<br />' . nl2br($body) . '<br />';
		echo "<br>to: " . $to . "<br>subject: " . $subject . "<br>body: " . $msgbody . "<br>headers:" . $headers . "<br>";
		die("<br>to: " .$to);
		die("<br>subject: " . $subject);
		die("<br>body: " . $msgbody);
		die("<br>headers:" . $headers . "<br>");
	    die("Verify the above data is correctly formatted!);
	    mail($to, $subject, $msgbody, $headers);
     }
  
  	mysqli_close($con);
 }[/php]

LOL, found it… You use single quotes, I use double quotes…

In the line #25 in the last post where it is $msgbody=…

After lastname, there is a
. ",
’ . it should be . “,
” . SORRY! I think me-bad!

That must have been it, and my errors (lol).

It’s resolved and it’s finished, thank you very much for your time, energy and knowledge. much appreciated.

CONGRATS ! Glad you got it working… I will mark this one solved!

CYA in the bitstream… Well, CYA when you post the next problem… LOL

Sponsor our Newsletter | Privacy Policy | Terms of Service