1<script language="Javascript" type="text/javascript">
2    function checkSubFolders(folder) {
3        var element = document.getElementById(folder);
4        var isset = element.checked;
5        for (var i = 0; i < document.folderlist.length; i++) {
6            var name = document.folderlist.elements[i].value;
7            if (name.indexOf(element.name) >= 0)
8                document.folderlist.elements[i].checked = isset;
9        }
10    }
11</script>
12
13<?php
14require_once dirname(__FILE__).'/accesscheck.php';
15if (!ALLOW_IMPORT) {
16    echo '<p class="information">'.$GLOBALS['I18N']->get('import is not available').'</p>';
17
18    return;
19}
20
21ob_end_flush();
22echo '<p class="button">'.$GLOBALS['I18N']->get('Import emails from IMAP folders').'</p>';
23$email_header_fields = array('to', 'from', 'cc', 'bcc', 'reply_to', 'sender', 'return_path');
24
25if ($require_login && !isSuperUser()) {
26    $access = accessLevel('import3');
27    if ($access == 'owner') {
28        $subselect = ' where owner = '.$_SESSION['logindetails']['id'];
29    } elseif ($access == 'all') {
30        $subselect = '';
31    } elseif ($access == 'none') {
32        $subselect = ' where id = 0';
33    }
34}
35
36$result = Sql_query('SELECT id,name FROM '.$tables['list']." $subselect ORDER BY listorder");
37while ($row = Sql_fetch_array($result)) {
38    $available_lists[$row['id']] = $row['name'];
39    $some = 1;
40}
41if (!$some) {
42    echo $GLOBALS['I18N']->get('No lists available').', '.PageLink2('editlist',
43            $GLOBALS['I18N']->get('Add a list'));
44}
45
46function mailBoxName($mailbox, $delimiter, $level)
47{
48    $folder_path = explode($delimiter, $mailbox);
49    if ($level > count($folder_path)) {
50        return 0;
51    } else {
52        return $folder_path[$level];
53    }
54}
55
56function mailBoxParent($mailbox, $delimiter, $level)
57{
58    $folder_path = explode($delimiter, $mailbox);
59    $parent = '';
60    for ($i = 0; $i < $level; ++$i) {
61        if ($folder_path[$i] == '') {
62            $parent .= 'INBOX';
63        } else {
64            $parent .= '.'.$folder_path[$i];
65        }
66    }
67
68    return $parent;
69}
70
71$nodesdone = array();
72
73function printTree($tree, $root, $delim)
74{
75    reset($tree);
76//  print "<hr/>ROOT: $root<br/>";
77    foreach ($tree as $node => $rec) {
78        if (!in_array($node, $GLOBALS['nodesdone'])) {
79            if (preg_match('#'.preg_quote($root).'#i', $node)) {
80                echo '<li>';
81                printf('<input type="checkbox" name="checkfolder[]" value="%s">&nbsp;', $node);
82                echo "<b>$node</b>\n";
83                printf('<input type="checkbox" name="%s" id="%s" value="1"
84          onchange="checkSubFolders(\'%s\');"> (add subfolders)', $node, $node, $node);
85                echo '</li>';
86                echo "<ul>\n";
87                foreach ($tree[$node]['children'] as $leaf) {
88                    if ($tree[$node.$delim.$leaf]) {
89                        //          print "<ul>";
90                        printTree($tree, $node.$delim.$leaf, $delim);
91                        //          print "</ul>";
92                    } else {
93                        //  print "NO $node$delim$leaf <br/>";
94                        echo '<li>';
95                        printf('<input type="checkbox" name="checkfolder[]" value="%s">&nbsp;', $node.$delim.$leaf);
96//            print "$node.$delim";
97                        echo "$leaf</li>\n";
98                    }
99                    array_push($GLOBALS['nodesdone'], $node);
100                }
101                echo '</ul>';
102            } else {
103                //     print "<li>$node</li>";
104                //      print $root ."===". $node . "<br/>";
105            }
106        } else {
107            //   print "<br/>Done: $node";
108        }
109    }
110}
111
112function fetchEmailsFromHeader($header, $folder, $fieldlist = array())
113{
114    $res = array();
115//  print "<br/>Processing $header";
116    if (!count($fieldlist)) {
117        $fieldlist = $GLOBALS['email_header_fields'];
118    }
119    ++$GLOBALS['messagecount'];
120
121//  foreach (array("to","from","cc","bcc","reply_to","sender","return_path") as $item) {
122    foreach ($fieldlist as $item) {
123        if (is_array($header->$item)) {
124            //      print "<br/><b>Values in $item<br/>";
125            foreach ($header->$item as $object) {
126                //        print "Personal: ".$object->personal."<br/>";
127//        print "Adl: ".$object->adl."<br/>";
128//        print "Mailbox: ".$object->mailbox."<br/>";
129//        print "Host: ".$object->host."<br/>";
130                //"$object->personal <".$object->mailbox.'@'.$object->host.">"
131                if (!is_array($res[strtolower($object->mailbox.'@'.$object->host)])) {
132                    $res[strtolower($object->mailbox.'@'.$object->host)] = array();
133                }
134                array_push($res[strtolower($object->mailbox.'@'.$object->host)],
135                    array(
136                        'personal' => $object->personal,
137                        'email'    => $object->mailbox.'@'.$object->host,
138                        'folder'   => $folder,
139                        'date'     => $header->udate,
140                    ));
141            }
142        }
143    }
144
145    return $res;
146}
147
148function processImapFolder($server, $user, $password, $folder, $fieldlist = array())
149{
150    $result = array();
151    //$port =  "993/imap/ssl/novalidate-cert";
152    $port = '143/imap/notls';
153    $mbox = imap_open('{'.$server.':'.$port."}$folder", $user, $password, OP_READONLY);
154    if (!$mbox) {
155        Fatal_Error($GLOBALS['I18N']->get("can't connect").': '.imap_last_error());
156
157        return 0;
158    }
159    echo $GLOBALS['I18N']->get('Processing').' '.$folder;
160    ++$GLOBALS['foldercount'];
161    $num = imap_num_msg($mbox);
162    echo '('.$num.' '.$GLOBALS['I18N']->get('messages').')';
163    for ($x = 1; $x <= $num; ++$x) {
164        set_time_limit(60);
165        $header = imap_headerinfo($mbox, $x);
166        $emails = fetchEmailsFromHeader($header, $folder, $fieldlist);
167//    $result = array_merge($result,$emails);
168        foreach ($emails as $email => $list) {
169            if (!is_array($result[$email])) {
170                $result[$email] = array();
171            }
172            foreach ($list as $key => $rec) {
173                array_push($result[$email], $rec);
174            }
175        }
176        if ($x % 25 == 0) {
177            echo $x."/$num ".$GLOBALS['I18N']->get('done').'<br/>';
178        }
179        echo "\n";
180        flush();
181    }
182
183    return $result;
184}
185
186function getImapFolders($server, $user, $password)
187{
188    //$port =  "993/imap/ssl/novalidate-cert";
189    $port = '143/imap/notls';
190    $mbox = @imap_open('{'.$server.':'.$port.'}', $user, $password, OP_HALFOPEN);
191    if (!$mbox) {
192        Fatal_Error($GLOBALS['I18N']->get("can't connect").': '.imap_last_error());
193
194        return 0;
195    }
196
197    $list = imap_getmailboxes($mbox, '{'.$server.'}', '*');
198    if (is_array($list)) {
199        return $list;
200    } else {
201        Fatal_Error($GLOBALS['I18N']->get('imap_getmailboxes failed').': '.imap_last_error()."\n");
202
203        return 0;
204    }
205    imap_close($mbox);
206}
207
208function sortbydate($a, $b)
209{
210    return $a['date'] < $b['date'];
211}
212
213function getBestVersion($emails)
214{
215    // to start with order in reverse time order
216    usort($emails, 'sortbydate');
217    foreach ($emails as $email) {
218        // now check how good the "personal" is
219        // if it is only the email repeated we do not want it
220        if (strpos($email['personal'], '@') === false) {
221            return $email;
222        }
223        // we possibly want to search for better ones, but leave it here
224//    print $email["date"] . '=>'.$email["email"]."<br/>";
225    }
226    // if we did not return anything return the latest version by date
227    return $emails[0];
228}
229
230if (!$_POST['server'] || !$_POST['user'] || !$_POST['password'] || !is_array($_POST['lists'])) {
231    echo '
232  <p class="information">' .$GLOBALS['I18N']->get('Please enter details of the IMAP account').'</p>
233  <form method="post">
234  <table class="importForm">
235  <tr><td>' .$GLOBALS['I18N']->get('Server').':</td><td><input type="text" name="server" value="" size="30"></td></tr>
236  <tr><td>' .$GLOBALS['I18N']->get('User').':</td><td><input type="text" name="user" value="" size="30"></td></tr>
237  <tr><td>' .$GLOBALS['I18N']->get('Password').':</td><td><input type="password" name="password" value="" size="30"></td></tr>
238  <tr><td colspan="2">' .$GLOBALS['I18N']->get('Select the headers fields to search').':</td></tr>
239  ';
240    foreach ($email_header_fields as $header_field) {
241        printf('
242    <tr><td>%s</td><td><input type="checkbox" name="selected_header_fields[]" value="%s"', $header_field,
243            $header_field);
244    }
245    $c = 0;
246    echo '<tr><td>';
247    if (count($available_lists) > 1) {
248        echo $GLOBALS['I18N']->get('Select the lists to add the emails to').'<br/>';
249    }
250    echo '<ul>';
251    foreach ($available_lists as $index => $name) {
252        if (count($available_lists) == 1) {
253            printf('<input type="hidden" name="lists[0]" value="%d">
254        <li>' .$GLOBALS['I18N']->get('Adding users to list').'. <b>%s</b>', $index, $name);
255        } else {
256            printf('<li><input type="checkbox" name="lists[%d]" value="%d">%s',
257                $c, $index, $name);
258            ++$c;
259        }
260    }
261
262    echo '
263  </ul></td></tr>
264<tr><td>' .$GLOBALS['I18N']->get('Mark new users as HTML').':</td><td><input type="checkbox" name="markhtml" value="yes"></td></tr>
265<tr><td colspan="2">' .$GLOBALS['I18N']->get('If you check')." '".$GLOBALS['I18N']->get('Overwrite Existing')."', ".$GLOBALS['I18N']->get('information about a user in the database will be replaced by the imported information. Users are matched by email.').'</td></tr>
266<tr><td>' .$GLOBALS['I18N']->get('Overwrite Existing').':</td><td><input type="checkbox" name="overwrite" value="yes"></td></tr>
267<tr><td colspan="2">' .$GLOBALS['I18N']->get('If you check')." '".$GLOBALS['I18N']->get('Only use complete addresses')."' ".$GLOBALS['I18N']->get('addresses that do not have a real name will be ignored. Otherwise all emails will be imported.').'</td></tr>
268<tr><td>' .$GLOBALS['I18N']->get('Only use complete addresses').':</td><td><input type="checkbox" name="onlyfull" value="yes"></td></tr>
269<tr><td colspan="2">' .$GLOBALS['I18N']->get('If you choose')." '".$GLOBALS['I18N']->get('send notification email')."' ".$GLOBALS['I18N']->get('the users you are adding will be sent the request for confirmation of subscription to which they will have to reply. This is recommended, because it will identify invalid emails.').'</td></tr>
270<tr><td>' .$GLOBALS['I18N']->get('Send&nbsp;Notification&nbsp;email&nbsp;').'<input type="radio" name="notify" value="yes"></td><td>'.$GLOBALS['I18N']->get('Make confirmed immediately').'&nbsp;<input type="radio" name="notify" value="no"></td></tr>
271<tr><td colspan="2">' .$GLOBALS['I18N']->get('There are two ways to add the names of the users,  either one attribute for the entire name or two attributes, one for first name and one for last name. If you use &quot;two attributes&quot;, the name will be split after the first space.').'
272</td></tr>
273<tr><td>' .$GLOBALS['I18N']->get('Use one attribute for name').'<input type="radio" name="nameattributes" value="one"></td><td>'.$GLOBALS['I18N']->get('Use two attributes for the name').'&nbsp;<input type="radio" name="nameattributes" value="two"></td></tr>
274<tr><td>' .$GLOBALS['I18N']->get('Attribute one').': </td><td><select name="attributeone">
275<option value="create">' .$GLOBALS['I18N']->get('Create Attribute').'</option>
276';
277    $req = Sql_Query("select * from {$tables['attribute']} where type=\"textline\"");
278    while ($att = Sql_Fetch_array($req)) {
279        printf('<option value="%d">%s</option>', $att['id'], $att['name']);
280    }
281    echo '</select></td></tr>
282  <tr><td>' .$GLOBALS['I18N']->get('Attribute two').': </td><td><select name="attributetwo">
283  <option value="create">' .$GLOBALS['I18N']->get('Create Attribute').'</option>';
284    $req = Sql_Query("select * from {$tables['attribute']} where type=\"textline\"");
285    while ($att = Sql_Fetch_array($req)) {
286        printf('<option value="%d">%s</option>', $att['id'], $att['name']);
287    }
288    echo '</select></td></tr>
289  <tr><td colspan="2"><p class="submit"><input type="submit" value="' .$GLOBALS['I18N']->get('Continue').'"></p></td></tr>
290  </table></form>
291  ';
292} elseif (!is_array($_POST['checkfolder'])) {
293    $folders = getImapFolders($server, $user, $password);
294    if (!$folders) {
295        Error($GLOBALS['I18N']->get('Cannot continue'));
296
297        return;
298    }
299
300    printf('
301  <form method="post" name="folderlist">
302  <input type="hidden" name="parsefolders" value="1">
303  ', $_POST['server'], $_POST['user'], $_POST['password']);
304    if (is_array($_POST['selected_header_fields'])) {
305        foreach ($_POST['selected_header_fields'] as $field) {
306            printf('<input type="hidden" name="selected_header_fields[]" value="%s">', $field);
307        }
308    }
309    if (is_array($_POST['lists'])) {
310        foreach ($_POST['lists'] as $key => $val) {
311            printf('<input type="hidden" name="lists[%d]" value="%s">', $key, $val);
312        }
313    }
314    foreach (array(
315                 'server',
316                 'user',
317                 'password',
318                 'markhtml',
319                 'overwrite',
320                 'onlyfull',
321                 'notify',
322                 'nameattributes',
323                 'attributeone',
324                 'attributetwo',
325             ) as $item) {
326        printf('<input type="hidden" name="%s" value="%s">', $item, $_POST[$item]);
327    }
328
329    $done = 0;
330    $level = 0;
331    $foldersdone = array();
332    $tree = array();
333    while (count($folderdone) < count($folders) && $level < 10) {
334        reset($folders);
335        asort($folders);
336        foreach ($folders as $key => $val) {
337            $delim = $val->delimiter;
338            $name = str_replace('{'.$server.'}INBOX', '', imap_utf7_decode($val->name));
339            $parent = mailBoxParent($name, $delim, $level);
340            $folder = mailBoxName($name, $delim, $level);
341            if ($folder) {
342                if (!is_array($tree[$parent])) {
343                    $tree[$parent] = array(
344                        'node'     => $parent,
345                        'children' => array(),
346                    );
347                }
348                if (!in_array($folder, $tree[$parent]['children'])) {
349                    array_push($tree[$parent]['children'], $folder);
350                }
351                //   print $parent . " ".$folder."<br/>";
352                flush();
353            } else {
354                array_push($foldersdone, $name);
355            }
356        }
357        ++$level;
358    }
359    ksort($tree);
360    echo '<ul>'.printTree($tree, 'INBOX', '.').'</ul>';
361    echo '<p class="submit"><input type="submit" value="'.$GLOBALS['I18N']->get('Process Selected Folders').'"></p></form>';
362} else {
363    $all_emails = array();
364    foreach ($_POST['checkfolder'] as $key => $folder) {
365        echo '<br/>';
366        flush();
367
368        $emails = processImapFolder($_POST['server'], $_POST['user'], $_POST['password'], $folder,
369            $_POST['selected_header_fields']);
370        if (is_array($emails)) {
371            foreach ($emails as $email => $list) {
372                if (!is_array($all_emails[$email])) {
373                    $all_emails[$email] = array();
374                }
375                //      $emaillist = array_merge($emaillist,$emails);
376                foreach ($list as $key => $rec) {
377                    array_push($all_emails[$email], $rec);
378                }
379            }
380            echo '... '.$GLOBALS['I18N']->get('ok');
381        } else {
382            echo '... '.$GLOBALS['I18N']->get('failed');
383        }
384        flush();
385    }
386    if (is_array($all_emails)) {
387        $num = count($all_emails);
388        echo '<p class="information">'.$GLOBALS['I18N']->get('Processed').':'.$GLOBALS['foldercount'].' '.$GLOBALS['I18N']->get('folders and').' '.$GLOBALS['messagecount'].' '.$GLOBALS['I18N']->get('messages').'</p>';
389        echo '<h3>'.count($all_emails).' '.$GLOBALS['I18N']->get('unique emails found').'</h3>';
390        flush();
391
392        $usetwo = 0;
393        // prepare the attributes
394        if ($_POST['nameattributes'] == 'two') {
395            $usetwo = 1;
396            if ($_POST['attributeone'] == 'create') {
397                $req = Sql_Query(sprintf('insert into %s (name,type)
398          values("First Name","textline")', $tables['attribute']));
399                $firstname_att_id = Sql_Insert_id();
400            } else {
401                $firstname_att_id = $_POST['attributeone'];
402            }
403            if ($_POST['attributetwo'] == 'create') {
404                $req = Sql_Query(sprintf('insert into %s (name,type)
405          values("Last Name","textline")', $tables['attribute']));
406                $lastname_att_id = Sql_Insert_id();
407            } else {
408                $lastname_att_id = $_POST['attributetwo'];
409            }
410        } else {
411            if ($_POST['attributeone'] == 'create') {
412                $req = Sql_Query(sprintf('insert into %s (name,type)
413          values("Name","textline")', $tables['attribute']));
414                $name_att_id = Sql_Insert_id();
415            } else {
416                $name_att_id = $_POST['attributeone'];
417            }
418        }
419
420        $x = 0;
421        $count_email_add = 0;
422        $count_exist = 0;
423        $count_list_add = 0;
424
425        foreach ($all_emails as $key => $versions) {
426            set_time_limit(60);
427            $importuser = getBestVersion($versions);
428            //     print $importuser["personal"]." &lt;".$importuser["email"]."&gt;<br/>";
429            printf('<input type="hidden" name="importemail[%s] value="%s">',
430                $importuser['email'], $importuser['personal']);
431
432            // split personal in first and last name
433            list($importuser['firstname'], $importuser['lastname']) = explode(' ', $importuser['personal'], 2);
434
435            ++$x;
436            if ($x % 25 == 0) {
437                echo $x."/$num ".$GLOBALS['I18N']->get('done').'<br/>';
438                flush();
439            }
440
441            // check for full email
442            if ($_POST['onlyfull'] != 'yes' ||
443                ($_POST['onlyfull'] == 'yes' && strpos($importuser['personal'], '@') === false) &&
444                strlen($importuser['email']) > 4
445            ) {
446                $new = 0;
447                $result = Sql_query(sprintf('SELECT id,uniqid FROM %s
448          WHERE email = "%s"', $tables['user'], $importuser['email']));
449                if (Sql_affected_rows()) {
450                    // Email exist, remember some values to add them to the lists
451                    ++$count_exist;
452                    $user = Sql_fetch_array($result);
453                    $userid = $user['id'];
454                    $uniqid = $user['uniqid'];
455                    Sql_Query(sprintf('update %s set htmlemail = %d where id = %d', $tables['user'],
456                        $_POST['markhtml'] ? '1' : '0', $userid));
457                } else {
458                    // Email does not exist
459                    $new = 1;
460
461                    $uniqid = getUniqid();
462                    $query = sprintf('INSERT INTO %s (email,entered,confirmed,uniqid,htmlemail)
463             values("%s",now(),%d,"%s",%d)',
464                        $tables['user'], $importuser['email'], $_POST['notify'] != 'yes', $uniqid,
465                        $_POST['markhtml'] ? '1' : '0');
466                    $result = Sql_query($query);
467                    $userid = Sql_insert_id();
468
469                    ++$count_email_add;
470                    $some = 1;
471                }
472
473                if ($_POST['overwrite'] == 'yes') {
474                    if ($usetwo) {
475                        Sql_query(sprintf('replace into %s (attributeid,userid,value) values(%d,%d,"%s")',
476                            $tables['user_attribute'], $firstname_att_id, $userid, $importuser['firstname']));
477                        Sql_query(sprintf('replace into %s (attributeid,userid,value) values(%d,%d,"%s")',
478                            $tables['user_attribute'], $lastname_att_id, $userid, $importuser['lastname']));
479                    } else {
480                        Sql_query(sprintf('replace into %s (attributeid,userid,value) values(%d,%d,"%s")',
481                            $tables['user_attribute'], $name_att_id, $userid, $importuser['personal']));
482                    }
483                }
484                //add this user to the lists identified
485                reset($lists);
486                $addition = 0;
487                $listoflists = '';
488                foreach ($lists as $key => $listid) {
489                    $query = 'replace INTO '.$tables['listuser']." (userid,listid,entered) values($userid,$listid,now())";
490                    $result = Sql_query($query);
491                    // if the affected rows is 2, the user was already subscribed
492                    $addition = $addition || Sql_Affected_Rows() == 1;
493                    $listoflists .= '  * '.$available_lists[$listid]."\n";
494                }
495                if ($addition) {
496                    ++$additional_emails;
497                }
498                if (!TEST && $_POST['notify'] == 'yes' && $addition) {
499                    $subscribemessage = str_replace('[LISTS]', $listoflists,
500                        getUserConfig('subscribemessage', $userid));
501                    sendMail($email, getConfig('subscribesubject'), $subscribemessage, system_messageheaders(),
502                        $envelope);
503                }
504            } // end if
505        } // end foreach
506
507        $num_lists = count($lists);
508
509        // be grammatically correct :-)
510        $displists = ($num_lists == 1) ? $GLOBALS['I18N']->get('list') : $GLOBALS['I18N']->get('lists');
511        $dispemail = ($count_email_add == 1) ? $GLOBALS['I18N']->get('new email was').' ' : $GLOBALS['I18N']->get('new emails were').' ';
512        $dispemail2 = ($additional_emails == 1) ? $GLOBALS['I18N']->get('email was').' ' : $GLOBALS['I18N']->get('emails were').' ';
513
514        if (!$some && !$additional_emails) {
515            echo '<br/>'.$GLOBALS['I18N']->get('All the emails already exist in the database and are members of the')." $displists.";
516        } else {
517            echo "$count_email_add $dispemail ".$GLOBALS['I18N']->get('succesfully imported to the database and added to')." $num_lists $displists.<br/>$additional_emails $dispemail2 ".$GLOBALS['I18N']->get('subscribed to the')." $displists";
518            if ($count_exist) {
519                echo "<br/>$count_exist ".$GLOBALS['I18N']->get('emails already existed in the database');
520            }
521            if ($invalid_email_count) {
522                echo "<br/>$invalid_email_count ".$GLOBALS['I18N']->get('Invalid Emails found.');
523                if (!$omit_invalid) {
524                    echo ' '.$GLOBALS['I18N']->get('These records were added, but the email has been made up. You can find them by doing a search on').' "Invalid Email"';
525                } else {
526                    echo ' '.$GLOBALS['I18N']->get('These records were deleted. Check your source and reimport the data. Duplicates will be identified.');
527                }
528            }
529        }
530    } else {
531        echo $GLOBALS['I18N']->get('No emails found');
532    }
533    echo '<p class="button">'.PageLink2('import', $GLOBALS['I18N']->get('Import some more emails'));
534}
535
536?>
537
538