php Mail sending double content - php

I am working on a massmail script which sends an e-mail to every e-mail id present in a particular database.
But there is some issue.
Like I have following database:
id email link
1 a#bc.com bc.com
2 b#cd.com cd.com
And suppose the mail content is : 'Testing this script'
The scripts sends email to a#bc.com perfectly but second time it sends the email, i.e to b#cd.com the content gets doubled.
I mean the second recipient receives an e-mail like this :
Testing this script
Testing this script
The third recipient receives an e-mail with the content repeat three times and the fourth one receives it with four times and so on.
The script grabs e-mail addresses from the email field in the database and sends e-mail to them.
My Code:
<?
include "header.php";
include "config2.php";
$subject="Massmail";
$headers .= "Content-type:text/html;charset=iso-8859-1" . "\r\n";
mysql_connect($server, $db_user, $db_pass)
or die ("Database CONNECT Error");
$resultquery = mysql_db_query($database, "select * from $table");
while ($query = mysql_fetch_array($resultquery))
{
$mailto=$query[$table_email];
$domain=$query[$table_link];
$domain2 = str_replace(array('http://','HTTP://','Http://'), '',$domain);
$handle = fopen("http://$domain2","r") or die("Unable to open link ( $domain ). <a href='javascript:history.go(-1);'>Go back</a> and please try again ");
$contents = '';
while (!feof($handle)) {
$contents .= fread($handle, 8192);
$contents = str_replace('window.location = "/abc.html"','window.location = ""',$contents);
$contents = mb_convert_encoding($contents, "HTML-ENTITIES", "auto");
}
$i = md5(uniqid(rand(), true)) . '.' . html;
$fh = fopen("/home/host/public_html/content/$i", "w");
fwrite($fh, $contents);
fclose($fh);
$filename = '/files/$i';
$message1 .= "Testing Mail Script Version 2";
mail($mailto, $subject, $message1, $headers, "-f" . 'noreply#domain.com');
echo 'Mail sent to '.$mailto.'<br>';
sleep($seconds);
}
include "footer.php";
?>
I have tried to echo the mail that has to be sent and I get this:
To: a#bc.com
Subject: Massmail
Message:
Testing mail script
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
to: b#cd.com
Subject: Massmail
Message:
Testing mail scriptTesting mail script
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Your help will be greatly appreciated. Thanks in advance

In the code line: $message1 .= "Testing Mail Script Version 2"; the period is a concatenate, so each time you loop it, you duplicate the message another time.

Agreed. Sounds like your loop is not functioning correctly? If you can't post the full code, try to post an abstraction for us to diagnose your issue.
If you cant, I would look into looping based on the number of email address you have, not some arbitrary counter. That might help you out.

Suppose this is your table. With id, email, link, message structured as:
id email message
1 a#test.com hello, how are you doing..
2 b#test.com hey, dude this is me..
3 c#test.com we are sending you this...
Now, let's assume you have 100 records. What I would do is (assuming $result is a mysql array returning all the results from mysql ex SELECT * FROM mail...)
I would try:
for($i=0; $i <= count($result); $i++){
$send = mail($result['to'], $result['subject'],
$result['message'], $result['headers']);
if(!$send){
echo 'e-mail, sending has stopped';
break;
}
else{
echo 'all e-mails are sent successfully'; }
}

Never mind, I fixed it. #Pirion's post helped me. I changed
$message1 .= "Testing Mail Script Version 2";
to
$message = "Testing Mail Script Version 2";
And everything worked perfectly. Thank You So Much Guys For Helping Me Out.

Related

Foreach function gives 503 Service Unavailable

