PHP Script to send email with no timeout - php

I am using this code to send email to my list using my server.
after a while as my list of email is large, the script get timeout.
is there a solution to this problem?
other thing i don't want to overload the server. Is there a code i can add to my script to load each email with a time between each line?
here is the php script i am using
<?php
$emailaddress = file("email-list.txt"); // load from a flat file, assuming 1 email per line in the file
$emailsubject = "[title] title of my email";
$emailbody = file_get_contents("email-content.html");
$fromaddress = "my#3emailserver.com";
$i = count($emailaddress);
$z = 0;
// here we check how many email address's we have, if its is 0, then we don't start the email function
if ($i != 0)
{// start if
// Lets loop until we reach the count from email address arrar
while ($i != $z)
{// start while
// here we send the email to the varables from above, using the email array incrament
mail($emailaddress[$z], $emailsubject, $emailbody, "From: " .$fromaddress. "\nX-Mailer: PHP 4.x");
// lets echo out that the email was sent
echo $z + 1 . " out of " . $i . " emails sent. (" . $emailaddress[$z] . ")<br>";
// increment the array one, so we get a new email address from the array
++$z;
}// end while
}//end if
else
{//start else
// we echo out that no emails where found in the array and end the script
echo "Warning: No emails in array.";
}// end else
?>

use
// sleep for 10 seconds
sleep(10);
after mail fire.

By default in php.ini, max_execution_time is set to 30 seconds. (check this in your php.ini)
Use set_time_limit function to alter that time (0=NOLIMIT):
set_time_limit(0);
Or use ini_set function:
ini_set('max_execution_time', 0);

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 Mail sending double content

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.

call php function every 10mins for 1hour

got this code that should check if url is available and also give me ping:
<?php
function test ($url){
$starttime = microtime(true);
$valid = #fsockopen($url, 80, $errno, $errstr, 30);
$stoptime = microtime(true);
echo (round(($stoptime-$starttime)*1000)).' ms.';
if (!$valid) {
echo "Status - Failure";
} else {
echo "Status - Success";
}
}
test('google.com');
?>
How do i make it so this function would be called every lets say 10minues for 1hour (6times in total) ?
I would recommend you to make use of cron jobs if you are using a Unix server or Windows Task Scheduler in the case of windows.
Like this you will be able to use programmed tasks.
In the case of using cron you could do it easily like this:
*/10 * * * * php -f your_relative_or_full_path_URL/params > /dev/null
depends: do you want to do that just once?
Then you can call the function inside a loop and use sleep() after each execution of the loop.
Do you want to do it everyday? or one specific day each week/month? use a cron.
Use a simple for-loop and the sleep command:
for ($i = 0; $i < 6; $i++) { // Run the code 6 times
test($url);
sleep(10 * 60); // Sleep 10 Minutes
}
Send Email every day in a Month. I used it in daily backup mail..
<?php
ignore_user_abort(true); //if page is closed its make it live
for($i=0;$i<=30;$i++)
{
$to = "someone#exmple.com";
$subject = "Test mail $i";
$message = "Hello! This is a simple email message.";
$from = "from#example.com";
$headers = "From:" . $from;
mail($to,$subject,$message,$headers);
sleep(24*60);//send mail in every 24 hour.
}
?>

Processing incoming e-mail with PHP Script

So I'm trying to figure out how to send an email to an address for example, something#whatever.com and instead of the e-mail going to there it would be instead sent or forwarded to a script that I create to read the contents of the email and store the contents into a database. Any suggestions on how to do it in PHP?
Thanks!
Here's some code you could use to get you going:
// set user to check
$strUser = "username";
$strPassword = "password";
// open
$hMail = imap_open ("{mail.yourdomain.com:143/notls}INBOX", "$strUser", "$strPassword");
// get headers
$aHeaders = imap_headers( $hMail );
// get message count
$objMail = imap_mailboxmsginfo( $hMail );
// process messages
for( $idxMsg = 1; $idxMsg <= $objMail->Nmsgs; $idxMsg++ )
{
// get header info
$objHeader = imap_headerinfo( $hMail, $idxMsg );
// get from object array
$aFrom = $objHeader->from;
// process headers
for( $idx = 0; $idx < count($aFrom); $idx++ )
{
// get object
$objData = $aFrom[ $idx ];
// get email from
$strEmailFrom = $objData->mailbox . "#" . $objData->host;
// do some stuff here
}
// delete message
imap_delete( $hMail, $idxMsg );
}
// expunge deleted messages
imap_expunge( $hMail );
// close
imap_close( $hMail );
Two options:
1) If you have access to the shell on the recipient email server, you can set up a rule to fire a script (like via procmail or the like) whenever a new message is received.
2) You can allow the email to drop into the mailbox as normal, then write your PHP script to access the mailbox via IMAP, pull the new messages, process them, then delete them. And then run the thing by cron every few minutes.

Categories