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 "&rsquo;" which is not replaced by html_decode
94    $message = preg_replace('/&rsquo;/', "'", $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&amp;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