Scheduling emails with data from MySQL database or text file - php

I am creating a service where users submit data that is stored in a MySQL database or text file and emailed to a specific address at a certain time each week.
I understand that this is not what PHP is for and I've read of something called Cron that does the job, but I was wondering if there are any other options? Is there a script that could send from Gmail perhaps with the data pasted or attached?

I can only think in two ways to do it:
Having a cron job to call your send script every x minutes
$database->query("SELECT * FROM `mail_queue` WHERE `time` < " . time());
while($object = $res->fetch_object()){
mail($object->to, $object->subject, $object->message, "FROM: xpto#domain.com");
}
(If you're using a webhosting account you can simply create it on the control panel)
* * * * * /bin/php complete_path_to_your_php_script.php
Having a script running in a loop (not reliable as it can stop working due to a timeout, error, memory outage, ...)

The best way is to use Cron jobs. If for some reasons you are not able to use them then you can use services of thecloudblocks.com which allows you to schedulejobs.
Alternatively, you can create a function to sleep untill the time for the job comes. Like,
function do_some_job_at($time){
time_sleep_until($time);
JOB();
}
do_some_job_at(time() + 20); //Runs job after 20 seconds.

If you need the php script to be running at all times then I would suggest using upstart jobs / services

Related

To send a message with a delay in PHP (without "sleep" function)

Trying to make a dice-roll function in my telegram bot.
How it works right now:
When a user sends "roll" bot replies with sendDice method and sends another message with result like "you rolled 5, you won and blah-blah .."
> how it looks <
The problem is — the second message should not appear instantly, ideally after dice-roll animation is finished.
My first and obvious try on that was to add "sleep(3)" before sending the second message, and it worked fine, until I realized it completely delays the execution of my script for those 3 seconds. (if two users rolled at the same time, one of the users has to wait until another guy's roll will be finished). So it's not cool
What can I use? :c
The easiest option is to add the "task" to the "queue". The queue can be a table in the database with timestamps and chat id, when and to whom to send a message. Start another process, for example, which is started by cron, and it works for one minute. During that minute, he goes to the database and checks to see if there is something that needs to be sent now.
Crontab config
Open crontab
sudo crontab -e
Add next string
* * * * * php /path/to/cron.php >> /path/to/log/file/for/debug.log 2>&1
Cron run your script every 1 minute.
Cron.php "live" 60 second
cron.php:
$now = time();
$expectedTime = $now + 60;
while (true) {
Worker::run();
if ($expectedTime < time()) {
die(0);
}
}
Where Worker::run() your method, which get records from db, check timestamp and send message
From Wikipedia:
In computing, [..] fork is an operation whereby a process creates a
copy of itself.
When your PHP script runs, you can create multiple processes that interact with each other. Those processes run concurrently and asynchronous. This way you can have one process waiting to send the message, while the rest of the script continues to run.
Instead of starting another process, you could also start another thread. The technical difference between the two is explained here:
Forking vs Threading
PHP offers Process Control Extensions for both forking and threading. You might want to check out the example in the PHP documentation for pcntl_fork().
Depending on your needs, you might want to use a framework designed to handle concurrency throughout your application. If that is the case, I would recommend amphp.

Update database every hour without cronjob

Alright, So users in my game have an hourly income. Each hour I have a cronjob run to check and see if it's time for them to be payed. It works and all, But I want to stop using cronjobs as much. Here's the coding. The coding works and I've done things without a cronjob before by using a timestamp and calculate if it's ready for the user to be able to do the function, but they have to be logged in for that. If the users not logged in for a day or so would still like them to get their hourly income each hour without cronjob.
Here's the coding:
<?php
$result = mysql_query("SELECT * FROM users ORDER BY id");
while($row = mysql_fetch_array($result)) {
$total_pay = $row['income'] - $row['upkeep'];
$timestamp_hour = time() + 3600;
$inactive_time = strtotime('+1 week',$row['last_login']);
if(time() > $inactive_time) {
$income_add = '';
echo '<div style="color: red;">'.$row['username'].' | <i>Inactive</i></div>';
}
elseif(time() < $inactive_time) {
$income_add = mysql_query("UPDATE users SET cash=(cash+".$total_pay."),energy=(energy+".$e_income.") WHERE id=".$row['id']."");
$update_time = mysql_query("UPDATE users SET payment=".$timestamp_hour." WHERE id=".$row['id']."");
echo '<div style="color: green;">'.$row['username'].' | <i>Active</i></div>';
$res = $income_add & $update_time;
}
}
?>
Would their be a way to do so without a cronjob?
Since everyone in the comments are saying the same thing - I would like to put in the same input with as much details as possible as to why you should leave it as a cron job.
1) Without a cron job or job that runs infinite with a sleep (which in essence is a cron job by itself) there is no PHP being done UNLESS you drive enough traffic that your script gets activated by a user visit (ie check if last run was more than current time, then activate)
2) the sole purpose of a cron job is to activate a set script on the clock X amount of determined time...
3) if you write your cron job effecive enough with enough fail safe you can have it small on ressources such as:
a) dont overload memory with large arrays
b) dont pull large amount of data and let it lock your table.
c) make your cron job select specific amount of data and terminates with it...if there is left over the cron job will activate itself and continue to do work until it catches up. Once caught up it will terminate quick and easy.
4) you have mentioned that people are paid at different times - the cron job shouldnt restrict that - it is up to your code and models to effectively check those time vs time now checks in order to update, so that the cron can do work when it is needed or sleep when it is not suppose to , as an example i can make a cron wake up every 5 mins but inside the code it can check current time vs last run time (via a select or last written log) and check if it should run or not. So with that you shouldn't believe that having a cron run on the clock will prevent different circumstances of your code to activate.
You can run this without a cron job on your server by using a monitoring service. Follow these steps:
Place your php script somewhere in your web path.
Open a free site monitoring account at http://www.montastic.com/
Point the site checker to the script's URL: www.YourSite.com/yourscript.php
Set the monitoring interval to 1 hour.
Enjoy!

