X-Git-Url: https://vcs.fsf.org/?a=blobdiff_plain;f=functions%2Fmailbox.php;h=8f9c92ab0e5cc17595a909f639d78e245f6b9350;hb=d4467150fe5126007ae625edb14ae757dbd687a0;hp=3b6af280a049c4a3027215fe196a9ebdc9d2f727;hpb=a09387f473293a14a597f6ee0afc9714700fb040;p=squirrelmail.git diff --git a/functions/mailbox.php b/functions/mailbox.php index 3b6af280..8f9c92ab 100644 --- a/functions/mailbox.php +++ b/functions/mailbox.php @@ -11,6 +11,7 @@ // select mailbox fputs($imapConnection, "mailboxSelect SELECT \"$mailbox\"\n"); $read = fgets($imapConnection, 1024); + $unseen = false; while ((substr($read, 0, 16) != "mailboxSelect OK") && (substr($read, 0, 17) != "mailboxSelect BAD")) { if (substr(Chop($read), -6) == "EXISTS") { $array = explode(" ", $read); @@ -20,37 +21,101 @@ } } - function getMessageHeaders($imapConnection, $i, &$from, &$subject, &$date) { - fputs($imapConnection, "messageFetch FETCH $i:$i RFC822.HEADER.LINES (From Subject Date)\n"); + function unseenMessages($imapConnection, &$numUnseen) { + fputs($imapConnection, "1 SEARCH UNSEEN NOT DELETED\n"); $read = fgets($imapConnection, 1024); - /* I have to replace <> with [] because HTML uses <> as tags, thus not printing what's in <> */ - $read = ereg_replace("<", "[", $read); - $read = ereg_replace(">", "]", $read); + $unseen = false; - while ((substr($read, 0, 15) != "messageFetch OK") && (substr($read, 0, 16) != "messageFetch BAD")) { - if (substr($read, 0, 5) == "From:") { - $read = ereg_replace("<", "EMAILSTART--", $read); - $read = ereg_replace(">", "--EMAILEND", $read); - $from = substr($read, 5, strlen($read) - 6); - } - else if (substr($read, 0, 5) == "Date:") { - $read = ereg_replace("<", "[", $read); - $read = ereg_replace(">", "]", $read); - $date = substr($read, 5, strlen($read) - 6); - } - else if (substr($read, 0, 8) == "Subject:") { - $read = ereg_replace("<", "[", $read); - $read = ereg_replace(">", "]", $read); - $subject = substr($read, 8, strlen($read) - 9); - } + if (strlen($read) > 10) { + $unseen = true; + $ary = explode(" ", $read); + $numUnseen = count($ary) - 2; + } + else { + $unseen = false; + $numUnseen = 0; + } + + $read = fgets($imapConnection, 1024); + return $unseen; + } + /** This function sends a request to the IMAP server for headers, 50 at a time + ** until $end is reached. I originally had it do them all at one time, but found + ** it slightly faster to do it this way. + ** + ** Originally we had getMessageHeaders get the headers for one message at a time. + ** Doing it in bunches gave us a speed increase from 9 seconds (for a box of 800 + ** messages) to about 3.5 seconds. + **/ + function getMessageHeaders($imapConnection, $start, $end, &$from, &$subject, &$date) { + $rel_start = $start; + if (($start > $end) || ($start < 1)) { + echo "Error in message header fetching. Start message: $start, End message: $end
"; + exit; + } + + $pos = 0; + while ($rel_start <= $end) { + if ($end - $rel_start > 50) { + $rel_end = $rel_start + 49; + } else { + $rel_end = $end; + } + fputs($imapConnection, "messageFetch FETCH $rel_start:$rel_end RFC822.HEADER.LINES (From Subject Date To Cc)\n"); $read = fgets($imapConnection, 1024); + + while ((substr($read, 0, 15) != "messageFetch OK") && (substr($read, 0, 16) != "messageFetch BAD")) { + + if (substr($read, 0, 5) == "From:") { + $read = ereg_replace("<", "EMAILSTART--", $read); + $read = ereg_replace(">", "--EMAILEND", $read); + $from[$pos] = substr($read, 5, strlen($read) - 6); + } + else if (substr($read, 0, 5) == "Date:") { + $read = ereg_replace("<", "<", $read); + $read = ereg_replace(">", ">", $read); + $date[$pos] = substr($read, 5, strlen($read) - 6); + } + else if (substr($read, 0, 8) == "Subject:") { + $read = ereg_replace("<", "<", $read); + $read = ereg_replace(">", ">", $read); + $subject[$pos] = substr($read, 8, strlen($read) - 9); + if (strlen(Chop($subject[$pos])) == 0) + $subject[$pos] = "(no subject)"; + } + else if (substr($read, 0, 1) == ")") { + if ($subject[$pos] == "") + $subject[$pos] = "(no subject)"; + else if ($from[$pos] == "") + $from[$pos] = "(unknown sender)"; + else if ($date[$pos] == "") + $from[$pos] = gettimeofday(); + + $pos++; + } + + $read = fgets($imapConnection, 1024); + } + $rel_start = $rel_start + 50; } } - function getMessageFlags($imapConnection, $i, &$flags) { + function setMessageFlag($imapConnection, $i, $q, $flag) { + fputs($imapConnection, "messageStore STORE $i:$q +FLAGS (\\$flag)\n"); + } + + /** This function gets the flags for message $j. It does only one message at a + ** time, rather than doing groups of messages (like getMessageHeaders does). + ** I found it one or two seconds quicker (on a box of 800 messages) to do it + ** individually. I'm not sure why it happens like that, but that's what my + ** testing found. Perhaps later I will be proven wrong and this will change. + **/ + function getMessageFlags($imapConnection, $j, &$flags) { /** * 2 FETCH (FLAGS (\Answered \Seen)) */ - fputs($imapConnection, "messageFetch FETCH $i:$i FLAGS\n"); + fputs($imapConnection, "messageFetch FETCH $j:$j FLAGS\n"); + $read = fgets($imapConnection, 1024); + $count = 0; while ((substr($read, 0, 15) != "messageFetch OK") && (substr($read, 0, 16) != "messageFetch BAD")) { if (strpos($read, "FLAGS")) { $read = ereg_replace("\(", "", $read); @@ -66,27 +131,41 @@ } else { $flags[0] = "None"; } + $count++; $read = fgets($imapConnection, 1024); } } + function decodeEmailAddr($sender) { + $emailAddr = getEmailAddr($sender); + if (strpos($emailAddr, "EMAILSTART--")) { + + $emailAddr = ereg_replace("EMAILSTART--", "", $emailAddr); + $emailAddr = ereg_replace("--EMAILEND", "", $emailAddr); + } else { + $emailAddr = $emailAddr; + } + return $emailAddr; + } + function getEmailAddr($sender) { if (strpos($sender, "EMAILSTART--") == false) - return ""; + return "$sender"; - $start = strpos($sender, "EMAILSTART--"); - $emailAddr = substr($sender, $start, strlen($sender)); + $emailStart = strpos($sender, "EMAILSTART--") + 12; + $emailAddr = substr($sender, $emailStart, strlen($sender)); + $emailAddr = substr($emailAddr, 0, strpos($emailAddr, "--EMAILEND")); return $emailAddr; } function getSender($sender) { if (strpos($sender, "EMAILSTART--") == false) - return ""; + return "$sender"; $first = substr($sender, 0, strpos($sender, "EMAILSTART--")); $second = substr($sender, strpos($sender, "--EMAILEND") +10, strlen($sender)); - return "$first$second"; + return "$first $second"; } function getSenderName($sender) { @@ -120,4 +199,348 @@ return $from; } + + /** returns "true" if the copy was completed successfully. + ** returns "false" with an error message if unsuccessful. + **/ + function copyMessages($imapConnection, $from_id, $to_id, $folder) { + fputs($imapConnection, "mailboxStore COPY $from_id:$to_id \"$folder\"\n"); + $read = fgets($imapConnection, 1024); + while ((substr($read, 0, 15) != "mailboxStore OK") && (substr($read, 0, 15) != "mailboxStore NO")) { + $read = fgets($imapConnection, 1024); + } + + if (substr($read, 0, 15) == "mailboxStore NO") { + return false; + } else if (substr($read, 0, 15) == "mailboxStore OK") { + return true; + } + + echo "UNKNOWN ERROR copying messages $from_id to $to_id to folder $folder.
"; + return false; + } + + /** expunges a mailbox **/ + function expungeBox($imapConnection, $mailbox) { + selectMailbox($imapConnection, $mailbox, $num); + fputs($imapConnection, "1 EXPUNGE\n"); + } + + function getFolderNameMinusINBOX($mailbox) { + if (substr($mailbox, 0, 6) == "INBOX.") + $box = substr($mailbox, 6, strlen($mailbox)); + else + $box = $mailbox; + + return $box; + } + + /** This function gets all the information about a message. Including Header and body **/ + function fetchMessage($imapConnection, $id) { + $message["HEADER"] = fetchHeader($imapConnection, $id); + $message["ENTITIES"] = fetchBody($imapConnection, $message["HEADER"]["BOUNDARY"], $id, $message["HEADER"]["TYPE0"], $message["HEADER"]["TYPE1"]); + + return $message; + } + + function fetchHeader($imapConnection, $id) { + fputs($imapConnection, "messageFetch FETCH $id:$id RFC822.HEADER.LINES (From Subject Date To Cc Content-Type MIME-Version)\n"); + $read = fgets($imapConnection, 1024); + + /** defaults... if the don't get overwritten, it will display text **/ + $header["TYPE0"] = "text"; + $header["TYPE1"] = "plain"; + $header["ENCODING"] = "us-ascii"; + while ((substr($read, 0, 15) != "messageFetch OK") && (substr($read, 0, 16) != "messageFetch BAD")) { + /** MIME-VERSION **/ + if (substr($read, 0, 17) == "MIME-Version: 1.0") { + $header["MIME"] = true; + $read = fgets($imapConnection, 1024); + } + + /** ENCODING TYPE **/ + else if (substr($read[$i], 0, 26) == "Content-Transfer-Encoding:") { + $header["ENCODING"] = strtolower(trim(substr($read[$i], 26))); + } + + /** CONTENT-TYPE **/ + else if (substr($read, 0, 13) == "Content-Type:") { + $cont = strtolower(trim(substr($read, 13))); + if (strpos($cont, ";")) + $cont = substr($cont, 0, strpos($cont, ";")); + $header["TYPE0"] = substr($cont, 0, strpos($cont, "/")); + $header["TYPE1"] = substr($cont, strpos($cont, "/")+1); + + $line = $read; + $read = fgets($imapConnection, 1024); + while ( (substr(substr($read, 0, strpos($read, " ")), -1) != ":") && (trim($read) != "") && (trim($read) != ")")) { + str_replace("\n", "", $line); + str_replace("\n", "", $read); + $line = "$line $read"; + $read = fgets($imapConnection, 1024); + } + + /** Detect the boundary of a multipart message **/ + if (strpos(strtolower(trim($line)), "boundary=")) { + $pos = strpos($line, "boundary=") + 9; + $bound = trim($line); + if (strpos($line, " ", $pos) > 0) { + $bound = substr($bound, $pos, strpos($line, " ", $pos)); + } else { + $bound = substr($bound, $pos); + } + $bound = str_replace("\"", "", $bound); + $header["BOUNDARY"] = $bound; + } + + /** Detect the charset **/ + if (strpos(strtolower(trim($line)), "charset=")) { + $pos = strpos($line, "charset=") + 8; + $charset = trim($line); + if (strpos($line, " ", $pos) > 0) { + $charset = substr($charset, $pos, strpos($line, " ", $pos)); + } else { + $charset = substr($charset, $pos); + } + $charset = str_replace("\"", "", $charset); + $header["CHARSET"] = $charset; + } else { + $header["CHARSET"] = "us-ascii"; + } + + } + /** FROM **/ + else if (substr($read, 0, 5) == "From:") { + $header["FROM"] = trim(substr($read, 5, strlen($read) - 6)); + $read = fgets($imapConnection, 1024); + } + /** DATE **/ + else if (substr($read, 0, 5) == "Date:") { + $d = substr($read, 5, strlen($read) - 6); + $d = trim($d); + $d = ereg_replace(" ", " ", $d); + $d = explode(" ", $d); + $header["DATE"] = getTimeStamp($d); + $read = fgets($imapConnection, 1024); + } + /** SUBJECT **/ + else if (substr($read, 0, 8) == "Subject:") { + $header["SUBJECT"] = trim(substr($read, 8, strlen($read) - 9)); + if (strlen(Chop($header["SUBJECT"])) == 0) + $header["SUBJECT"] = "(no subject)"; + $read = fgets($imapConnection, 1024); + } + /** CC **/ + else if (substr($read, 0, 3) == "CC:") { + $pos = 0; + $header["CC"][$pos] = trim(substr($read, 4)); + $read = fgets($imapConnection, 1024); + while ((substr($read, 0, 1) == " ") && (trim($read) != "")) { + $pos++; + $header["CC"][$pos] = trim($read); + $read = fgets($imapConnection, 1024); + } + } + /** TO **/ + else if (substr($read, 0, 3) == "To:") { + $pos = 0; + $header["TO"][$pos] = trim(substr($read, 4)); + $read = fgets($imapConnection, 1024); + while ((substr($read, 0, 1) == " ") && (trim($read) != "")){ + $pos++; + $header["TO"][$pos] = trim($read); + $read = fgets($imapConnection, 1024); + } + } + + /** ERROR CORRECTION **/ + else if (substr($read, 0, 1) == ")") { + if ($header["SUBJECT"] == "") + $header["SUBJECT"] = "(no subject)"; + + if ($header["FROM"] == "") + $header["FROM"] = "(unknown sender)"; + + if ($header["DATE"] == "") + $header["DATE"] = time(); + $read = fgets($imapConnection, 1024); + } + else { + $read = fgets($imapConnection, 1024); + } + } + return $header; + } + + function fetchBody($imapConnection, $bound, $id, $type0, $type1) { + /** This first part reads in the full body of the message **/ + fputs($imapConnection, "messageFetch FETCH $id:$id BODY[TEXT]\n"); + $read = fgets($imapConnection, 1024); + + $count = 0; + while ((substr($read, 0, 15) != "messageFetch OK") && (substr($read, 0, 16) != "messageFetch BAD")) { + $body[$count] = $read; + $count++; + + $read = fgets($imapConnection, 1024); + } + + /** this deletes the first line, and the last two (imap stuff we ignore) **/ + $i = 0; + $j = 0; + while ($i < count($body)) { + if ( ($i != 0) && ($i != count($body) - 1) && ($i != count($body)) ) { + $bodytmp[$j] = $body[$i]; + $j++; + } + $i++; + } + $body = $bodytmp; + + /** Now, lets work out the MIME stuff **/ + /** (needs mime.php included) **/ + return decodeMime($body, $bound, $type0, $type1); + } + + function fetchEntityHeader($imapConnection, &$read, &$type0, &$type1, &$bound, &$encoding, &$charset) { + /** defaults... if the don't get overwritten, it will display text **/ + $type0 = "text"; + $type1 = "plain"; + $encoding = "us-ascii"; + $i = 0; + while (trim($read[$i]) != "") { + if (substr($read[$i], 0, 26) == "Content-Transfer-Encoding:") { + $encoding = strtolower(trim(substr($read[$i], 26))); + + } else if (substr($read[$i], 0, 13) == "Content-Type:") { + $cont = strtolower(trim(substr($read[$i], 13))); + if (strpos($cont, ";")) + $cont = substr($cont, 0, strpos($cont, ";")); + $type0 = substr($cont, 0, strpos($cont, "/")); + $type1 = substr($cont, strpos($cont, "/")+1); + + $line = $read[$i]; + while ( (substr(substr($read[$i], 0, strpos($read[$i], " ")), -1) != ":") && (trim($read[$i]) != "") && (trim($read[$i]) != ")")) { + str_replace("\n", "", $line); + str_replace("\n", "", $read[$i]); + $line = "$line $read[$i]"; + $i++; + } + + /** Detect the boundary of a multipart message **/ + if (strpos(strtolower(trim($line)), "boundary=")) { + $pos = strpos($line, "boundary=") + 9; + $bound = trim($line); + if (strpos($line, " ", $pos) > 0) { + $bound = substr($bound, $pos, strpos($line, " ", $pos)); + } else { + $bound = substr($bound, $pos); + } + $bound = str_replace("\"", "", $bound); + } + + /** Detect the charset **/ + if (strpos(strtolower(trim($line)), "charset=")) { + $pos = strpos($line, "charset=") + 8; + $charset = trim($line); + if (strpos($line, " ", $pos) > 0) { + $charset = substr($charset, $pos, strpos($line, " ", $pos)); + } else { + $charset = substr($charset, $pos); + } + $charset = str_replace("\"", "", $charset); + } + } + $i++; + } + + /** remove the header from the entity **/ + $i = 0; + while (trim($read[$i]) != "") { + $i++; + } + $i++; + + for ($p = 0; $i < count($read); $p++) { + $entity[$p] = $read[$i]; + $i++; + } + + $read = $entity; + } + + function parsePlainTextMessage($line) { + $line = "^^$line"; + + if ((strpos(strtolower($line), "") == false) && + (strpos(strtolower($line), "") == false)) { + $line = str_replace("<", "<", $line); + $line = str_replace(">", ">", $line); + } + + $wrap_at = 86; // Make this configurable int the config file some time + if (strlen($line) - 2 >= $wrap_at) // -2 because of the ^^ at the beginning + $line = wordWrap($line, $wrap_at); + + $line = str_replace(" ", " ", $line); + $line = str_replace("\t", "        ", $line); + + /** if >> or > are found at the beginning of a line, I'll assume that was + replied text, so make it different colors **/ + if (strpos(trim(str_replace(" ", "", $line)), ">>") == 2) { + $line = substr($line, 2, strlen($line)); + $line = "$line
\n"; + } else if (strpos(trim(str_replace(" ", "", $line)), ">") == 2) { + $line = substr($line, 2, strlen($line)); + $line = "$line
\n"; + } else { + $line = substr($line, 2, strlen($line)); + $line = "$line
\n"; + } + + /** This translates "http://" into a link. It could be made better to accept + "www" and "mailto" also. That should probably be added later. **/ + if (strpos(strtolower($line), "http://") != false) { + $line = ereg_replace("
", "", $line); + $start = strpos(strtolower($line), "http://"); + $link = substr($line, $start, strlen($line)); + + if (strpos($link, " ")) { + $end = strpos($link, " ")-1; + } + else if (strpos($link, " ")) { + $end = strpos($link, " ")-1; + } + else if (strpos($link, "<")) { + $end = strpos($link, "<"); + } + else if (strpos($link, ">")) { + $end = strpos($link, ">"); + } + else if (strpos($link, "(")) { + $end = strpos($link, "(")-1; + } + else if (strpos($link, ")")) { + $end = strpos($link, ")")-1; + } + else if (strpos($link, "{")) { + $end = strpos($link, "{")-1; + } + else if (strpos($link, "}")) { + $end = strpos($link, "}")-1; + } + else + $end = strlen($link); + + $link = substr($line, $start, $end); + $end = $end + $start; + $before = substr($line, 0, $start); + $after = substr($line, $end, strlen($line)); + + $line = "$before$link$after
"; + } + + return $line; + } ?>