I know I’ve been promising these for a while, but here are the three PHP scripts that make up my PHP -> Email integration. I’m still working on converting this to a full multi-user system. You can see I already started with the conversion on the schedule dispatch email. Full scripts after the jump!
Schedule Sending
This script sends out an email to you with your full upcoming schedule.
[php]<?php
mysql_connect(‘{SQL SERVER}’,’[SQL USER}','{SQL PASSWORD}');
@mysql_select_db('rtm_memory') or die( "Unable to select database");
$sql = "select * from users where active = 1;";
$users = mysql_query($sql);
while($user = mysql_fetch_array($users)) {
//what's the current hour?
$curHour = date(G);
$userID = $user['id'];
$sql = "select * from hours where userID = ‘$userID’ and hour = ‘$curHour’;";
$hours = mysql_query($sql);
$hourc = mysql_num_rows($hours);
if ($hourc == 0){
exit;
}
//First, get the list of incomplete tasks, this list is sorted in reverse chronoligical order by due date. (The higher an item’s value in the array, the sooner it needs to be done)
//I opted to get the list in JSON format for easy manipulation. It’s what I’m comfortable with. It’s also available in REST.
//This API call is static, so we can just go ahead and calculate the sign
$apiCallVars = ‘{SHARED SECRET}api_key{API KEY}auth_token’.$user['token'].’filterstatus:incompleteformatjsonfrob’.$user['frob'].’methodrtm.tasks.getList’;
$sig = md5($apiCallVars);
//And build the URI
$url = ‘http://www.rememberthemilk.com/services/rest/?api_key={API KEY}&auth_token=’.$user['token'].’&filter=status:incomplete&format=json&frob=’.$user['frob'].’&method=rtm.tasks.getList&api_sig=’.$sig;
//echo $url;
//And retrieve and decode the response
$response = file_get_contents($url);
$tasks = json_decode($response);
//Make sure the string is good, if it’s not, keep trying until it is (up to 100 tries)!
$rt = 0;
while ($tasks->rsp->stat != ‘ok’ && $rt < 100) {
$response = file_get_contents($url);
$tasks = json_decode($response);
$rt++;
}
//var_dump($tasks);
if ($tasks->rsp->stat != ‘ok’) {
//Start building our email with a failure notice
$body = "Communications error with Remember The Milk. Sorry!
";
} else {
//Start building our email with a Past Due header for the first tasks. I almost always have something past due, so I keep this there always
$body = $body . "Past Due:
————————-
";
}
//I opted to break up my list into Past Due, Upcoming, and Future events, so I need to get the current time
$now = time();
//And set the future time 1 week from now (604,800 seconds)
$future = time() + 604800;
//Have we reached current events?
$nt = 0;
//Have we reached future events? (we set nt and ft so that it doesn’t show the headers more than once)
$ft = 0;
//How many tasks are there? Find out and subtract 1 because our counting starts at 0
//Note: I indicate the use of list 1 because that’s the list that all of my tasks are in (my inbox), YMMV. If you build this
//and get errors, try switching list[$listCount] to list['0'] thoughout the script
$tc = count($tasks->rsp->tasks->list->taskseries);
$tc–;
//Process each task
while ($tc > -1) {
//Pull out the name and due date… that’s all I use on RTM… if you use more, then you can include them. Not a big problem.
$name = $tasks->rsp->tasks->list->taskseries[$tc]->name;
$date = $tasks->rsp->tasks->list->taskseries[$tc]->task->due;
//Convert the due date/time to my timezone, MST (my server is in PST), and then put it into a friendly format
$ts = strtotime($date) + 3600;
$time = date(‘D, M j g:ia’, $ts);
//Check to see if this is the first "Upcoming" or "Future" task, if so, put on the appropriate header
if ($now < $ts && $nt == 0) {
$nt = 1;
$body = $body."
Upcoming:
————————-
";
}
if ($future < $ts && $ft == 0) {
$ft = 1;
$body = $body."
Future:
————————-
";
}
//Build the string we’re going to add to the body. This is just the time string – the task name and a line break, for example
//Thu, Mar 5 3:30pm – Meet the Qwest Installer
$bodyl = $time." – ".$name."
";
//Pin this onto the body
$body = $body.$bodyl;
//Reduce the count
$tc–;
}
//I now use the unix "cal" command to generate the next 4 months in plaintext calendar format to append to the end of the message
ob_start();
$cM = date(‘m’);
$com = "cal ".$cM." 2009";
passthru($com, $cal1);
$cM++;
$com = "cal ".$cM." 2009";
passthru($com, $cal2);
$cM++;
$com = "cal ".$cM." 2009";
passthru($com, $cal3);
$cM++;
$com = "cal ".$cM." 2009";
passthru($com, $cal4);
$calData = ob_get_contents();
ob_end_clean();
//Pin that calendar data on
$body = $body."
".$calData;
//Lets also put a note at the bottom about the number of communications tries it took:
$body = $body."
RTM reached after ".$rt." retries.
This schedule sent to you courtesy of Hotchkiss Consulting (http://hotchkissconsulting.net/)";
//Output the email body
echo $body;
//Build and send the email
$to = $user['email'];
$subject = ‘My Schedule’;
$message = $body;
$headers = ‘From: rtm@hotchkissconsulting.net’ . "rn" . ‘Reply-To: rtm@hotchkissconsulting.net’ . "rn" . ‘X-Mailer: PHP/’ . phpversion();
mail($to, $subject, $message, $headers);
} ?>[/php]
Notification Sending
This script sends out a notification email to you with appointments coming up within the next 30 minutes.
[php]<?php
//Lets get ourselves a timeline
$key = md5(‘{SHARED SECRET}api_key{API KEY}auth_token{AUTH TOKEN}formatjsonfrob{FROB}methodrtm.timelines.create’);
$url = ‘http://www.rememberthemilk.com/services/rest/?api_key={API KEY}&auth_token={AUTH TOKEN}&format=json&frob={FROB}&method=rtm.timelines.create&api_sig=’.$key;
$response1 = file_get_contents($url);
$tl = json_decode($response1);
$timeline = $tl->rsp->timeline;
//And download the tasks list
//This API call is static, so we can just go ahead and calculate the sign
$sig = md5(‘{SHARED SECRET}api_key{API KEY}auth_token{AUTH TOKEN}filterstatus:incompleteformatjsonfrob{FROB}methodrtm.tasks.getList’);
//And build the URI
$url = ‘http://www.rememberthemilk.com/services/rest/?api_key={API KEY}&auth_token={AUTH TOKEN}&filter=status:incomplete&format=json&frob={FROB}&method=rtm.tasks.getList&api_sig=’.$sig;
//And retrieve and decode the response
$response = file_get_contents($url);
$tasks = json_decode($response);
//Make sure the string is good, if it’s not, keep trying until it is (up to 30 tries)!
$rt = 0;
while ($tasks->rsp->stat != ‘ok’ && $rt < 30) {
$response = file_get_contents($url);
$tasks = json_decode($response);
$rt++;
}
//Get the current time so we know whether or not to send an alert
$now = time();
//How many tasks are there? Find out and subtract 1 because our counting starts at 0
//Note: I indicate the use of list 1 because that’s the list that all of my tasks are in (my inbox), YMMV. If you build this
//and get errors, try switching list to list['0'] thoughout the script
$tc = count($tasks->rsp->tasks->list->taskseries);
$tc–;
//Set the email headers now so it doesn’t do it repeatedly through the while statement
$headers = ‘From: {FROM ADDRESS}’ . "rn" .
‘Reply-To: {FROM ADDRESS}’ . "rn" .
‘X-Mailer: PHP/’ . phpversion();
$to = ‘sam@samandbecky.net’;
//Run this for every task
while ($tc > -1) {
//Get the list ID
$lid = $tasks->rsp->tasks->list->id;
//Get the task title
$name = $tasks->rsp->tasks->list->taskseries[$tc]->name;
//get the task notes
$notes = $tasks->rsp->tasks->list->taskseries[$tc]->notes;
//Get the due date
$date = $tasks->rsp->tasks->list->taskseries[$tc]->task->due;
//Get the estimated time field which I use to see if I’ve sent a notification for this task yet
$notified = $tasks->rsp->tasks->list->taskseries[$tc]->task->estimate;
//Get the task series ID
$tsid = $tasks->rsp->tasks->list->taskseries[$tc]->id;
//Get the task ID
$tid = $tasks->rsp->tasks->list->taskseries[$tc]->task->id;
//Convert both the task time and the current time into my time zone, MST from PST and make the due date pretty
$ts = strtotime($date) + 3600;
$now = time() + 3600;
$time = date(‘D, M j g:ia’, $ts);
//Calculate the difference, in seconds, between now and when the task is due
$tt = $ts – $now;
//Build a notify string that indicates the day so that we are reminded more than once
//for recurring tasks
$notificationVal = date(‘zy’) . ‘min’;
//Notify if the task is due in fewer than 30 minutes (1,800 seconds) and a notification hasn’t already been sent.
//We also check to make sure that the task wasn’t due more than 2 hours ago. This prevents an issue with repeating
//tasks where they will notify over and over.
if ($tt < 1800 && $tt > -7200 && $notified != $notificationVal) {
//The email subject will be the task name, then a dash, then the Task ID, Task Series ID, and List ID delimited by commas
$subject = $name." – ".$tid.’.’.$tsid.’.’.$lid;
//The email body contains the due time and the notes
$message = "Due: ".$time."
Notes: ".$notes['0'];
//send the email
mail($to, $subject, $message, $headers);
//Now we’re going to make it as notification sent by setting the estimated time to complete to our notification val
//first build the sig
$toHash = ‘{SHARED SECRET}api_key{API KEY}auth_token{AUTH TOKEN}estimate’.$notificationVal.’formatjsonfrob{FROB}list_id{LIST ID}methodrtm.tasks.setEstimatetask_id’.$tid.’taskseries_id’.$tsid.’timeline’.$timeline;
$sig = md5($toHash);
//then build our query URL
$url =’http://www.rememberthemilk.com/services/rest/?api_key={API KEY}&auth_token={AUTH TOKEN}&estimate=’.$notificationVal.’&format=json&frob={FROB}&list_id={LIST ID}&method=rtm.tasks.setEstimate&task_id=’.$tid.’&taskseries_id=’.$tsid.’&timeline=’.$timeline.’&api_sig=’.$sig;
//then submit the query. Voila!
//And retrieve and decode the response
$response3 = file_get_contents($url);
$result = json_decode($response3);
//Make sure the string is good, if it’s not, keep trying until it is (up to 30 tries)!
$rt = 0;
while ($result->rsp->stat != ‘ok’ && $rt < 100) {
$response3 = file_get_contents($url);
$result = json_decode($response3);
$rt++;
}
}
//Move on to the next task
$tc–;
}
?>
[/php]
Notification Reply Processing
This script processing replies that you send to the notification message, and submits any needed changes to RTM
[php]</em>
<em><?php
//Lets get ourselves a timeline
$key = md5(‘{SHARED SECRET}api_key{API KEY}auth_token{AUTH TOKEN}formatjsonfrob{FROB}methodrtm.timelines.create’);
$url = ‘http://www.rememberthemilk.com/services/rest/?api_key={API KEY}&auth_token={AUTH TOKEN}&format=json&frob={FROB}&method=rtm.timelines.create&api_sig=’.$key;
$response1 = file_get_contents($url);
$tl = json_decode($response1);
$timeline = $tl->rsp->timeline;
//Now we’re going to check our secret RTM email account that you’ve set up with gmail
$connection = imap_open ("{imap.gmail.com:993/imap/ssl}INBOX", "{FROM ADDRESS}", "{EMAIL PASSWORD}") or die("can’t connect: " . imap_last_error());
//How many messages are there, if 0, it will just skip the while statement, close the connection, and be done.
$num_mgs = imap_num_msg($connection);
$c = 1;
while ($c <= $num_mgs) {
//Get the email subject line
$headers = imap_headerinfo($connection, $c);
$subject = $headers->subject;
//Get the first character of the email body, this is your "procCode" which will tell the script what you want to do
$body = imap_body($connection, $c);
$procCode = strtolower(substr($body,0,1));
//Out of the subject line, extract the List ID, Task Series ID, and Task ID
$lid = substr($subject, -7);
$tsid = substr($subject, -16, -8);
$tid = substr($subject, -25, -17);
//if the procCode is C, we’ll mark the task completed
if ($procCode == ‘c’) {
// Tell RTM it’s finished
//Build our hash
$toHash = ‘{SHARED SECRET}api_key{API KEY}auth_token{AUTH TOKEN}estimate1minformatjsonfrob{FROB}list_id’.$lid.’methodrtm.tasks.completetask_id’.$tid.’taskseries_id’.$tsid.’timeline’.$timeline;
$sig = md5($toHash);
//Build our URL
$url =’http://www.rememberthemilk.com/services/rest/?api_key={API KEY}&auth_token={AUTH TOKEN}&estimate=1min&format=json&frob={FROB}&list_id={LIST ID}&method=rtm.tasks.complete&task_id=’.$tid.’&taskseries_id=’.$tsid.’&timeline=’.$timeline.’&api_sig=’.$sig;
//Submit it and check the response
$response3 = file_get_contents($url);
$alterResp = json_decode($response3);
//If it worked, delete the email, if not, we’ll try again next time the script runs
if ($alterResp->rsp->stat == ‘ok’) {
//Move the message to the trash if it’s successful
$move = "[Gmail]/Trash";
@imap_mail_move($connection, $c, $move);
}
}
//if the procCode is P, we’ll postpone the task
if ($procCode == ‘p’) {
// Postpone it
//Build our hash
$toHash = ‘{SHARED SECRET}api_key{API KEY}auth_token{AUTH TOKEN}estimate1minformatjsonfrob{FROB}list_id’.$lid.’methodrtm.tasks.postponetask_id’.$tid.’taskseries_id’.$tsid.’timeline’.$timeline;
$sig = md5($toHash);
//Build our URL
$url =’http://www.rememberthemilk.com/services/rest/?api_key={API KEY}&auth_token={AUTH TOKEN}&estimate=1min&format=json&frob={FROB}&list_id={LIST ID}&method=rtm.tasks.postpone&task_id=’.$tid.’&taskseries_id=’.$tsid.’&timeline=’.$timeline.’&api_sig=’.$sig;
//Submit it and check the response
$response3 = file_get_contents($url);
$alterResp = json_decode($response3);
//If it worked, delete the email, if not, we’ll try again next time the script runs
if ($alterResp->rsp->stat == ‘ok’) {
//Move the message to the trash if it’s successful
$move = "[Gmail]/Trash";
@imap_mail_move($connection, $c, $move);
}
}
//if the procCode is S, we’ll resend the schedule
if ($procCode == ‘s’) {
// Resend Schedule
include(‘sendRTMsched.php’);
$move = "[Gmail]/Trash";
@imap_mail_move($connection, $c, $move);
}
$c++;
}
imap_close($connection);
?>
[/php]
Post questions in the comments and I will be happy to help you out!
and
[...] UPDATE: Scripts are available here: http://hotchkissconsulting.net/177/remember-the-milk-email-scripts/ [...]