how to trigger email sending automatically from the database

Hello I'm battling with some problem here. I have a message in my mysql database that I want to send based on the scheduled date is there any way to do this : that when is the exact date the server should send the maill by itself, OR is there anyway to make a page load itself everyday without my access to send the email(if no one visit the site). Thanks. I'm using php and mysql db. I have scheduleddate column in my database
You could use a cron job to call a script which checks the database at a set interval (perhaps once per hour) and then have that script pull out the relevant messages and sends them.
The cron for that would look something like:
0 * * * * /path/to/email/script.php
This script could then query the database and send those messages which need sending. Of course you could set this to run every single minute (* * * * *), but I'd be very wary of having any script run every single minute!
This isn't really ideal thought, and instead you should look at using some form of queue management. If you take a look at queues.io you can find lots of info on various popular queue projects projects.
I also found this post on setting up background jobs using resque very helpful!
Of course how you integrate such a system is very much dependent on your codebase and your environment.
Some frameworks have this kinda functionality integrated very well, I have worked with Laravel 4's queue component quite a lot and it really does make it very easy to work with..
In reality many people just end up using a cron/script combo to do the job, but it's important to know there are other (better) ways to achieve this.
The best way to do this without killing your CPU utilization is by scheduling it via a scheduled cron task on your server. Write your code to send the email, then add that page to a daily cron in your server's Admin Control Panel.

PHP run script after few hours

I have a website in PHP and users can schedule message to be sent. I can sent message with command similar to this one:
php sendMsg.php 249
where number is ID of the message
Many people suggested to use cron jobs, but since I don't want to run this in interval cron is no option(only once - for example after 3 hours).
My idea was as follows:
$seconds = $hours*60*60;
exec('sleep '.$seconds.'; php sendMsg.php 249');
But this wont work because it will block php for further executing. What is the simplest way to achieve this?
You said you don't want to use a cron job because you only want the message sent once, but this is mis-understanding the way that a cron job would be written for this kind of task
Consider a situation where you have many users creating many messages to be sent at various given points in time.
You don't want to have a PHP program sitting running on your server all that time for each of those messages; it would be wasteful of server resources, even if they were all just sleep()ing for the duration.
Instead, one would use a cron job to run a short-lived PHP program once every minute (or whatever interval suits you).
Your message creation program would not be written to acually send the message; instead it would insert it into a database, along with the time it needs to be sent.
Meanwhile, the cronjob PHP program would scan this database every minute to see if there are any messages that are due to send but have not yet been sent. It would then send those messages and mark them as 'sent' on the DB.
This is the standard way to write this kind of thing, so it's not surprising that people are recommending it to you.
Doing it this way means that you never have a program running on your system for longer than necessary. Both PHP programs do their job quickly and exit, meaning that no-one is kept waiting for them.
It also makes it much more robust. Imagine if your server had to be rebooted. If you had a bunch of PHP programs running for hours waiting for their moment to send their message, they'd all be lost. On the other hand, if they had saved their message to a DB, the cron job would find them and send them correctly once the server was restarted.
Put the schedule in a database. Run a cronjob every minute or so, check the database if a message should be sent within this minute, and send it.
Is there a reason you don't want to use a cron job? That would be the simplest and most efficient way of sending the messages.
I would think that a cronjob ist still the right way
Create a table where the to be send messages are stored, with a timestamp when to be send and a flag for isSend
Create a cronjob - start php skript every 1 minute , which sends the messages with timestamp < current time and isSend = false
Ignore suggestions of cron, if you want to simply wait a period of time then use the at scheduler:
$hours = 2;
$command = sprintf('echo "php sendMsg.php 249" | at now + %d hours', $hours);
exec($command);

