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"> ', $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"> ', $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 Notification email ').'<input type="radio" name="notify" value="yes"></td><td>'.$GLOBALS['I18N']->get('Make confirmed immediately').' <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 "two attributes", 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').' <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"]." <".$importuser["email"]."><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