├── PhpImap ├── IncomingMail.php ├── Mailbox.php └── __autoload.php ├── config.php ├── index.php ├── readme.md └── styles.css /PhpImap/IncomingMail.php: -------------------------------------------------------------------------------- 1 | attachments[$attachment->id] = $attachment; 33 | } 34 | 35 | /** 36 | * @return IncomingMailAttachment[] 37 | */ 38 | public function getAttachments() { 39 | return $this->attachments; 40 | } 41 | 42 | /** 43 | * Get array of internal HTML links placeholders 44 | * @return array attachmentId => link placeholder 45 | */ 46 | public function getInternalLinksPlaceholders() { 47 | return preg_match_all('/=["\'](ci?d:([\w\.%*@-]+))["\']/i', $this->textHtml, $matches) ? array_combine($matches[2], $matches[1]) : array(); 48 | 49 | } 50 | 51 | public function replaceInternalLinks($baseUri) { 52 | $baseUri = rtrim($baseUri, '\\/') . '/'; 53 | $fetchedHtml = $this->textHtml; 54 | foreach($this->getInternalLinksPlaceholders() as $attachmentId => $placeholder) { 55 | if(isset($this->attachments[$attachmentId])) { 56 | $fetchedHtml = str_replace($placeholder, $baseUri . basename($this->attachments[$attachmentId]->filePath), $fetchedHtml); 57 | } 58 | } 59 | return $fetchedHtml; 60 | } 61 | } 62 | 63 | class IncomingMailAttachment { 64 | 65 | public $id; 66 | public $name; 67 | public $filePath; 68 | public $disposition; 69 | } 70 | -------------------------------------------------------------------------------- /PhpImap/Mailbox.php: -------------------------------------------------------------------------------- 1 | setImapPath($imapPath); 32 | $this->imapLogin = $login; 33 | $this->imapPassword = $password; 34 | $this->serverEncoding = strtoupper($serverEncoding); 35 | if($attachmentsDir) { 36 | if(!is_dir($attachmentsDir)) { 37 | throw new Exception('Directory "' . $attachmentsDir . '" not found'); 38 | } 39 | $this->attachmentsDir = rtrim(realpath($attachmentsDir), '\\/'); 40 | } 41 | } 42 | 43 | /** 44 | * Set custom connection arguments of imap_open method. See http://php.net/imap_open 45 | * @param int $options 46 | * @param int $retriesNum 47 | * @param array $params 48 | */ 49 | public function setConnectionArgs($options = 0, $retriesNum = 0, array $params = null) { 50 | $this->imapOptions = $options; 51 | $this->imapRetriesNum = $retriesNum; 52 | $this->imapParams = $params; 53 | } 54 | 55 | /** 56 | * Set custom folder for attachments in case you want to have tree of folders for each email 57 | * i.e. a/1 b/1 c/1 where a,b,c - senders, i.e. john@smith.com 58 | * @param string $dir folder where to save attachments 59 | * 60 | * @return void 61 | */ 62 | public function setAttachmentsDir($dir) { 63 | $this->attachmentsDir = $dir; 64 | } 65 | 66 | /** 67 | * Get IMAP mailbox connection stream 68 | * @param bool $forceConnection Initialize connection if it's not initialized 69 | * @return null|resource 70 | */ 71 | public function getImapStream($forceConnection = true) { 72 | if($forceConnection) { 73 | if($this->imapStream && (!is_resource($this->imapStream) || !imap_ping($this->imapStream))) { 74 | $this->disconnect(); 75 | $this->imapStream = null; 76 | } 77 | if(!$this->imapStream) { 78 | $this->imapStream = $this->initImapStream(); 79 | } 80 | } 81 | return $this->imapStream; 82 | } 83 | 84 | /** 85 | * Switch mailbox without opening a new connection 86 | * 87 | * @param string $imapPath 88 | */ 89 | public function switchMailbox($imapPath = '') { 90 | $this->imapPath = $imapPath; 91 | $imapStream = @imap_reopen($this->getImapStream(), $imapPath); 92 | if(!$imapStream) { 93 | throw new Exception("Couldn't switch mailbox: " . imap_last_error()); 94 | } 95 | } 96 | 97 | protected function initImapStream() { 98 | $imapStream = @imap_open($this->imapPath, $this->imapLogin, $this->imapPassword, $this->imapOptions, $this->imapRetriesNum, $this->imapParams); 99 | if(!$imapStream) { 100 | $lastError = imap_last_error(); 101 | imap_errors(); 102 | throw new Exception('Connection error: ' . $lastError); 103 | } 104 | return $imapStream; 105 | } 106 | 107 | protected function disconnect() { 108 | $imapStream = $this->getImapStream(false); 109 | if($imapStream && is_resource($imapStream)) { 110 | imap_close($imapStream, $this->expungeOnDisconnect ? CL_EXPUNGE : 0); 111 | } 112 | } 113 | 114 | /** 115 | * Sets 'expunge on disconnect' parameter 116 | * @param bool $isEnabled 117 | */ 118 | public function setExpungeOnDisconnect($isEnabled) { 119 | $this->expungeOnDisconnect = $isEnabled; 120 | } 121 | 122 | /** 123 | * Get information about the current mailbox. 124 | * 125 | * Returns the information in an object with following properties: 126 | * Date - current system time formatted according to RFC2822 127 | * Driver - protocol used to access this mailbox: POP3, IMAP, NNTP 128 | * Mailbox - the mailbox name 129 | * Nmsgs - number of mails in the mailbox 130 | * Recent - number of recent mails in the mailbox 131 | * 132 | * @return stdClass 133 | */ 134 | public function checkMailbox() { 135 | return imap_check($this->getImapStream()); 136 | } 137 | 138 | /** 139 | * Creates a new mailbox specified by mailbox. 140 | * 141 | * @return bool 142 | */ 143 | 144 | public function createMailbox() { 145 | return imap_createmailbox($this->getImapStream(), imap_utf7_encode($this->imapPath)); 146 | } 147 | 148 | /** 149 | * Gets status information about the given mailbox. 150 | * 151 | * This function returns an object containing status information. 152 | * The object has the following properties: messages, recent, unseen, uidnext, and uidvalidity. 153 | * 154 | * @return stdClass if the box doesn't exist 155 | */ 156 | 157 | public function statusMailbox() { 158 | return imap_status($this->getImapStream(), $this->imapPath, SA_ALL); 159 | } 160 | 161 | 162 | /** 163 | * Gets listing the folders 164 | * 165 | * This function returns an object containing listing the folders. 166 | * The object has the following properties: messages, recent, unseen, uidnext, and uidvalidity. 167 | * 168 | * @return array listing the folders 169 | */ 170 | 171 | public function getListingFolders() { 172 | $folders = imap_list($this->getImapStream(), $this->imapPath, "*"); 173 | foreach ($folders as $key => $folder) 174 | { 175 | if (function_exists('mb_convert_encoding')) { 176 | $folder = str_replace($this->imapPath, "", mb_convert_encoding($folder, "UTF-8", "UTF7-IMAP")); 177 | } else { 178 | $folder = str_replace($this->imapPath, "", imap_utf7_decode($folder)); 179 | } 180 | $folders[$key] = $folder; 181 | } 182 | return $folders; 183 | } 184 | 185 | 186 | /** 187 | * This function uses imap_search() to perform a search on the mailbox currently opened in the given IMAP stream. 188 | * For example, to match all unanswered mails sent by Mom, you'd use: "UNANSWERED FROM mom". 189 | * 190 | * @param string $criteria See http://php.net/imap_search for a complete list of available criteria 191 | * @return array mailsIds (or empty array) 192 | */ 193 | public function searchMailbox($criteria = 'ALL') { 194 | $mailsIds = imap_search($this->getImapStream(), $criteria, SE_UID, $this->serverEncoding); 195 | return $mailsIds ? $mailsIds : array(); 196 | } 197 | 198 | /** 199 | * Save mail body. 200 | * @return bool 201 | */ 202 | public function saveMail($mailId, $filename = 'email.eml') { 203 | return imap_savebody($this->getImapStream(), $filename, $mailId, "", FT_UID); 204 | } 205 | 206 | /** 207 | * Marks mails listed in mailId for deletion. 208 | * @return bool 209 | */ 210 | public function deleteMail($mailId) { 211 | return imap_delete($this->getImapStream(), $mailId, FT_UID); 212 | } 213 | 214 | /** 215 | * Moves mails listed in mailId into new mailbox 216 | * @return bool 217 | */ 218 | public function moveMail($mailId, $mailBox) { 219 | return imap_mail_move($this->getImapStream(), $mailId, $mailBox, CP_UID) && $this->expungeDeletedMails(); 220 | } 221 | 222 | /** 223 | * Copys mails listed in mailId into new mailbox 224 | * @return bool 225 | */ 226 | public function copyMail($mailId, $mailBox) { 227 | return imap_mail_copy($this->getImapStream(), $mailId, $mailBox, CP_UID) && $this->expungeDeletedMails(); 228 | } 229 | 230 | /** 231 | * Deletes all the mails marked for deletion by imap_delete(), imap_mail_move(), or imap_setflag_full(). 232 | * @return bool 233 | */ 234 | public function expungeDeletedMails() { 235 | return imap_expunge($this->getImapStream()); 236 | } 237 | 238 | /** 239 | * Add the flag \Seen to a mail. 240 | * @return bool 241 | */ 242 | public function markMailAsRead($mailId) { 243 | return $this->setFlag(array($mailId), '\\Seen'); 244 | } 245 | 246 | /** 247 | * Remove the flag \Seen from a mail. 248 | * @return bool 249 | */ 250 | public function markMailAsUnread($mailId) { 251 | return $this->clearFlag(array($mailId), '\\Seen'); 252 | } 253 | 254 | /** 255 | * Add the flag \Flagged to a mail. 256 | * @return bool 257 | */ 258 | public function markMailAsImportant($mailId) { 259 | return $this->setFlag(array($mailId), '\\Flagged'); 260 | } 261 | 262 | /** 263 | * Add the flag \Seen to a mails. 264 | * @return bool 265 | */ 266 | public function markMailsAsRead(array $mailId) { 267 | return $this->setFlag($mailId, '\\Seen'); 268 | } 269 | 270 | /** 271 | * Remove the flag \Seen from some mails. 272 | * @return bool 273 | */ 274 | public function markMailsAsUnread(array $mailId) { 275 | return $this->clearFlag($mailId, '\\Seen'); 276 | } 277 | 278 | /** 279 | * Add the flag \Flagged to some mails. 280 | * @return bool 281 | */ 282 | public function markMailsAsImportant(array $mailId) { 283 | return $this->setFlag($mailId, '\\Flagged'); 284 | } 285 | 286 | /** 287 | * Causes a store to add the specified flag to the flags set for the mails in the specified sequence. 288 | * 289 | * @param array $mailsIds 290 | * @param string $flag which you can set are \Seen, \Answered, \Flagged, \Deleted, and \Draft as defined by RFC2060. 291 | * @return bool 292 | */ 293 | public function setFlag(array $mailsIds, $flag) { 294 | return imap_setflag_full($this->getImapStream(), implode(',', $mailsIds), $flag, ST_UID); 295 | } 296 | 297 | /** 298 | * Cause a store to delete the specified flag to the flags set for the mails in the specified sequence. 299 | * 300 | * @param array $mailsIds 301 | * @param string $flag which you can set are \Seen, \Answered, \Flagged, \Deleted, and \Draft as defined by RFC2060. 302 | * @return bool 303 | */ 304 | public function clearFlag(array $mailsIds, $flag) { 305 | return imap_clearflag_full($this->getImapStream(), implode(',', $mailsIds), $flag, ST_UID); 306 | } 307 | 308 | /** 309 | * Fetch mail headers for listed mails ids 310 | * 311 | * Returns an array of objects describing one mail header each. The object will only define a property if it exists. The possible properties are: 312 | * subject - the mails subject 313 | * from - who sent it 314 | * to - recipient 315 | * date - when was it sent 316 | * message_id - Mail-ID 317 | * references - is a reference to this mail id 318 | * in_reply_to - is a reply to this mail id 319 | * size - size in bytes 320 | * uid - UID the mail has in the mailbox 321 | * msgno - mail sequence number in the mailbox 322 | * recent - this mail is flagged as recent 323 | * flagged - this mail is flagged 324 | * answered - this mail is flagged as answered 325 | * deleted - this mail is flagged for deletion 326 | * seen - this mail is flagged as already read 327 | * draft - this mail is flagged as being a draft 328 | * 329 | * @param array $mailsIds 330 | * @return array 331 | */ 332 | public function getMailsInfo(array $mailsIds) { 333 | $mails = imap_fetch_overview($this->getImapStream(), implode(',', $mailsIds), FT_UID); 334 | if(is_array($mails) && count($mails)) 335 | { 336 | foreach($mails as &$mail) 337 | { 338 | if(isset($mail->subject)) { 339 | $mail->subject = $this->decodeMimeStr($mail->subject, $this->serverEncoding); 340 | } 341 | if(isset($mail->from)) { 342 | $mail->from = $this->decodeMimeStr($mail->from, $this->serverEncoding); 343 | } 344 | if(isset($mail->to)) { 345 | $mail->to = $this->decodeMimeStr($mail->to, $this->serverEncoding); 346 | } 347 | } 348 | } 349 | return $mails; 350 | } 351 | 352 | /** 353 | * Get information about the current mailbox. 354 | * 355 | * Returns an object with following properties: 356 | * Date - last change (current datetime) 357 | * Driver - driver 358 | * Mailbox - name of the mailbox 359 | * Nmsgs - number of messages 360 | * Recent - number of recent messages 361 | * Unread - number of unread messages 362 | * Deleted - number of deleted messages 363 | * Size - mailbox size 364 | * 365 | * @return object Object with info | FALSE on failure 366 | */ 367 | 368 | public function getMailboxInfo() { 369 | return imap_mailboxmsginfo($this->getImapStream()); 370 | } 371 | 372 | /** 373 | * Gets mails ids sorted by some criteria 374 | * 375 | * Criteria can be one (and only one) of the following constants: 376 | * SORTDATE - mail Date 377 | * SORTARRIVAL - arrival date (default) 378 | * SORTFROM - mailbox in first From address 379 | * SORTSUBJECT - mail subject 380 | * SORTTO - mailbox in first To address 381 | * SORTCC - mailbox in first cc address 382 | * SORTSIZE - size of mail in octets 383 | * 384 | * @param int $criteria 385 | * @param bool $reverse 386 | * @return array Mails ids 387 | */ 388 | public function sortMails($criteria = SORTARRIVAL, $reverse = true) { 389 | return imap_sort($this->getImapStream(), $criteria, $reverse, SE_UID); 390 | } 391 | 392 | /** 393 | * Get mails count in mail box 394 | * @return int 395 | */ 396 | public function countMails() { 397 | return imap_num_msg($this->getImapStream()); 398 | } 399 | 400 | /** 401 | * Retrieve the quota settings per user 402 | * @return array - FALSE in the case of call failure 403 | */ 404 | protected function getQuota() { 405 | return imap_get_quotaroot($this->getImapStream(), 'INBOX'); 406 | } 407 | 408 | /** 409 | * Return quota limit in KB 410 | * @return int - FALSE in the case of call failure 411 | */ 412 | public function getQuotaLimit() { 413 | $quota = $this->getQuota(); 414 | if(is_array($quota)) { 415 | $quota = $quota['STORAGE']['limit']; 416 | } 417 | return $quota; 418 | } 419 | 420 | /** 421 | * Return quota usage in KB 422 | * @return int - FALSE in the case of call failure 423 | */ 424 | public function getQuotaUsage() { 425 | $quota = $this->getQuota(); 426 | if(is_array($quota)) { 427 | $quota = $quota['STORAGE']['usage']; 428 | } 429 | return $quota; 430 | } 431 | 432 | /** 433 | * Get raw mail data 434 | * 435 | * @param $msgId 436 | * @param bool $markAsSeen 437 | * @return mixed 438 | */ 439 | public function getRawMail($msgId, $markAsSeen = true){ 440 | $options = FT_UID; 441 | if(!$markAsSeen) { 442 | $options |= FT_PEEK; 443 | } 444 | 445 | return imap_fetchbody($this->getImapStream(), $msgId, '', $options); 446 | } 447 | 448 | /** 449 | * Get mail data 450 | * 451 | * @param $mailId 452 | * @param bool $markAsSeen 453 | * @return IncomingMail 454 | */ 455 | public function getMail($mailId, $markAsSeen = true) { 456 | $headersRaw = imap_fetchheader($this->getImapStream(), $mailId, FT_UID); 457 | $head = imap_rfc822_parse_headers($headersRaw); 458 | 459 | $mail = new IncomingMail(); 460 | $mail->headersRaw = $headersRaw; 461 | $mail->headers = $head; 462 | $mail->id = $mailId; 463 | $mail->date = date('Y-m-d H:i:s', isset($head->date) ? strtotime(preg_replace('/\(.*?\)/', '', $head->date)) : time()); 464 | $mail->subject = isset($head->subject) ? $this->decodeMimeStr($head->subject, $this->serverEncoding) : null; 465 | $mail->fromName = isset($head->from[0]->personal) ? $this->decodeMimeStr($head->from[0]->personal, $this->serverEncoding) : null; 466 | $mail->fromAddress = strtolower($head->from[0]->mailbox . '@' . $head->from[0]->host); 467 | 468 | if(isset($head->to)) { 469 | $toStrings = array(); 470 | foreach($head->to as $to) { 471 | if(!empty($to->mailbox) && !empty($to->host)) { 472 | $toEmail = strtolower($to->mailbox . '@' . $to->host); 473 | $toName = isset($to->personal) ? $this->decodeMimeStr($to->personal, $this->serverEncoding) : null; 474 | $toStrings[] = $toEmail; 475 | $mail->to[$toEmail] = $toName; 476 | } 477 | } 478 | $mail->toString = implode(', ', $toStrings); 479 | } 480 | 481 | if(isset($head->cc)) { 482 | foreach($head->cc as $cc) { 483 | $mail->cc[strtolower($cc->mailbox . '@' . $cc->host)] = isset($cc->personal) ? $this->decodeMimeStr($cc->personal, $this->serverEncoding) : null; 484 | } 485 | } 486 | 487 | if(isset($head->bcc)) { 488 | foreach($head->bcc as $bcc) { 489 | $mail->bcc[strtolower($bcc->mailbox . '@' . $bcc->host)] = isset($bcc->personal) ? $this->decodeMimeStr($bcc->personal, $this->serverEncoding) : null; 490 | } 491 | } 492 | 493 | if(isset($head->reply_to)) { 494 | foreach($head->reply_to as $replyTo) { 495 | $mail->replyTo[strtolower($replyTo->mailbox . '@' . $replyTo->host)] = isset($replyTo->personal) ? $this->decodeMimeStr($replyTo->personal, $this->serverEncoding) : null; 496 | } 497 | } 498 | 499 | if(isset($head->message_id)) { 500 | $mail->messageId = $head->message_id; 501 | } 502 | 503 | $mailStructure = imap_fetchstructure($this->getImapStream(), $mailId, FT_UID); 504 | 505 | if(empty($mailStructure->parts)) { 506 | $this->initMailPart($mail, $mailStructure, 0, $markAsSeen); 507 | } 508 | else { 509 | foreach($mailStructure->parts as $partNum => $partStructure) { 510 | $this->initMailPart($mail, $partStructure, $partNum + 1, $markAsSeen); 511 | } 512 | } 513 | 514 | return $mail; 515 | } 516 | 517 | protected function initMailPart(IncomingMail $mail, $partStructure, $partNum, $markAsSeen = true) { 518 | $options = FT_UID; 519 | if(!$markAsSeen) { 520 | $options |= FT_PEEK; 521 | } 522 | $data = $partNum ? imap_fetchbody($this->getImapStream(), $mail->id, $partNum, $options) : imap_body($this->getImapStream(), $mail->id, $options); 523 | 524 | if($partStructure->encoding == 1) { 525 | $data = imap_utf8($data); 526 | } 527 | elseif($partStructure->encoding == 2) { 528 | $data = imap_binary($data); 529 | } 530 | elseif($partStructure->encoding == 3) { 531 | $data = preg_replace('~[^a-zA-Z0-9+=/]+~s', '', $data); // https://github.com/barbushin/php-imap/issues/88 532 | $data = imap_base64($data); 533 | } 534 | elseif($partStructure->encoding == 4) { 535 | $data = quoted_printable_decode($data); 536 | } 537 | 538 | $params = array(); 539 | if(!empty($partStructure->parameters)) { 540 | foreach($partStructure->parameters as $param) { 541 | $params[strtolower($param->attribute)] = $param->value; 542 | } 543 | } 544 | if(!empty($partStructure->dparameters)) { 545 | foreach($partStructure->dparameters as $param) { 546 | $paramName = strtolower(preg_match('~^(.*?)\*~', $param->attribute, $matches) ? $matches[1] : $param->attribute); 547 | if(isset($params[$paramName])) { 548 | $params[$paramName] .= $param->value; 549 | } 550 | else { 551 | $params[$paramName] = $param->value; 552 | } 553 | } 554 | } 555 | 556 | // attachments 557 | /* 558 | $attachmentId = $partStructure->ifid 559 | ? trim($partStructure->id, " <>") 560 | : (isset($params['filename']) || isset($params['name']) ? mt_rand() . mt_rand() : null); 561 | */ 562 | $attachmentId = null; 563 | // ignore contentId on body when mail isn't multipart (https://github.com/barbushin/php-imap/issues/71) 564 | if (!$partNum && TYPETEXT === $partStructure->type) 565 | { 566 | $attachmentId = null; 567 | } 568 | 569 | if($attachmentId) { 570 | if(empty($params['filename']) && empty($params['name'])) { 571 | $fileName = $attachmentId . '.' . strtolower($partStructure->subtype); 572 | } 573 | else { 574 | $fileName = !empty($params['filename']) ? $params['filename'] : $params['name']; 575 | $fileName = $this->decodeMimeStr($fileName, $this->serverEncoding); 576 | $fileName = $this->decodeRFC2231($fileName, $this->serverEncoding); 577 | } 578 | $attachment = new IncomingMailAttachment(); 579 | $attachment->id = $attachmentId; 580 | $attachment->name = $fileName; 581 | $attachment->disposition = (isset($partStructure->disposition) ? $partStructure->disposition : null); 582 | if($this->attachmentsDir) { 583 | $replace = array( 584 | '/\s/' => '_', 585 | '/[^0-9a-zа-яіїє_\.]/iu' => '', 586 | '/_+/' => '_', 587 | '/(^_)|(_$)/' => '', 588 | ); 589 | $fileSysName = preg_replace('~[\\\\/]~', '', $mail->id . '_' . $attachmentId . '_' . preg_replace(array_keys($replace), $replace, $fileName)); 590 | $attachment->filePath = $this->attachmentsDir . DIRECTORY_SEPARATOR . $fileSysName; 591 | 592 | if(strlen($attachment->filePath) > 255) { 593 | $ext = pathinfo($attachment->filePath, PATHINFO_EXTENSION); 594 | $attachment->filePath = substr($attachment->filePath, 0, 255 -1 -strlen($ext)).".".$ext; 595 | } 596 | 597 | file_put_contents($attachment->filePath, $data); 598 | } 599 | $mail->addAttachment($attachment); 600 | } 601 | else { 602 | if(!empty($params['charset'])) { 603 | $data = $this->convertStringEncoding($data, $params['charset'], $this->serverEncoding); 604 | } 605 | if($partStructure->type == 0 && $data) { 606 | if(strtolower($partStructure->subtype) == 'plain') { 607 | $mail->textPlain .= $data; 608 | } 609 | else { 610 | $mail->textHtml .= $data; 611 | } 612 | } 613 | elseif($partStructure->type == 2 && $data) { 614 | $mail->textPlain .= trim($data); 615 | } 616 | } 617 | if(!empty($partStructure->parts)) { 618 | foreach($partStructure->parts as $subPartNum => $subPartStructure) { 619 | if($partStructure->type == 2 && $partStructure->subtype == 'RFC822') { 620 | $this->initMailPart($mail, $subPartStructure, $partNum, $markAsSeen); 621 | } 622 | else { 623 | $this->initMailPart($mail, $subPartStructure, $partNum . '.' . ($subPartNum + 1), $markAsSeen); 624 | } 625 | } 626 | } 627 | } 628 | 629 | protected function decodeMimeStr($string, $charset = 'utf-8') { 630 | $newString = ''; 631 | $elements = imap_mime_header_decode($string); 632 | for($i = 0; $i < count($elements); $i++) { 633 | if($elements[$i]->charset == 'default') { 634 | $elements[$i]->charset = 'iso-8859-1'; 635 | } 636 | $newString .= $this->convertStringEncoding($elements[$i]->text, $elements[$i]->charset, $charset); 637 | } 638 | return $newString; 639 | } 640 | 641 | function isUrlEncoded($string) { 642 | $hasInvalidChars = preg_match( '#[^%a-zA-Z0-9\-_\.\+]#', $string ); 643 | $hasEscapedChars = preg_match( '#%[a-zA-Z0-9]{2}#', $string ); 644 | return !$hasInvalidChars && $hasEscapedChars; 645 | } 646 | 647 | protected function decodeRFC2231($string, $charset = 'utf-8') { 648 | if(preg_match("/^(.*?)'.*?'(.*?)$/", $string, $matches)) { 649 | $encoding = $matches[1]; 650 | $data = $matches[2]; 651 | if($this->isUrlEncoded($data)) { 652 | $string = $this->convertStringEncoding(urldecode($data), $encoding, $charset); 653 | } 654 | } 655 | return $string; 656 | } 657 | 658 | /** 659 | * Converts a string from one encoding to another. 660 | * @param string $string 661 | * @param string $fromEncoding 662 | * @param string $toEncoding 663 | * @return string Converted string if conversion was successful, or the original string if not 664 | */ 665 | protected function convertStringEncoding($string, $fromEncoding, $toEncoding) { 666 | $convertedString = null; 667 | if($string && $fromEncoding != $toEncoding) { 668 | $convertedString = @iconv($fromEncoding, $toEncoding . '//IGNORE', $string); 669 | if(!$convertedString && extension_loaded('mbstring')) { 670 | $convertedString = @mb_convert_encoding($string, $toEncoding, $fromEncoding); 671 | } 672 | } 673 | return $convertedString ?: $string; 674 | } 675 | 676 | public function __destruct() { 677 | $this->disconnect(); 678 | } 679 | 680 | /** 681 | * @param $imapPath 682 | * @return void 683 | */ 684 | protected function setImapPath($imapPath) 685 | { 686 | if (function_exists('mb_convert_encoding')) { 687 | $this->imapPath = mb_convert_encoding($imapPath, "UTF7-IMAP", "UTF-8"); 688 | } else { 689 | $this->imapPath = imap_utf7_encode($imapPath); 690 | } 691 | } 692 | } 693 | 694 | class Exception extends \Exception { 695 | 696 | } 697 | -------------------------------------------------------------------------------- /PhpImap/__autoload.php: -------------------------------------------------------------------------------- 1 | "TMail Lite", 4 | "host"=>"", 5 | "user"=>"", 6 | "pass"=>"", 7 | "domain"=>"" 8 | ); 9 | ?> 10 | -------------------------------------------------------------------------------- /index.php: -------------------------------------------------------------------------------- 1 | searchMailbox($toList); 29 | $mailIdsCc = $mailbox->searchMailbox($ccList); 30 | $mailIdsBcc = $mailbox->searchMailbox($bccList); 31 | $mailsIds = array_reverse(array_unique(array_merge($mailIdsTo,$mailIdsCc,$mailIdsBcc))); 32 | if(isset($unseen) && $unseen == 1) { 33 | $unseenIds = $mailbox->searchMailbox("UNSEEN"); 34 | $mailsIds = array_intersect($mailsIds,$unseenIds); 35 | } 36 | ?> 37 | 38 | 39 |
40 | 41 | 42 |