It is 1 AM and I am struggling for 3-4 hours to see what's wrong with my script...
My database has ~400 emails. I set $ChunkSize as counter for the loop and also to count which is the next chunk to be processed.
I've set some echo() to debug
echo "This is the " . $GLOBALS["ChunkSize"] . " chunk. <br>";
It should output what chunk is processed at that time.
If I disable mail() then I don't get 503 Service Unavailable but every echo() displays at the same time, not in the order of processing.
I also found out that some emails arrive, but not to everyone. Also, if some emails are sent, that means foreach() should have processed at least one chunk, that means it should display at least one echo().
I've set break 1; so every time it breaks out of foreach() it should display the echo() with the chunk number processed by foreach() but it doesn't.
What I am doing wrong?
$connection = mysql_connect($hostname, $username, $password);
mysql_select_db($dbname, $connection);
$result = mysql_query("SHOW COLUMNS FROM `Emails`");
while($row = mysql_fetch_array($result)){
$Addresses[] = $row['Field'];}
$Subject = "Test";
$Message = "
Test
";
$Headers = array( EMPTY FOR SECURITY REASONS );
$Headers = implode( "\r\n" , $Headers );
$ChunkAddresses = 50;
$EmailChunkArray = array_chunk($Addresses, $ChunkAddresses);
$ArraySize = count ($EmailChunkArray);
$ChunkSize = 0;
ChunkLoop: {
$EmailChunkArrayLoop = $GLOBALS["EmailChunkArray"];
foreach ($EmailChunkArrayLoop[$GLOBALS["ChunkSize"]] as $ToChunkLoop) {
if ($GLOBALS["ChunkSize"] <= $GLOBALS["ArraySize"]) {
mail($ToChunkLoop,$GLOBALS["Subject"],$GLOBALS["Message"],$GLOBALS["Headers"]);
echo "This is the " . $GLOBALS["ChunkSize"] . " chunk. <br>";
} else if ($GLOBALS["ChunkSize"] == $GLOBALS["ArraySize"]){
exit();}
$GLOBALS["ChunkSize"]++;
break 1;}
}
if ($GLOBALS["ChunkSize"] != $GLOBALS["ArraySize"]){
echo "Test. <br>";
goto ChunkLoop;
} else {
echo "Finished! <br>";}
Create script that will only do one thing - send mail.
sendMail.php
<?php
// Get recipient from the argv array
$recipient = $_SERVER['argv'][1];
// Mail args
$subject = 'HELLOOOOOOO';
$message = 'BLablabla';
$headers = [...]; // optional or not
// Send it
mail($recipient, $subject, $message, $headers);
And inside of Your code where You do:
mail($ToChunkLoop,$GLOBALS["Subject"],$GLOBALS["Message"],$GLOBALS["Headers"]);
Replace with:
$recipient = escapeshellarg($ToChunkLoop);
exec("php /path/to/sendMail.php ".$recipient." > /dev/null &"); // that will call mail script and will not wait when execution will end
Feel free to adapt my code examples as You wish
P.S. this solution is for cases when You don't want to pay for normal batch mail sending, mail subscription or dedicated, vps services and have just small web hosting. (:
P.S.. it's not a brilliant solution, but done for requirements provided by question author

MySQL, PHP - retrieve data from mysql and email it temperamental

I have the following cod which basically sends a message with some user data from MySQL. Now the thing is the email in question gets sent sometimes but not if I need to resend it. Here is the code:
<?php
//including the database connection file
include("config.php");
//getting id of the data from url
$id = $_GET['id'];
//fetching data in descending order (lastest entry first)
$result = mysql_query("SELECT * FROM my_table_name Where id='$id'");
if($res = mysql_fetch_array($result)) {
$name = $res['name'];
$email = $res['email'];
$date = $res['date'];
if(empty($id)) {
echo "<font color='red'>Error: Did not send.</font><br/>";
} else {
// The message
$message = "Hi $name,\r\n\r\nThis email is to inform you that your
\r\n\r\nRegards, \r\n Me.";
$headers = 'From: no-reply#mydomain.org' . "\r\n" .
'Reply-To: no-reply#mydomain.org' . "\r\n" .
'X-Mailer: PHP/' . phpversion();
$Subject = 'Hello';
// Send
mail($email, $Subject, $message, $headers);
//display success message
echo "<font color='green'>Email sent successfully to $name.</font><br/>";
echo "<br/><a href='index.php' class='button button1 link'>Go Back to Overview</a>";
}
}
?>
Any help is greatly appreciated.
If I understood your question correctly and it was about mail function call failing sometimes:
You can add retry logic to your mail call:
$triesLeft = 5;
while ($triesLeft > 0) {
$rc = mail(...);
if ($rc === true) {
break;
}
sleep(1); // Space to improve here - see exponential backoff, for instance
$triesLeft -= 1;
}
if ($triesLeft === 0) {
// Log critical error
}
But this might and will introduce delays in your response time, and in some cases client will even get a timeout.
So usually the solution to this problem is not to send the email right away, but to quickly put it in any kind of queue (even simple db table will suffice), and then make another worker script that will send all that is unsent.
You can move this retry logic to this worker script and sleep all you want, it won't block client.
The only "downsides" to this solution is that:
You will not be able to show result of mail call to your client (which is useless anyway since it means only that is was "accepted for delivery", not actually delivered), and
You'll have a bit more moving parts and you'll have to write a bit more code. But it's either that or accepting that some of your mail calls will fail.
An outline of a solution might be:
form.php (gets called when customer submits form):
get request parameters
form email subject, body from request parameters
save email to db with status = unsent
worker.php (should be always running in an infinite loop or something like that in background on server):
get unsent email from db
try to send it, retrying if needed
if sent successfully - mark email as sent
if failed to send - mark email an failed, log critical error, mitigate manually

