#! /usr/bin/env php . // remind.php [--lapsed | --failed] [--show_email] [--userid ID] // // --lapsed // Send emails to lapsed user (see below) // --failed // Send emails to failed user (see below) // --userid // Send both "lapsed" and "failed" emails to the given user, // regardless of whether they are due to be sent. // The --lapsed and --failed options are ignored. // (for testing) // --show_email // Show the text that would be mailed // --explain // Show which users would be sent email and why // --send // Actually send emails (this is an option to encourage // you to do thorough testing before using it) // --count N // By default send to all users that qualify, but if count is // set, only send to N users at a time // // This program sends "reminder" emails to // - failed users: those who // 1) were created at least $start_interval seconds ago, // 2) have zero total credit // 3) haven't been sent an email in at least $email_interval seconds. // These people typically either had a technical glitch, // or their prefs didn't allow sending them work, // or the app crashed on their host. // The email should direct them to a web page that helps // them fix the startup problem. // // Set $start_interval according to your project's delay bounds // e.g. (1 or 2 weeks). /// $email_interval should be roughly 1 month - // we don't want to bother people too often. // // - lapsed users: those who // 1) have positive total credit, // 2) haven't done a scheduler RPC within the past // $lapsed_interval seconds, and // 3) haven't been sent an email in at least $email_interval seconds. // The email should gently prod them to start running the project again. // $cli_only = true; require_once("../inc/util_ops.inc"); require_once("../inc/email.inc"); db_init(); set_time_limit(0); $globals->start_interval = 14*86400; $globals->email_interval = 200*86400; $globals->lapsed_interval = 60*86400; $globals->do_failed = false; $globals->do_lapsed = false; $globals->show_email = false; $globals->send = false; $globals->explain = false; $globals->userid = 0; $globals->count = -1; for ($i=1; $i<$argc; $i++) { if ($argv[$i] == "--failed") { $globals->do_failed = true; } elseif ($argv[$i] == "--lapsed") { $globals->do_lapsed = true; } elseif ($argv[$i] == "--show_email") { $globals->show_email = true; } elseif ($argv[$i] == "--explain") { $globals->explain = true; } elseif ($argv[$i] == "--send") { $globals->send = true; } elseif ($argv[$i] == "--userid") { $i++; $globals->userid = $argv[$i]; } elseif ($argv[$i] == "--count") { $i++; $globals->count = $argv[$i]; } else { echo "unrecognized option $argv[$i]\n"; echo "usage: remind.php [--failed ] [--lapsed] [--userid N] [--show_mail] [--explain] [--send] [--count N]\n"; exit (1); } } // File names for the various mail types. // Change these here if needed. // $dir = "remind_email"; $failed_html = "$dir/reminder_failed_html"; $failed_text = "$dir/reminder_failed_text"; $failed_subject = "$dir/reminder_failed_subject"; $lapsed_html = "$dir/reminder_lapsed_html"; $lapsed_text = "$dir/reminder_lapsed_text"; $lapsed_subject = "$dir/reminder_lapsed_subject"; // return time of last scheduler RPC from this user, // or zero if they're never done one // function last_rpc_time($user) { $x = 0; $result = _mysql_query("select rpc_time from host where userid=$user->id"); while ($host = _mysql_fetch_object($result)) { if ($host->rpc_time > $x) $x = $host->rpc_time; } _mysql_free_result($result); return $x; } function read_files(&$item) { $item['html'] = @file_get_contents($item['html_file']); if (!$item['html']) { //$x = $item['html_file']; //echo "file missing: $x\n"; //exit(); } $item['text'] = @file_get_contents($item['text_file']); if (!$item['text']) { $x = $item['text_file']; echo "file missing: $x\n"; exit(); } $item['subject'] = @file_get_contents($item['subject']); if (!$item['subject']) { $x = $item['subject']; echo "file missing: $x\n"; exit(); } } function read_email_files() { global $failed_html; global $failed_text; global $failed_subject; global $lapsed_html; global $lapsed_text; global $lapsed_subject; $failed['html_file'] = $failed_html; $failed['text_file'] = $failed_text; $failed['subject'] = $failed_subject; $lapsed['html_file'] = $lapsed_html; $lapsed['text_file'] = $lapsed_text; $lapsed['subject'] = $lapsed_subject; read_files($failed); read_files($lapsed); $email_files['failed'] = $failed; $email_files['lapsed'] = $lapsed; return $email_files; } function replace($user, $template) { $pat = array( '//', '//', '//', '//', '//', '//', '//', ); $rep = array( $user->name, $user->email_addr, gmdate('d F Y', $user->create_time), number_format($user->total_credit, 0), opt_out_url($user), $user->id, floor ((time() - last_rpc_time($user)) / 86400), ); return preg_replace($pat, $rep, $template); } function mail_type($user, $type) { global $globals; global $email_files; $email_file = $email_files[$type]; if ($email_file['html']) { $html = replace($user, $email_file['html']); } else { $html = null; } $text = replace($user, $email_file['text']); if ($globals->show_email) { echo "------- SUBJECT ----------\n"; echo $email_file['subject']; echo "\n------- HTML ----------\n"; echo $html; echo "\n------- TEXT ----------\n"; echo $text; } if ($globals->send) { echo "sending to $user->email_addr\n"; echo send_email( $user, $email_file['subject'], $text, $html ); $now = time(); $ntype = 0; if ($type == 'lapsed') $ntype = 2; if ($type == 'failed') $ntype = 3; $query = "insert into sent_email values($user->id, $now, $ntype)"; _mysql_query($query); } $globals->count--; if ($globals->count == 0) { echo "reached limit set by --count - exiting...\n"; exit(); } } function last_reminder_time($user) { $query = "select * from sent_email where userid=$user->id"; $result = _mysql_query($query); $t = 0; while ($r = _mysql_fetch_object($result)) { if ($r->email_type !=2 && $r->email_type != 3) continue; if ($r->time_sent > $t) $t = $r->time_sent; } _mysql_free_result($result); return $t; } function handle_user($user, $do_type) { global $globals; global $email_interval; if ($user->send_email == 0) { if ($globals->explain) { echo "user: $user->id send_email = 0\n"; } return; } $max_email_time = time() - $globals->email_interval; if (last_reminder_time($user) > $max_email_time) { if ($globals->explain) { echo "user: $user->id sent too recently\n"; } return; } if ($globals->explain) { $x = (time() - $user->create_time)/86400; $t = last_rpc_time($user); $show_lapsed_interval = (time()-$t)/86400; echo "user $user->id ($user->email_addr) was created $x days ago\n"; echo " total_credit: $user->total_credit; last RPC $show_lapsed_interval days ago\n"; echo " sending $do_type email\n"; } mail_type($user, $do_type); } function do_failed() { global $globals; $max_create_time = time() - $globals->start_interval; $result = _mysql_query( "select * from user where send_email<>0 and create_time<$max_create_time and total_credit = 0;" ); while ($user = _mysql_fetch_object($result)) { handle_user($user, 'failed'); } _mysql_free_result($result); } function do_lapsed() { global $globals; $max_last_rpc_time = time() - $globals->lapsed_interval; // the following is an efficient way of getting the list of // users for which no host has done an RPC recently // $result = _mysql_query( "select userid from host group by userid having max(rpc_time)<$max_last_rpc_time;" ); while ($host = _mysql_fetch_object($result)) { $uresult = _mysql_query("select * from user where id = $host->userid;"); $user = _mysql_fetch_object($uresult); _mysql_free_result($uresult); if (!$user) { echo "Can't find user $host->userid\n"; continue; } handle_user($user, 'lapsed'); } _mysql_free_result($result); } if (!function_exists('make_php_mailer')) { echo "You must use PHPMailer (http://phpmailer.sourceforge.net)\n"; exit(); } $email_files = read_email_files(); if ($globals->userid) { $user = BoincUser::lookup_id($globals->userid); if (!$user) { echo "No such user: $globals->userid\n"; exit(); } $user->last_rpc_time = last_rpc_time($user); mail_type($user, 'failed'); mail_type($user, 'lapsed'); } else { if ($globals->do_failed) { do_failed(); } if ($globals->do_lapsed) { do_lapsed(); } } ?>