PageRenderTime 75ms CodeModel.GetById 26ms RepoModel.GetById 1ms app.codeStats 0ms

/src/boinc/boinc/html/ops/remind.php

http://decs.googlecode.com/
PHP | 310 lines | 233 code | 22 blank | 55 comment | 36 complexity | 53655ab41a977929ba9bb00a4c0e6794 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1, LGPL-2.0
  1. #! /usr/bin/env php
  2. <?php
  3. // remind.php [--lapsed | --failed] [--show_email] [--userid ID]
  4. //
  5. // --lapsed
  6. // Send emails to lapsed user (see below)
  7. // --failed
  8. // Send emails to failed user (see below)
  9. // --userid
  10. // Send both "lapsed" and "failed" emails to the given user,
  11. // regardless of whether they are due to be sent.
  12. // The --lapsed and --failed options are ignored.
  13. // (for testing)
  14. // --show_email
  15. // Show the text that would be mailed
  16. // --explain
  17. // Show which users would be sent email and why
  18. // --send
  19. // Actually send emails (this is an option to encourage
  20. // you to do thorough testing before using it)
  21. //
  22. // This program sends "reminder" emails to
  23. // - failed users: those who
  24. // 1) were created at least $start_interval seconds ago,
  25. // 2) have zero total credit
  26. // 3) haven't been sent an email in at least $email_interval seconds.
  27. // These people typically either had a technical glitch,
  28. // or their prefs didn't allow sending them work,
  29. // or the app crashed on their host.
  30. // The email should direct them to a web page that helps
  31. // them fix the startup problem.
  32. //
  33. // Set $start_interval according to your project's delay bounds
  34. // e.g. (1 or 2 weeks).
  35. /// $email_interval should be roughly 1 month -
  36. // we don't want to bother people too often.
  37. //
  38. // - lapsed users: those who
  39. // 1) have positive total credit,
  40. // 2) haven't done a scheduler RPC within the past
  41. // $lapsed_interval seconds, and
  42. // 3) haven't been sent an email in at least $email_interval seconds.
  43. // The email should gently prod them to start running the project again.
  44. //
  45. $globals->start_interval = 14*86400;
  46. $globals->email_interval = 30*86400;
  47. $globals->lapsed_interval = 60*86400;
  48. $globals->do_failed = false;
  49. $globals->do_lapsed = false;
  50. $globals->show_email = false;
  51. $globals->send = false;
  52. $globals->explain = false;
  53. $globals->userid = 0;
  54. for ($i=1; $i<$argc; $i++) {
  55. if ($argv[$i] == "--failed") {
  56. $do_failed = true;
  57. } elseif ($argv[$i] == "--lapsed") {
  58. $do_lapsed = true;
  59. } elseif ($argv[$i] == "--show_email") {
  60. $globals->show_email = true;
  61. } elseif ($argv[$i] == "--explain") {
  62. $globals->explain = true;
  63. } elseif ($argv[$i] == "--send") {
  64. $globals->send = true;
  65. } elseif ($argv[$i] == "--userid") {
  66. $i++;
  67. $globals->userid = $argv[$i];
  68. } else {
  69. echo "unrecognized option $argv[$i]\n";
  70. echo "usage: remind.php [--failed ] [--lapsed] [--userid N] [--show_mail] [--explain] [--send]\n";
  71. exit (1);
  72. }
  73. }
  74. require_once('../project/project.inc');
  75. require_once("../inc/db.inc");
  76. require_once("../inc/email.inc");
  77. db_init();
  78. set_time_limit(0);
  79. // File names for the various mail types.
  80. // Change these here if needed.
  81. //
  82. $dir = "remind_email";
  83. $failed_html = "$dir/failed_html";
  84. $failed_text = "$dir/failed_text";
  85. $failed_subject = "$dir/failed_subject";
  86. $lapsed_html = "$dir/lapsed_html";
  87. $lapsed_text = "$dir/lapsed_text";
  88. $lapsed_subject = "$dir/lapsed_subject";
  89. // return time of last scheduler RPC from this user,
  90. // or zero if they're never done one
  91. //
  92. function last_rpc_time($user) {
  93. $x = 0;
  94. $result = mysql_query("select rpc_time from host where userid=$user->id");
  95. while ($host = mysql_fetch_object($result)) {
  96. if ($host->rpc_time > $x) $x = $host->rpc_time;
  97. }
  98. mysql_free_result($result);
  99. return $x;
  100. }
  101. function read_files(&$item) {
  102. $item['html'] = @file_get_contents($item['html_file']);
  103. if (!$item['html']) {
  104. //$x = $item['html_file'];
  105. //echo "file missing: $x\n";
  106. //exit();
  107. }
  108. $item['text'] = @file_get_contents($item['text_file']);
  109. if (!$item['text']) {
  110. $x = $item['text_file'];
  111. echo "file missing: $x\n";
  112. exit();
  113. }
  114. $item['subject'] = @file_get_contents($item['subject']);
  115. if (!$item['subject']) {
  116. $x = $item['subject'];
  117. echo "file missing: $x\n";
  118. exit();
  119. }
  120. }
  121. function read_email_files() {
  122. global $failed_html;
  123. global $failed_text;
  124. global $failed_subject;
  125. global $lapsed_html;
  126. global $lapsed_text;
  127. global $lapsed_subject;
  128. $failed['html_file'] = $failed_html;
  129. $failed['text_file'] = $failed_text;
  130. $failed['subject'] = $failed_subject;
  131. $lapsed['html_file'] = $lapsed_html;
  132. $lapsed['text_file'] = $lapsed_text;
  133. $lapsed['subject'] = $lapsed_subject;
  134. read_files($failed);
  135. read_files($lapsed);
  136. $email_files['failed'] = $failed;
  137. $email_files['lapsed'] = $lapsed;
  138. return $email_files;
  139. }
  140. function replace($user, $template) {
  141. $pat = array(
  142. '/<name\/>/',
  143. '/<create_time\/>/',
  144. '/<total_credit\/>/',
  145. '/<opt_out_url\/>/',
  146. '/<user_id\/>/',
  147. '/<lapsed_interval\/>/',
  148. );
  149. $rep = array(
  150. $user->name,
  151. gmdate('d F Y', $user->create_time),
  152. number_format($user->total_credit, 0),
  153. URL_BASE."opt_out.php?code=".salted_key($user->authenticator)."&userid=$user->id",
  154. $user->id,
  155. floor ((time() - $user->last_rpc_time) / 86400),
  156. );
  157. return preg_replace($pat, $rep, $template);
  158. }
  159. function mail_type($user, $type) {
  160. global $globals;
  161. global $email_files;
  162. $email_file = $email_files[$type];
  163. if ($email_file['html']) {
  164. $html = replace($user, $email_file['html']);
  165. } else {
  166. $html = null;
  167. }
  168. $text = replace($user, $email_file['text']);
  169. if ($globals->show_email) {
  170. echo "------- SUBJECT ----------\n";
  171. echo $email_file['subject'];
  172. echo "\n------- HTML ----------\n";
  173. echo $html;
  174. echo "\n------- TEXT ----------\n";
  175. echo $text;
  176. }
  177. if ($globals->send) {
  178. echo "sending to $user->email_addr\n";
  179. echo send_email(
  180. $user,
  181. $email_file['subject'],
  182. $text,
  183. $html
  184. );
  185. $now = time();
  186. $ntype = 0;
  187. if ($type == 'lapsed') $ntype = 2;
  188. if ($type == 'failed') $ntype = 3;
  189. $query = "insert into sent_email values($user->id, $now, $ntype)";
  190. mysql_query($query);
  191. }
  192. }
  193. function last_reminder_time($user) {
  194. $query = "select * from sent_email where userid=$user->id";
  195. $result = mysql_query($query);
  196. $t = 0;
  197. while ($r = mysql_fetch_object($result)) {
  198. if ($r->email_type !=2 && $r->email_type != 3) continue;
  199. if ($r->time_sent > $t) $t = $r->time_sent;
  200. }
  201. mysql_free_result($result);
  202. return $t;
  203. }
  204. function handle_user($user, $do_type) {
  205. global $globals;
  206. global $email_interval;
  207. if ($user->send_email == 0) {
  208. if ($globals->explain) {
  209. echo "user: $user->id send_email = 0\n";
  210. }
  211. return;
  212. }
  213. $max_email_time = time() - $email_interval;
  214. if (last_reminder_time($user) > $max_email_time) {
  215. if ($globals->explain) {
  216. echo "user: $user->id sent too recently\n";
  217. }
  218. return;
  219. }
  220. if ($globals->explain) {
  221. $x = (time() - $user->create_time)/86400;
  222. $t = last_rpc_time($user);
  223. $show_lapsed_interval = (time()-$t)/86400;
  224. echo "user $user->id ($user->email_addr) was created $x days ago\n";
  225. echo " total_credit: $user->total_credit; last RPC $show_lapsed_interval days ago\n";
  226. echo " sending $do_type email\n";
  227. }
  228. mail_type($user, $do_type);
  229. }
  230. function do_failed() {
  231. global $globals;
  232. $max_create_time = time() - $globals->start_interval;
  233. $result = mysql_query(
  234. "select * from user where send_email<>0 and create_time<$max_create_time and total_credit = 0;"
  235. );
  236. while ($user = mysql_fetch_object($result)) {
  237. handle_user($user, 'failed');
  238. }
  239. mysql_free_result($result);
  240. }
  241. function do_lapsed() {
  242. global $globals;
  243. $max_last_rpc_time = time() - $globals->lapsed_interval;
  244. // the following is an efficient way of getting the list of
  245. // users for which no host has done an RPC recently
  246. //
  247. $result = mysql_query(
  248. "select userid from host group by userid having max(rpc_time)<$max_last_rpc_time;"
  249. );
  250. while ($host = mysql_fetch_object($result)) {
  251. $uresult = mysql_query("select * from user where id = $host->userid;");
  252. $user = mysql_fetch_object($uresult);
  253. mysql_free_result($uresult);
  254. if (!$user) {
  255. echo "Can't find user $host->userid\n";
  256. continue;
  257. }
  258. handle_user($user, 'lapsed');
  259. }
  260. mysql_free_result($result);
  261. }
  262. if (!$USE_PHPMAILER) {
  263. echo "You must use PHPMailer (http://phpmailer.sourceforge.net)\n";
  264. exit();
  265. }
  266. $email_files = read_email_files();
  267. if ($globals->userid) {
  268. $user = lookup_user_id($globals->userid);
  269. if (!$user) {
  270. echo "No such user: $globals->userid\n";
  271. exit();
  272. }
  273. $user->last_rpc_time = last_rpc_time($user);
  274. mail_type($user, 'failed');
  275. mail_type($user, 'lapsed');
  276. } else {
  277. if ($do_failed) {
  278. do_failed();
  279. }
  280. if ($do_lapsed) {
  281. do_lapsed();
  282. }
  283. }
  284. ?>