PHP email Piping get 'to' field

I am trying to use email piping with PHP.
I have it working except I can't get the 'To' field.
I am using the following PHP code:
#!/usr/bin/php -q
<?php
// read from stdin
$fd = fopen("php://stdin", "r");
$email = "";
while (!feof($fd))
{
$email .= fread($fd, 1024);
$to1 = explode ("\nTo: ", $email);
$to2 = explode ("\n", $to1[1]);
$to = str_replace ('>', '', str_replace('<', '', $to2[0]));
}
fclose($fd);
mail('email#example.com','From my email pipe!','"' . $to . '"');
?>
If I use a email address (for example: john#smith.com) and send a email to my email address that is forwarded to my PHP piping script (pipe.php) I want it to be able to get who the email was sent to.
For Example:
john#smith.com emails my forwarding email that goes to my PHP piping script (bob#example.com) I want it to return just the bob part only without the #example.com
What happens now is that it returns the whole email address such as "bob#example.com" and I want it to only return bob (without any talking marks).
I have tried using this:
$to = $to.split("#");
but I seem to get an error that says: split() expects at least 2 parameters.
That gets sent to the person who sent the email.
Does anyone know how to do this or know what I might be doing wrong?
This is my first time using Piping in PHP, so if I am doing something wrong please let me know.
Ended up using:
$to1 = explode ("\nTo: ", $email);
$to2 = explode ("\n", $to1[1]);
$to = str_replace ('>', '', str_replace('<', '', $to2[0]));
list($toa, $tob) = explode('#', $to);
then changed the mail to:
mail('email#example.com','From my email pipe!','"' . $toa . '"');

send email to multiple recepients

I'm trying to send an e-mail to multiple e-mail address in my database. Here is my current code. It is only working when I specify a single e-mail address, however, I need to have them query my database and send the e-mail to each e-mail address. Where am I going wrong here?
$elist = $database->getRows("SELECT * FROM `emails`");
if ($elist) {
foreach ($elist as $elist_result) {
$frm = 'rdsyh#gmail.com';
$sub = 'Weekly Work Report';
ob_start(); // start output buffering
include_once('mail_content.php');
$mail_body = ob_get_contents(); // get the contents from the buffer
ob_end_clean();
$to = $elist_result['email'];
$mailstatus = l_mail('', '', $to, $elist_result['firstname'] . ' ' . $elist_result['lastname'], $frm, 'HR', $sub, $mail_body);
}
}
if ($mailstatus == 'ok') {
echo '<center><font color=red style="font-size:14px">Message has been sent Succesfully.....!</font></center><br>';
} else {
echo $mailstatus;
}
Well, there's a lot of abstraction here that we know nothing about from your code. Things to check:
Are you certain that your database query is returning all of the results you're looking for (is $elist populated properly)?
Are you certain that the query is returning data in the format that you're trying to access it in (is $to populated properly)?
Are you certain your l_mail() function is behaving (is it possible it exit's or otherwise terminates script execution in the middle of the first pass)?
Based on what I see here, if everything else was working properly, you should successfully be sending a bunch of emails, one to each email in your list.
Now, if instead you're trying to send a single email that is sent to all of the addresses at once, then you need to group the email addresses in the for loop and then run your mail function afterwards:
<?
$tos = array();
foreach ($elist as $elist_result) {
$tos[] = $elist_result['email'];
}
$frm = 'rdsyh#gmail.com';
$sub = 'Weekly Work Report';
ob_start(); // start output buffering
include_once('mail_content.php');
$mail_body = ob_get_contents(); // get the contents from the buffer
ob_end_clean();
$to = implode(', ', $tos);
$mailstatus = l_mail('', '', $to, $elist_result['firstname'] . ' ' . $elist_result['lastname'], $frm, 'HR', $sub, $mail_body);
?>
What does l_mail() do? If its a web service, then it might have limit for mass emails.

WhileLoop through a mysql db list

Ok so long story short, I have a simple mailto function I want to apply/run for every name on a db list. Since it's not working, I removed all the mail stuff from it and to test to make sure the while loop was working with the db, did this
<?php
$connect2db = mysqli_connect('127.0.0.1','root','pass','dbnamehere');
if(!$connect2db){
die("Sorry but theres a connection to database error" . mysqli_error);
}
$sn_query = "SELECT * FROM email_list";
$sn_queryResult = mysqli_query($connect2db, $sn_query) or die("Sorry but theres a connection to database error" . mysqli_error);
$sn_rowSelect = mysqli_fetch_array($sn_queryResult);
$to = $sn_rowSelect;
?>
<br/><br/>
////lower part on page //////<br/><br/>
<?php
while($sn_rowSelect = mysqli_fetch_array($sn_queryResult) ) {
echo "hello there" . " " . $sn_rowSelect['firstname'] . " <br/>";
}
?>
Now this works, it goess through my db and prints out all my first names from the database list. In my noob brain, id think that if i remove the echo lines, and enter the appropriate mailto information, that it would loop just like before, but send mail to each name. so i did this:
<?php
$sn_query = "SELECT email FROM email_list";
$sn_queryResult = mysqli_query($connect2db, $sn_query) or die("Sorry but theres a connection to database error" . mysqli_error);
$sn_rowSelect = mysqli_fetch_array($sn_queryResult);
$to = implode(",",$sn_rowSelect);
$from = $_POST['sender'];
$subject = $_POST['subj'];
$mssg = $_POST['message'];
$headers = "MIME-Version: 1.0rn";
$headers .= "From: $from\r\n";
$mailstatus = mail($to, $subject, $mssg, $headers);
?>
<br/><br/>
//////////<br/><br/>
<?php
while($sn_rowSelect = mysqli_fetch_array($sn_queryResult) ) {
$mailstatus;
if($mailstatus) {
echo "Success";
}else{
echo "There was a problem sending the mail. Check your code and make sure that the e-mail address $to is valid\n";
}
}
?>
now this emails the first name on my list, but not the rest.
I don't get any errors so not sure what the problem is. I was going to try an if statement with num_rows but somewhere else, on StackOverflow, someone said that didn't help since the while loop took care of it by itself. (I tried it either way and it still emailed only the first name) I'm trying here but to no avail.
You have not called the mail() function inside your loop. You call it once outside. Instead try something like the following.
Assuming you have retrieved the $to address from your database query (like you did with the firstname in testing), pull it from the rowset, and use it in mail():
while($sn_rowSelect = mysqli_fetch_array($sn_queryResult) ) {
// Get the $to address:
$to = $sn_rowSelect['email'];
// Call mail() inside the loop.
$mailstatus = mail($to, $subject, $mssg, $headers);
if($mailstatus) {
echo "Success";
}else{
echo "There was a problem sending the mail. Check your code and make sure that the e-mail address $to is valid\n";
}
}
Note also, that since you call mysql_fetch_array() at the top of your script, your while loop will start with the second row. You should remove the first call to mysql_fetch_array() that occurs before the loop.
$sn_queryResult = mysqli_query($connect2db, $sn_query) or die("Sorry but theres a connection to database error" . mysqli_error);
// Don't want this...
//$sn_rowSelect = mysqli_fetch_array($sn_queryResult);

Categories