1<?php 2 3require_once dirname(__FILE__).'/accesscheck.php'; 4 5//####################################################################### 6// Reads mail from a test account that will recieve all sent mail. 7// Use developer_email to send all mail to one account. 8// Use test_email settings to pop this box. 9// This file shows the links from the first email foun d for a selected user. 10// The links can be use to for instance confirm the user in an automated test. 11 12// 2007 Bas Ovink - tincan ltd 13//####################################################################### 14 15//CREATE TABLE `dev-phplist`.`phplist_testemail` ( 16//`id` int( 11 ) NOT NULL AUTO_INCREMENT , 17//`date` datetime default NULL , 18//`header` text, 19//`data` blob, 20//`status` varchar( 255 ) default NULL , 21//`comment` text, 22//PRIMARY KEY ( `id` ) , 23//KEY `dateindex` ( `date` ) 24//) ENGINE = MYISAM DEFAULT CHARSET = latin1 AUTO_INCREMENT =34; 25 26if (!$GLOBALS['commandline']) { 27 ob_end_flush(); 28 if (!MANUALLY_PROCESS_testS) { 29 echo $GLOBALS['I18N']->get('This page can only be called from the commandline'); 30 31 return; 32 } 33} else { 34 ob_end_clean(); 35 echo ClineSignature(); 36 ob_start(); 37} 38 39function prepareOutput() 40{ 41 global $outputdone; 42 if (!$outputdone) { 43 $outputdone = 1; 44 45 return formStart('name="outputform" class="readtestmailOutput" ').'<textarea name="output" rows=10 cols=70></textarea></form>'; 46 } 47} 48 49$report = ''; 50//# some general functions 51function finish($flag, $message) 52{ 53 if ($flag == 'error') { 54 $subject = $GLOBALS['I18N']->get('test processing error'); 55 } elseif ($flag == 'info') { 56 $subject = $GLOBALS['I18N']->get('test Processing info'); 57 } 58 if (!TEST && $message) { 59 sendReport($subject, $message); 60 } 61 62 // try..catch 63 global $link; 64 imap_close($link); 65} 66 67function ProcessError($message) 68{ 69 output("$message"); 70 finish('error', $message); 71 exit; 72} 73 74function processTestEmails_shutdown() 75{ 76 global $report, $process_id; 77 releaseLock($process_id); 78 // $report .= "Connection status:".connection_status(); 79 finish('info', $report); 80 if (!$GLOBALS['commandline']) { 81 include_once dirname(__FILE__).'/footer.inc'; 82 } 83} 84 85function output($message, $reset = 0) 86{ 87 $infostring = '['.date('D j M Y H:i', 88 time()).'] ['.getenv('REMOTE_HOST').'] ['.getClientIP().']'; 89 //print "$infostring $message<br/>\n"; 90 $message = preg_replace("/\n/", '', $message); 91 //# contribution from http://forums.phplist.com/viewtopic.php?p=14648 92 //# in languages with accented characters replace the HTML back 93 //Replace the "’" which is not replaced by html_decode 94 $message = preg_replace('/’/', "'", $message); 95 //Decode HTML chars 96 //$message = html_entity_decode($message,ENT_QUOTES,$_SESSION['adminlanguage']['charset']); 97 $message = html_entity_decode($message, ENT_QUOTES, 'UTF-8'); 98 if ($GLOBALS['commandline']) { 99 ob_end_clean(); 100 echo strip_tags($message)."\n"; 101 ob_start(); 102 } else { 103 if ($reset) { 104 echo '<script language="Javascript" type="text/javascript"> 105 // if (document.forms[0].name == "outputform") { 106 document.outputform.output.value = ""; 107 document.outputform.output.value += "\n"; 108 // } 109 </script>' ."\n"; 110 } 111 112 echo '<script language="Javascript" type="text/javascript"> 113 // if (document.forms[0].name == "outputform") { 114 document.outputform.output.value += "' .$message.'"; 115 document.outputform.output.value += "\n"; 116 // } else 117 // document.writeln("' .$message.'"); 118 </script>' ."\n"; 119 } 120 121 flush(); 122} 123 124//function processTestEmail($link, $mailIndex, $header) { 125// global $tables; 126// $headerinfo= imap_headerinfo($link, $mailIndex); 127// $header= imap_fetchheader($link, $mailIndex); 128 129// $body= imap_body($link, $mailIndex); 130// $msgid= 0; 131// $user= 0; 132// preg_match("/X-MessageId: (.*)/i", $header, $match); 133// if (is_array($match) && isset ($match[1])) 134// $msgid= trim($match[1]); 135// if (!$msgid) { 136// # older versions use X-Message 137// preg_match("/X-Message: (.*)/i", $header, $match); 138// if (is_array($match) && isset ($match[1])) 139// $msgid= trim($match[1]); 140// } 141 142// preg_match("/X-ListMember: (.*)/i", $header, $match); 143// if (is_array($match) && isset ($match[1])) 144// $user= trim($match[1]); 145// if (!$user) { 146// # older version use X-User 147// preg_match("/X-User: (.*)/i", $header, $match); 148// if (is_array($match) && isset ($match[1])) 149// $user= trim($match[1]); 150// } 151// # some versions used the email to identify the users, some the userid and others the uniqid 152// # use backward compatible way to find user 153// if (preg_match("/.*@.*/i", $user, $match)) { 154// $userid_req= Sql_Fetch_Row_Query("select id from {$tables["user"]} where email = \"$user\""); 155// if (VERBOSE) 156// output("UID" . 157// $userid_req[0] . " MSGID" . $msgid); 158// $userid= $userid_req[0]; 159// } 160// elseif (preg_match("/^\d$/", $user)) { 161// $userid= $user; 162// if (VERBOSE) 163// output("UID" . $userid . " MSGID" . $msgid); 164// } 165// elseif ($user) { 166// $userid_req= Sql_Fetch_Row_Query("select id from {$tables["user"]} where uniqid = \"$user\""); 167// if (VERBOSE) 168// output("UID" . $userid_req[0] . " MSGID" . $msgid); 169// $userid= $userid_req[0]; 170// } else { 171// $userid= ''; 172// } 173// // Sql_Query(sprintf('insert into %s (date,header,data) 174// // values("%s","%s","%s")', 'phplist_testemail', date("Y-m-d H:i", @ strtotime($headerinfo->date)), addslashes($header), addslashes($body))); 175// // $testid= Sql_Insert_id(); 176// // if ($userid) { 177// // Sql_Query(sprintf('update %s 178// // set status = "test system message", 179// // comment = "userid %s" 180// // where id = %d', 'phplist_testemail', $userid, $testid)); 181// // } else { 182// // Sql_Query(sprintf('update %s 183// // set status = "unidentified test", 184// // comment = "not processed" 185// // where id = %d', 'phplist_testemail', $testid)); 186// // return false; 187// // } 188// dbg($userid, '$userid'); 189// return true; 190//} 191 192function openPop($server, $user, $password) 193{ 194 $port = $GLOBALS['test_mailbox_port']; 195 if (!$port) { 196 $port = '110/pop3/notls'; 197 } 198 set_time_limit(6000); 199 200 if (!TEST) { 201 $link = imap_open('{'.$server.':'.$port.'}INBOX', $user, $password, CL_EXPUNGE); 202 } else { 203 $link = imap_open('{'.$server.':'.$port.'}INBOX', $user, $password); 204 } 205 206 if (!$link) { 207 output($GLOBALS['I18N']->get('Cannot create POP3 connection to')." $server: ".imap_last_error()); 208 209 return; 210 } 211 212 return $link; 213} 214 215function openMbox($file) 216{ 217 set_time_limit(6000); 218 219 if (!TEST) { 220 $link = imap_open($file, '', '', CL_EXPUNGE); 221 } else { 222 $link = imap_open($file, '', ''); 223 } 224 if (!$link) { 225 output($GLOBALS['I18N']->get('Cannot open mailbox file').' '.imap_last_error()); 226 227 return; 228 } 229 230 return $link; 231} 232 233function findEmailForUser($link, $mailToFind, $max = 3000) 234{ 235 global $test_mailbox_purge_unprocessed, $test_mailbox_purge; 236 output(sprintf('Looking for emails to %s', $mailToFind)); 237 238 $num = imap_num_msg($link); 239 output($num.' '.$GLOBALS['I18N']->get('mails in mailbox')."\n"); 240 output($GLOBALS['I18N']->get('Please do not interrupt this process')."\n"); 241 if ($num > $max) { 242 echo $GLOBALS['I18N']->get('Processing first')." $max ".$GLOBALS['I18N']->get('tests').'<br/>'; 243 $num = $max; 244 } 245 246 $nberror = 0; 247 $found = false; 248 $mailIndex = 0; 249 while (!$found && $mailIndex++ <= $num) { //for ($x= 1; $x <= $num; $x++) 250 set_time_limit(60); 251 $header = imap_fetchheader($link, $mailIndex); 252 preg_match('/X-ListMember: (.*)/i', $header, $match); 253 254 if (is_array($match) && isset($match[1])) { 255 $match[1] = trim($match[1]); 256 $found = $mailToFind == $match[1]; 257 if (!$found) { 258 printf('<a href="?page=readtestmail&email=%s">Get (& delete) %s</a><br />', $match[1], $match[1]); 259 } 260 } 261 262 if ($found) { 263 output('Message found'); 264 if (!TEST && $test_mailbox_purge) { 265 output($GLOBALS['I18N']->get('Deleting message')." $mailIndex"); 266 imap_delete($link, $mailIndex); 267 } 268 } else { 269 if (!TEST && $test_mailbox_purge_unprocessed) { 270 output($GLOBALS['I18N']->get('Deleting message')." $mailIndex"); 271 imap_delete($link, $mailIndex); 272 } 273 } 274 flush(); 275 } 276 flush(); 277 output($GLOBALS['I18N']->get('Closing mailbox, and purging messages')); 278 if ($found) { 279 return $num; 280 } else { 281 return; 282 } 283} 284 285//############################################ 286// main 287function main() 288{ 289} 290 291if (!function_exists('imap_open')) { 292 Error($GLOBALS['I18N']->get('IMAP is not included in your PHP installation, cannot continue'). 293 '<br/>'.$GLOBALS['I18N']->get('Check out'). 294 ' <a href="http://www.php.net/manual/en/ref.imap.php">http://www.php.net/manual/en/ref.imap.php</a>'); 295 296 return; 297} 298 299flush(); 300$outputdone = 0; 301 302// lets not do this unless we do some locking first 303register_shutdown_function('processTestEmails_shutdown'); 304$abort = ignore_user_abort(1); 305$process_id = getPageLock(); 306 307if (!empty($_REQUEST['email'])) { 308 $mailToFind = $_REQUEST['email']; 309 echo prepareOutput(); 310 311 switch ($test_protocol) { 312 case 'pop': 313 $link = openPop($test_mailbox_host, $test_mailbox_user, $test_mailbox_password); 314 break; 315 case 'mbox': 316 $link = openMbox($test_mailbox); 317 break; 318 default: 319 Error($GLOBALS['I18N']->get('test_protocol not supported')); 320 321 return; 322 } 323 324 if (isset($link)) { 325 $mailIndex = findEmailForUser($link, $mailToFind); 326 if (!is_null($mailIndex)) { 327 $body = imap_body($link, $mailIndex); 328 $overview = imap_fetch_overview($link, $mailIndex); 329 printf('Subject: %s<br />', $overview[0]->subject); 330 331 preg_match_all("/<a(.*)href=[\"\'](.*)[\"\']([^>]*)>/Umis", $body, $links); 332 foreach ($links[0] as $matchindex => $fullmatch) { 333 preg_match('/p=(\w+)/', $fullmatch, $linkPages); 334 printf('<a href="%s" id=%s>Link %s: %s</a><br />', $fullmatch, $matchindex++, $matchindex, 335 $linkPages[1]); 336 } 337 338 preg_match_all('/http:\/\/\S+/', $body, $links); 339 foreach ($links[0] as $matchindex => $fullmatch) { 340 preg_match('/p=(\w+)/', $fullmatch, $linkPages); 341 printf('<a href="%s" id=%s>Link %s: %s</a><br />', $fullmatch, $matchindex++, $matchindex, 342 $linkPages[1]); 343 } 344 } 345 } 346} 347 348{ 349 echo '<form method="get">'; 350 echo ' <input name="page" value="readtestmail" type="hidden" />'; 351 echo ' <input class="submit" type="submit" name="action" value="Get email for user: " />'; 352 printf(' <input type="text" name="email" value="%s" />', $_REQUEST['email']); 353 echo '</form>'; 354} 355