/ tasks / signin_mailer.php
signin_mailer.php
  1  <?php
  2  
  3  // Link expiration time. Will be isnerted the email message.
  4  define('LINK_TTL', '24 hours');
  5  // Time after which entries will be deleted even if the email wasn't sent
  6  define('ENTRY_TTL', 3600); // in seconds
  7  // Number of emails to send per run
  8  define('BATCH_SIZE', 100);
  9  // Table name
 10  define('TBL', 'email_signins_queue');
 11  
 12  // ---
 13  
 14  echo "[" . date('r') . "] - Mailer run started\n";
 15  
 16  // Only one mailer instance can run at a time
 17  $run_lock = fopen(sys_get_temp_dir() . '/signin_mailer.lock', 'a');
 18  
 19  if (!$run_lock) {
 20    echo "Couldn't create lock file. Aborting\n";
 21    exit(-1);
 22  }
 23  
 24  if (!flock($run_lock, LOCK_EX | LOCK_NB)) {
 25    echo "Previous run hasn't finished yet. Aborting\n";
 26    exit(0);
 27  }
 28  
 29  // ---
 30  
 31  require_once 'lib/db.php';
 32  
 33  set_time_limit(60);
 34  
 35  function send_email($email, $token) {
 36    $ttl = LINK_TTL;
 37    
 38    $subject = "Email Verification Request";
 39    $message =<<<MSG
 40  Hello,
 41  
 42  We have received a request to verify this email address for use on 4chan. If you requested this verification, please go to the following URL:
 43  
 44  https://sys.4chan.org/signin?action=verify&tkn=$token
 45  
 46  This link will expire in $ttl. You can use it multiple times to authorize as many of your devices as needed.
 47  
 48  If you did NOT request to verify this email address, do not click on the link.
 49  
 50  Sincerely,
 51  
 52  Team 4chan.
 53  MSG;
 54    
 55    $headers = "From: 4chan <noreply@4chan.org>\r\n";
 56    $headers .= "MIME-Version: 1.0\r\n";
 57    $headers .= "Content-Type: text/plain; charset=UTF-8\r\n";
 58    
 59    $opts = '-f noreply@4chan.org';
 60    
 61    return mail($email, $subject, $message, $headers, $opts);
 62  }
 63  
 64  // ---
 65  
 66  // Cleanup expired entries to not keep plaintext emails for too long.
 67  $tbl = TBL;
 68  
 69  $ttl = (int)ENTRY_TTL;
 70  
 71  $sql = "DELETE FROM `$tbl` WHERE created_on <= DATE_SUB(NOW(), INTERVAL $ttl SECOND)";
 72  
 73  $res = mysql_global_call($sql);
 74  
 75  if (!$res) {
 76    echo "DB error while pruning stale entries. Aborting\n";
 77    exit(-1);
 78  }
 79  
 80  // Start sending mails
 81  $batch_size = (int)BATCH_SIZE;
 82  
 83  $sql = "SELECT id, email, token FROM `$tbl` ORDER BY id ASC LIMIT $batch_size";
 84  
 85  $res = mysql_global_call($sql);
 86  
 87  if (!$res) {
 88    echo "DB error while fetching entries. Aborting\n";
 89    exit(-1);
 90  }
 91  
 92  $sent_count = 0;
 93  $error_count = 0;
 94  
 95  while ($row = mysql_fetch_assoc($res)) {
 96    $id = (int)$row['id'];
 97    $email = $row['email'];
 98    $token = $row['token'];
 99    
100    if (!$email || !$token) {
101      $error_count++;
102      continue;
103    }
104    
105    $ret = send_email($email, $token);
106    
107    if ($ret) {
108      $sent_count++;
109      $sql = "DELETE FROM `$tbl` WHERE id = $id LIMIT 1";
110      mysql_global_call($sql);
111    }
112    else {
113      $error_count++;
114    }
115    
116    //usleep(10000); // 10ms
117  }
118  
119  // ---
120  
121  fclose($run_lock);
122  
123  echo "[" . date('r') . "] - Mailer run finished: sent $sent_count, errors $error_count\n";
124  
125  exit(0);