6 * Copyright (c) 1999-2003 The SquirrelMail Project Team
7 * Licensed under the GNU GPL. For full terms see the file COPYING.
9 * This implements all functions that do general imap functions.
14 require_once(SM_PATH
. 'functions/page_header.php');
15 require_once(SM_PATH
. 'functions/auth.php');
18 global $sqimap_session_id;
19 $sqimap_session_id = 1;
21 /* Sets an unique session id in order to avoid simultanous sessions crash. */
22 function sqimap_session_id($unique_id = false) {
23 global $data_dir, $username, $sqimap_session_id;
25 return( sprintf("A%03d", $sqimap_session_id++
) );
27 return( sprintf("A%03d", $sqimap_session_id++
) . ' UID' );
32 * Both send a command and accept the result from the command.
33 * This is to allow proper session number handling.
35 function sqimap_run_command_list ($imap_stream, $query, $handle_errors, &$response, &$message, $unique_id = false) {
37 $sid = sqimap_session_id($unique_id);
38 fputs ($imap_stream, $sid . ' ' . $query . "\r\n");
39 $read = sqimap_read_data_list ($imap_stream, $sid, $handle_errors, $response, $message, $query );
42 global $squirrelmail_language, $color;
43 set_up_language($squirrelmail_language);
44 require_once(SM_PATH
. 'functions/display_messages.php');
45 $string = "<b><font color=$color[2]>\n" .
46 _("ERROR : No available imapstream.") .
48 error_box($string,$color);
54 function sqimap_run_command ($imap_stream, $query, $handle_errors, &$response,
55 &$message, $unique_id = false,$filter=false,
56 $outputstream=false,$no_return=false) {
58 $sid = sqimap_session_id($unique_id);
59 fputs ($imap_stream, $sid . ' ' . $query . "\r\n");
60 $read = sqimap_read_data ($imap_stream, $sid, $handle_errors, $response,
61 $message, $query,$filter,$outputstream,$no_return);
64 global $squirrelmail_language, $color;
65 set_up_language($squirrelmail_language);
66 require_once(SM_PATH
. 'functions/display_messages.php');
67 $string = "<b><font color=$color[2]>\n" .
68 _("ERROR : No available imapstream.") .
70 error_box($string,$color);
78 * custom fgets function. gets a line from IMAP
79 * no matter how big it may be
82 function sqimap_fgets($imap_stream) {
87 while (strpos($results, "\r\n", $offset) === false) {
88 if (!($read = fgets($imap_stream, $buffer))) {
89 /* this happens in case of an error */
90 /* reset $results because it's useless */
94 if ( $results != '' ) {
95 $offset = strlen($results) - 1;
102 function sqimap_fread($imap_stream,$iSize,$filter=false,
103 $outputstream=false, $no_return=false) {
104 if (!$filter ||
!$outputstream) {
105 $iBufferSize = $iSize;
107 // FIXME This doesn't work with base64 decode, Why ?
108 // The idea is to use a buffersize of 32k i.e.
109 $iBufferSize = $iSize;
111 $iRet = $iSize - $iBufferSize;
115 while (($iRetrieved < ($iSize - $iBufferSize))) {
116 $sRead = fread($imap_stream,$iBufferSize);
117 if ($sRead === false) {
121 $iRetrieved +
= $iBufferSize;
127 if (is_resource($outputstream)) {
128 fwrite($outputstream,$sRead);
129 } else if ($outputstream == 'php://stdout') {
138 if ($results !== false) {
139 $sRead = fread($imap_stream,($iSize - ($iRetrieved)));
144 if (is_resource($outputstream)) {
145 fwrite($outputstream,$sRead);
146 } else if ($outputstream == 'php://stdout') { // FIXME
161 * Reads the output from the IMAP stream. If handle_errors is set to true,
162 * this will also handle all errors that are received. If it is not set,
163 * the errors will be sent back through $response and $message
166 function sqimap_read_data_list ($imap_stream, $tag_uid, $handle_errors,
167 &$response, &$message, $query = '',
168 $filter = false, $outputstream = false, $no_return = false) {
169 global $color, $squirrelmail_language;
171 $tag_uid_a = explode(' ',trim($tag_uid));
172 $tag = $tag_uid_a[0];
173 $resultlist = array();
175 $read = sqimap_fgets($imap_stream);
183 $read = sqimap_fgets($imap_stream);
188 /* get the command */
191 $s = substr($read,$i);
192 if (($j = strpos($s,' ')) ||
($j = strpos($s,"\n"))) {
193 $arg = substr($s,0,$j);
195 $found_tag = substr($read,0,$i-1);
196 if ($arg && $found_tag==$tag) {
205 $message = trim(substr($read,$i+
strlen($arg)));
206 break 3; /* switch switch while */
208 /* this shouldn't happen */
210 $message = trim(substr($read,$i+
strlen($arg)));
211 break 3; /* switch switch while */
213 } elseif($found_tag !== $tag) {
214 /* reset data array because we do not need this reponse */
216 $read = sqimap_fgets($imap_stream);
219 } // end case $tag{0}
223 if (preg_match('/^\*\s\d+\sFETCH/',$read)) {
224 /* check for literal */
225 $s = substr($read,-3);
226 $fetch_data = array();
227 do { /* outer loop, continue until next untagged fetch
229 do { /* innerloop for fetching literals. with this loop
230 we prohibid that literal responses appear in the
231 outer loop so we can trust the untagged and
232 tagged info provided by $read */
233 if ($s === "}\r\n") {
234 $j = strrpos($read,'{');
235 $iLit = substr($read,$j+
1,-3);
236 $fetch_data[] = $read;
237 $sLiteral = sqimap_fread($imap_stream,$iLit,$filter,$outputstream,$no_return);
238 if ($sLiteral === false) { /* error */
239 break 4; /* while while switch while */
241 /* backwards compattibility */
242 $aLiteral = explode("\n", $sLiteral);
243 /* release not neaded data */
245 foreach ($aLiteral as $line) {
246 $fetch_data[] = $line ."\n";
248 /* release not neaded data */
250 /* next fgets belongs to this fetch because
251 we just got the exact literalsize and there
252 must follow data to complete the response */
253 $read = sqimap_fgets($imap_stream);
254 if ($read === false) { /* error */
255 break 4; /* while while switch while */
257 $fetch_data[] = $read;
259 $fetch_data[] = $read;
261 /* retrieve next line and check in the while
262 statements if it belongs to this fetch response */
263 $read = sqimap_fgets($imap_stream);
264 if ($read === false) { /* error */
265 break 4; /* while while switch while */
267 /* check for next untagged reponse and break */
268 if ($read{0} == '*') break 2;
269 $s = substr($read,-3);
270 } while ($s === "}\r\n");
271 $s = substr($read,-3);
272 } while ($read{0} !== '*' &&
273 substr($read,0,strlen($tag)) !== $tag);
274 $resultlist[] = $fetch_data;
275 /* release not neaded data */
278 $s = substr($read,-3);
280 if ($s === "}\r\n") {
281 $j = strrpos($read,'{');
282 $iLit = substr($read,$j+
1,-3);
284 $sLiteral = fread($imap_stream,$iLit);
285 if ($sLiteral === false) { /* error */
287 break 3; /* while switch while */
290 $fetch_data[] = sqimap_fgets($imap_stream);
294 $read = sqimap_fgets($imap_stream);
295 if ($read === false) {
296 break 3; /* while switch while */
297 } else if ($read{0} == '*') {
300 $s = substr($read,-3);
301 } while ($s === "}\r\n");
309 /* error processing in case $read is false */
310 if ($read === false) {
312 set_up_language($squirrelmail_language);
313 require_once(SM_PATH
. 'functions/display_messages.php');
314 $string = "<b><font color=$color[2]>\n" .
315 _("ERROR : Connection dropped by imap-server.") .
318 htmlspecialchars($query) . '<br>' . "</font><br>\n";
319 error_box($string,$color);
323 /* Set $resultlist array */
325 $resultlist[] = $data;
327 elseif (empty($resultlist)) {
328 $resultlist[] = array();
331 /* Return result or handle errors */
332 if ($handle_errors == false) {
333 return( $resultlist );
341 /* ignore this error from M$ exchange, it is not fatal (aka bug) */
342 if (strstr($message, 'command resulted in') === false) {
343 set_up_language($squirrelmail_language);
344 require_once(SM_PATH
. 'functions/display_messages.php');
345 $string = "<b><font color=$color[2]>\n" .
346 _("ERROR : Could not complete request.") .
349 htmlspecialchars($query) . '<br>' .
350 _("Reason Given: ") .
351 htmlspecialchars($message) . "</font><br>\n";
352 error_box($string,$color);
353 echo '</body></html>';
358 set_up_language($squirrelmail_language);
359 require_once(SM_PATH
. 'functions/display_messages.php');
360 $string = "<b><font color=$color[2]>\n" .
361 _("ERROR : Bad or malformed request.") .
364 htmlspecialchars($query) . '<br>' .
365 _("Server responded: ") .
366 htmlspecialchars($message) . "</font><br>\n";
367 error_box($string,$color);
368 echo '</body></html>';
371 set_up_language($squirrelmail_language);
372 require_once(SM_PATH
. 'functions/display_messages.php');
373 $string = "<b><font color=$color[2]>\n" .
374 _("ERROR : Imap server closed the connection.") .
377 htmlspecialchars($query) . '<br>' .
378 _("Server responded: ") .
379 htmlspecialchars($message) . "</font><br>\n";
380 error_box($string,$color);
381 echo '</body></html>';
384 set_up_language($squirrelmail_language);
385 require_once(SM_PATH
. 'functions/display_messages.php');
386 $string = "<b><font color=$color[2]>\n" .
387 _("ERROR : Unknown imap response.") .
390 htmlspecialchars($query) . '<br>' .
391 _("Server responded: ") .
392 htmlspecialchars($message) . "</font><br>\n";
393 error_box($string,$color);
394 /* the error is displayed but because we don't know the reponse we
395 return the result anyway */
401 function sqimap_read_data ($imap_stream, $tag_uid, $handle_errors,
402 &$response, &$message, $query = '',
403 $filter=false,$outputstream=false,$no_return=false) {
404 $res = sqimap_read_data_list($imap_stream, $tag_uid, $handle_errors,
405 $response, $message, $query,$filter,$outputstream,$no_return);
406 /* sqimap_read_data should be called for one response
407 but since it just calls sqimap_read_data_list which
408 handles multiple responses we need to check for that
409 and merge the $res array IF they are seperated and
410 IF it was a FETCH response. */
412 // if (isset($res[1]) && is_array($res[1]) && isset($res[1][0])
413 // && preg_match('/^\* \d+ FETCH/', $res[1][0])) {
414 // $result = array();
415 // foreach($res as $index=>$value) {
416 // $result = array_merge($result, $res["$index"]);
419 if (isset($result)) {
429 * Logs the user into the imap server. If $hide is set, no error messages
430 * will be displayed. This function returns the imap connection handle.
432 function sqimap_login ($username, $password, $imap_server_address, $imap_port, $hide) {
433 global $color, $squirrelmail_language, $onetimepad, $use_imap_tls, $imap_auth_mech;
435 if (!isset($onetimepad) ||
empty($onetimepad)) {
436 sqgetglobalvar('onetimepad' , $onetimepad , SQ_SESSION
);
438 $imap_server_address = sqimap_get_user_server($imap_server_address, $username);
439 $host=$imap_server_address;
441 if (($use_imap_tls == true) and (check_php_version(4,3)) and (extension_loaded('openssl'))) {
442 /* Use TLS by prefixing "tls://" to the hostname */
443 $imap_server_address = 'tls://' . $imap_server_address;
446 $imap_stream = fsockopen ( $imap_server_address, $imap_port, $error_number, $error_string, 15);
448 /* Do some error correction */
451 set_up_language($squirrelmail_language, true);
452 require_once(SM_PATH
. 'functions/display_messages.php');
453 $string = sprintf (_("Error connecting to IMAP server: %s.") .
454 "<br>\r\n", $imap_server_address) .
455 "$error_number : $error_string<br>\r\n";
456 logout_error($string,$color);
461 $server_info = fgets ($imap_stream, 1024);
463 /* Decrypt the password */
464 $password = OneTimePadDecrypt($password, $onetimepad);
466 if (($imap_auth_mech == 'cram-md5') OR ($imap_auth_mech == 'digest-md5')) {
467 // We're using some sort of authentication OTHER than plain or login
468 $tag=sqimap_session_id(false);
469 if ($imap_auth_mech == 'digest-md5') {
470 $query = $tag . " AUTHENTICATE DIGEST-MD5\r\n";
471 } elseif ($imap_auth_mech == 'cram-md5') {
472 $query = $tag . " AUTHENTICATE CRAM-MD5\r\n";
474 fputs($imap_stream,$query);
475 $answer=sqimap_fgets($imap_stream);
476 // Trim the "+ " off the front
477 $response=explode(" ",$answer,3);
478 if ($response[0] == '+') {
479 // Got a challenge back
480 $challenge=$response[1];
481 if ($imap_auth_mech == 'digest-md5') {
482 $reply = digest_md5_response($username,$password,$challenge,'imap',$host);
483 } elseif ($imap_auth_mech == 'cram-md5') {
484 $reply = cram_md5_response($username,$password,$challenge);
486 fputs($imap_stream,$reply);
487 $read=sqimap_fgets($imap_stream);
488 if ($imap_auth_mech == 'digest-md5') {
489 // DIGEST-MD5 has an extra step..
490 if (substr($read,0,1) == '+') { // OK so far..
491 fputs($imap_stream,"\r\n");
492 $read=sqimap_fgets($imap_stream);
495 $results=explode(" ",$read,3);
496 $response=$results[1];
497 $message=$results[2];
499 // Fake the response, so the error trap at the bottom will work
501 $message='IMAP server does not appear to support the authentication method selected.';
502 $message .= ' Please contact your system administrator.';
504 } elseif ($imap_auth_mech == 'login') {
505 // Original IMAP login code
506 $query = 'LOGIN "' . quoteimap($username) . '" "' . quoteimap($password) . '"';
507 $read = sqimap_run_command ($imap_stream, $query, false, $response, $message);
508 } elseif ($imap_auth_mech == 'plain') {
509 /* Replace this with SASL PLAIN if it ever gets implemented */
511 $message='SquirrelMail does not support SASL PLAIN yet. Rerun conf.pl and use login instead.';
514 $message="Internal SquirrelMail error - unknown IMAP authentication method chosen. Please contact the developers.";
517 /* If the connection was not successful, lets see why */
518 if ($response != 'OK') {
520 if ($response != 'NO') {
521 /* "BAD" and anything else gets reported here. */
522 $message = htmlspecialchars($message);
523 set_up_language($squirrelmail_language, true);
524 require_once(SM_PATH
. 'functions/display_messages.php');
525 if ($response == 'BAD') {
526 $string = sprintf (_("Bad request: %s")."<br>\r\n", $message);
528 $string = sprintf (_("Unknown error: %s") . "<br>\n", $message);
530 if (isset($read) && is_array($read)) {
531 $string .= '<br>' . _("Read data:") . "<br>\n";
532 foreach ($read as $line) {
533 $string .= htmlspecialchars($line) . "<br>\n";
536 error_box($string,$color);
540 * If the user does not log in with the correct
541 * username and password it is not possible to get the
542 * correct locale from the user's preferences.
543 * Therefore, apply the same hack as on the login
546 * $squirrelmail_language is set by a cookie when
547 * the user selects language and logs out
550 set_up_language($squirrelmail_language, true);
551 include_once(SM_PATH
. 'functions/display_messages.php' );
553 logout_error( _("Unknown user or password incorrect.") );
563 /* Simply logs out the IMAP session */
564 function sqimap_logout ($imap_stream) {
565 /* Logout is not valid until the server returns 'BYE'
566 * If we don't have an imap_ stream we're already logged out */
567 if(isset($imap_stream) && $imap_stream)
568 sqimap_run_command($imap_stream, 'LOGOUT', false, $response, $message);
571 function sqimap_capability($imap_stream, $capability='') {
572 global $sqimap_capabilities;
573 if (!is_array($sqimap_capabilities)) {
574 $read = sqimap_run_command($imap_stream, 'CAPABILITY', true, $a, $b);
576 $c = explode(' ', $read[0]);
577 for ($i=2; $i < count($c); $i++
) {
578 $cap_list = explode('=', $c[$i]);
579 if (isset($cap_list[1])) {
580 $sqimap_capabilities[$cap_list[0]] = $cap_list[1];
582 $sqimap_capabilities[$cap_list[0]] = TRUE;
587 if (isset($sqimap_capabilities[$capability])) {
588 return $sqimap_capabilities[$capability];
593 return $sqimap_capabilities;
596 /* Returns the delimeter between mailboxes: INBOX/Test, or INBOX.Test */
597 function sqimap_get_delimiter ($imap_stream = false) {
598 global $sqimap_delimiter, $optional_delimiter;
600 /* Use configured delimiter if set */
601 if((!empty($optional_delimiter)) && $optional_delimiter != 'detect') {
602 return $optional_delimiter;
605 /* Do some caching here */
606 if (!$sqimap_delimiter) {
607 if (sqimap_capability($imap_stream, 'NAMESPACE')) {
609 * According to something that I can't find, this is supposed to work on all systems
610 * OS: This won't work in Courier IMAP.
611 * OS: According to rfc2342 response from NAMESPACE command is:
612 * OS: * NAMESPACE (PERSONAL NAMESPACES) (OTHER_USERS NAMESPACE) (SHARED NAMESPACES)
613 * OS: We want to lookup all personal NAMESPACES...
615 $read = sqimap_run_command($imap_stream, 'NAMESPACE', true, $a, $b);
616 if (eregi('\\* NAMESPACE +(\\( *\\(.+\\) *\\)|NIL) +(\\( *\\(.+\\) *\\)|NIL) +(\\( *\\(.+\\) *\\)|NIL)', $read[0], $data)) {
617 if (eregi('^\\( *\\((.*)\\) *\\)', $data[1], $data2)) {
620 $pna = explode(')(', $pn);
621 while (list($k, $v) = each($pna)) {
622 $lst = explode('"', $v);
623 if (isset($lst[3])) {
624 $pn[$lst[1]] = $lst[3];
630 $sqimap_delimiter = $pn[0];
632 fputs ($imap_stream, ". LIST \"INBOX\" \"\"\r\n");
633 $read = sqimap_read_data($imap_stream, '.', true, $a, $b);
634 $quote_position = strpos ($read[0], '"');
635 $sqimap_delimiter = substr ($read[0], $quote_position+
1, 1);
638 return $sqimap_delimiter;
642 /* Gets the number of messages in the current mailbox. */
643 function sqimap_get_num_messages ($imap_stream, $mailbox) {
644 $read_ary = sqimap_run_command ($imap_stream, "EXAMINE \"$mailbox\"", false, $result, $message);
645 for ($i = 0; $i < count($read_ary); $i++
) {
646 if (ereg("[^ ]+ +([^ ]+) +EXISTS", $read_ary[$i], $regs)) {
650 return false; //"BUG! Couldn't get number of messages in $mailbox!";
654 function parseAddress($address, $max=0) {
657 $iCnt = strlen($address);
658 $aSpecials = array('(' ,'<' ,',' ,';' ,':');
659 $aReplace = array(' (',' <',' ,',' ;',' :');
660 $address = str_replace($aSpecials,$aReplace,$address);
663 $cChar = $address{$i};
667 $iEnd = strpos($address,'>',$i+
1);
669 $sToken = substr($address,$i);
672 $sToken = substr($address,$i,$iEnd - $i +
1);
675 $sToken = str_replace($aReplace, $aSpecials,$sToken);
676 $aTokens[] = $sToken;
679 $iEnd = strpos($address,$cChar,$i+
1);
681 $sToken = substr($address,$i);
684 // also remove the surrounding quotes
685 $sToken = substr($address,$i+
1,$iEnd - $i -1);
688 $sToken = str_replace($aReplace, $aSpecials,$sToken);
689 if ($sToken) $aTokens[] = $sToken;
692 $iEnd = strpos($address,')',$i);
694 $sToken = substr($address,$i);
697 $sToken = substr($address,$i,$iEnd - $i +
1);
700 $sToken = str_replace($aReplace, $aSpecials,$sToken);
701 $aTokens[] = $sToken;
710 $iEnd = strpos($address,' ',$i+
1);
712 $sToken = trim(substr($address,$i,$iEnd - $i));
715 $sToken = trim(substr($address,$i));
718 if ($sToken) $aTokens[] = $sToken;
722 $sPersonal = $sEmail = $sComment = $sGroup = '';
723 $aStack = $aComment = array();
724 foreach ($aTokens as $sToken) {
725 if ($max && $max == count($aAddress)) {
737 $aComment[] = substr($sToken,1,-1);
741 $sEmail = trim(implode(' ',$aStack));
742 $aAddress[] = array($sGroup,$sEmail);
743 $aStack = $aComment = array();
749 while (count($aStack) && !$sEmail) {
750 $sEmail = trim(array_pop($aStack));
753 if (count($aStack)) {
754 $sPersonal = trim(implode('',$aStack));
758 if (!$sPersonal && count($aComment)) {
759 $sComment = implode(' ',$aComment);
760 $sPersonal .= $sComment;
762 $aAddress[] = array($sEmail,$sPersonal);
763 $sPersonal = $sComment = $sEmail = '';
764 $aStack = $aComment = array();
767 $sGroup = implode(' ',$aStack); break;
771 $sEmail = trim(substr($sToken,1,-1));
776 default: $aStack[] = $sToken; break;
779 /* now do the action again for the last address */
781 while (count($aStack) && !$sEmail) {
782 $sEmail = trim(array_pop($aStack));
785 if (count($aStack)) {
786 $sPersonal = trim(implode('',$aStack));
790 if (!$sPersonal && count($aComment)) {
791 $sComment = implode(' ',$aComment);
792 $sPersonal .= $sComment;
794 $aAddress[] = array($sEmail,$sPersonal);
801 * Returns the number of unseen messages in this folder
803 function sqimap_unseen_messages ($imap_stream, $mailbox) {
804 $read_ary = sqimap_run_command ($imap_stream, "STATUS \"$mailbox\" (UNSEEN)", false, $result, $message);
806 $regs = array(false, false);
807 while (isset($read_ary[$i])) {
808 if (ereg("UNSEEN ([0-9]+)", $read_ary[$i], $regs)) {
817 * Returns the number of unseen/total messages in this folder
819 function sqimap_status_messages ($imap_stream, $mailbox) {
820 $read_ary = sqimap_run_command ($imap_stream, "STATUS \"$mailbox\" (MESSAGES UNSEEN RECENT)", false, $result, $message);
822 $messages = $unseen = $recent = false;
823 $regs = array(false,false);
824 while (isset($read_ary[$i])) {
825 if (preg_match('/UNSEEN\s+([0-9]+)/i', $read_ary[$i], $regs)) {
828 if (preg_match('/MESSAGES\s+([0-9]+)/i', $read_ary[$i], $regs)) {
829 $messages = $regs[1];
831 if (preg_match('/RECENT\s+([0-9]+)/i', $read_ary[$i], $regs)) {
836 return array('MESSAGES' => $messages, 'UNSEEN'=>$unseen, 'RECENT' => $recent);
841 * Saves a message to a given folder -- used for saving sent messages
843 function sqimap_append ($imap_stream, $sent_folder, $length) {
844 fputs ($imap_stream, sqimap_session_id() . " APPEND \"$sent_folder\" (\\Seen) \{$length}\r\n");
845 $tmp = fgets ($imap_stream, 1024);
848 function sqimap_append_done ($imap_stream, $folder='') {
849 global $squirrelmail_language, $color;
850 fputs ($imap_stream, "\r\n");
851 $tmp = fgets ($imap_stream, 1024);
852 if (preg_match("/(.*)(BAD|NO)(.*)$/", $tmp, $regs)) {
853 set_up_language($squirrelmail_language);
854 require_once(SM_PATH
. 'functions/display_messages.php');
856 if ($regs[2] == 'NO') {
857 $string = "<b><font color=$color[2]>\n" .
858 _("ERROR : Could not append message to") ." $folder." .
860 _("Server responded: ") .
862 if (preg_match("/(.*)(quota)(.*)$/i", $reason, $regs)) {
863 $string .= _("Solution: ") .
864 _("Remove unneccessary messages from your folder and start with your Trash folder.")
867 $string .= "</font>\n";
868 error_box($string,$color);
870 $string = "<b><font color=$color[2]>\n" .
871 _("ERROR : Bad or malformed request.") .
873 _("Server responded: ") .
874 $tmp . "</font><br>\n";
875 error_box($string,$color);
881 function sqimap_get_user_server ($imap_server, $username) {
882 if (substr($imap_server, 0, 4) != "map:") {
885 $function = substr($imap_server, 4);
886 return $function($username);
889 /* This is an example that gets imapservers from yellowpages (NIS).
890 * you can simple put map:map_yp_alias in your $imap_server_address
891 * in config.php use your own function instead map_yp_alias to map your
892 * LDAP whatever way to find the users imapserver. */
894 function map_yp_alias($username) {
895 $yp = `ypmatch
$username aliases`
;
896 return chop(substr($yp, strlen($username)+
1));