Schedule PHP script execution dynamically

I think Cron may be the best answer for this, but the task seems daunting and I know so little about cron, it's probably best that I ask first.
I am writing an API for an iPhone application that schedules shared tasks in a group. This will require sending push notifications at various times. Here is one example:
Person A assigns a task for Person B to complete in n days. This task is added, Person B is notified that the task has been assigned and after n-1 days a reminder notification is sent, if the task was not completed after n days, another notification is sent alerting Person B that they failed to complete the task.
My assumption here is that the process would go something like this:
When the task is initially assigned and the task is added to the DB, a cron scheduling script would be called which would schedule 2 cron jobs - 1 to fire the reminder notification, and one to fire the failure notification.
When the task is completed, it calls another script which either marks the task as completed in the DB (or removes it), and un-schedules the cron jobs.
Am I way off base here, or is this the easiest way to take this on? If it is - are there any PHP classes to make dynamically scheduling (and un-scheduling) cron jobs easier?
You could have a cron job that fires once every day.
This loops through data in the database, if a reminder needs to be sent (e.g. n-1 days is today, send the notification).
If that date has passed and it isn't complete, then it can send the failure notification.
If the task is complete, then you can change the database in that cron task, or a seperate one that fires more often.
Hopefully that helps.
My advise would be: determine what the fastest response needed would be (every minute, every 10 minutes, every hour etc.) and run a cron script in that time frame.
The script itself could be PHP, en when the script runs it figures out what to do, what actions are needed etc.
I worked on a mailing queue recently, and I implemented it as follows:
There is a one cron job that fires every minute a script, that check if database contains any e-mails in the queue. If they are found, script sends them out.
There is another cron job, that fire every day which adds scheduled e-mails to database (with a specified time, when to send it out).
So, there is a daily cron job that generates jobs to be processed at various times, and there is another one which runs constantly and processes jobs in queue.
It's easy to add some priority mechanisms too.
Your host will likely offer a cron capability in your hosting control panel. The few times I have used it, I have found that it is a case of putting in the file that you want to run's path on the server then from a couple of drop downs select the frequency. From there you are off..
As for the solution you could have AS A VERY SIMPLE EXAMPLE...
cron.php
<?php
/*
Steps
1 - Set any completed tasks to done
2 - Check if users need to be notified and send the notifications
*/
function send_notifications($email,$time_ends){
// insert code here to deal with sending the notification to the iphone
}
include("db.php"); // contains your MySQL connection vars or whatnot
// STEP 1 - Set any completed tasks to done
$update_db = mysql_query("UPDATE Notifications SET complete = '1' WHERE time_completed > '0000-00-00 00:00:00'");
// STEP 2 - Send any outstanding notifications out
$result = mysql_query("SELECT * FROM Notifications WHERE time_completed = '0000-00-00 00:00:00'"); // add another where clause to prevent bombarding with notifications for example " AND notification_2_days = '0'"
while($row = mysql_fetch_array($result))
{
send_notifications($row['email'],$row['time_ends']);
// insert an update query here to flag as a notification sent, you dont want to bombard
}
?>
WARNING - This is using depreciated connection code for simplicity (look up MySQL PDO etc) and this lacks any kind of security.
cron is great for scripts run on a regular basis, but if you want a one-off (or two-off) script to run at a particular time you would use the unix 'at' command, and you can do it directly from php using code like this:
/****
* Schedule a command using the AT command
*
* To do this you need to ensure that the www-data user is allowed to
* use the 'at' command - check this in /etc/at.deny
*
*
* EXAMPLE USAGE ::
*
* scriptat( '/usr/bin/command-to-execute', 'time-to-run');
* The time-to-run shoud be in this format: strftime("%Y%m%d%H%M", $unixtime)
*
**/
function scriptat( $cmd = null, $time = null ) {
// Both parameters are required
if (!$cmd) {
error_log("******* ScriptAt: cmd not specified");
return false;
}
if (!$time) {
error_log("******* ScriptAt: time not specified");
return false;
}
// We need to locate php (executable)
if (!file_exists("/usr/bin/php")) {
error_log("~ ScriptAt: Could not locate /usr/bin/php");
return false;
}
$fullcmd = "/usr/bin/php -f $cmd";
$r = popen("/usr/bin/at $time", "w");
if (!$r) {
error_log("~ ScriptAt: unable to open pipe for AT command");
return false;
}
fwrite($r, $fullcmd);
pclose($r);
error_log("~ ScriptAt: cmd=${cmd} time=${time}");
return true;
}

Categories