Implements the following IMAP-related RFCs (see http://www.iana.org/assignments/imap4-capabilities): - RFC 2086/4314: ACL - RFC 2087: QUOTA - RFC 2088: LITERAL+ - RFC 2195: AUTH=CRAM-MD5 - RFC 2221: LOGIN-REFERRALS - RFC 2342: NAMESPACE - RFC 2595/4616: TLS & AUTH=PLAIN - RFC 2831: DIGEST-MD5 authentication mechanism (obsoleted by RFC 6331) - RFC 2971: ID - RFC 3348: CHILDREN - RFC 3501: IMAP4rev1 specification - RFC 3502: MULTIAPPEND - RFC 3516: BINARY - RFC 3691: UNSELECT - RFC 4315: UIDPLUS - RFC 4422: SASL Authentication (for DIGEST-MD5) - RFC 4466: Collected extensions (updates RFCs 2088, 3501, 3502, 3516) - RFC 4469/5550: CATENATE - RFC 4551: CONDSTORE - RFC 4731: ESEARCH - RFC 4959: SASL-IR - RFC 5032: WITHIN - RFC 5161: ENABLE - RFC 5162: QRESYNC - RFC 5182: SEARCHRES - RFC 5255: LANGUAGE/I18NLEVEL - RFC 5256: THREAD/SORT - RFC 5258: LIST-EXTENDED - RFC 5267: ESORT; PARTIAL search return option - RFC 5464: METADATA - RFC 5530: IMAP Response Codes - RFC 5819: LIST-STATUS - RFC 5957: SORT=DISPLAY - RFC 6154: SPECIAL-USE/CREATE-SPECIAL-USE - RFC 6203: SEARCH=FUZZY Implements the following non-RFC extensions:
  • draft-ietf-morg-inthread-01: THREAD=REFS
  • draft-daboo-imap-annotatemore-07: ANNOTATEMORE
  • draft-daboo-imap-annotatemore-08: ANNOTATEMORE2
  • XIMAPPROXY
    • Requires imapproxy v1.2.7-rc1 or later
    • See https://squirrelmail.svn.sourceforge.net/svnroot/squirrelmail/trunk/imap_proxy/README
TODO (or not necessary?):
  • RFC 2177: IDLE
    • Probably not necessary due to the limited connection time of each HTTP/PHP request
  • RFC 2193: MAILBOX-REFERRALS
  • RFC 4467/5092/5524/5550/5593: URLAUTH, URLAUTH=BINARY, URL-PARTIAL
  • RFC 4978: COMPRESS=DEFLATE
    • See: http://bugs.php.net/bug.php?id=48725
  • RFC 5257: ANNOTATE (Experimental)
  • RFC 5259: CONVERT
  • RFC 5267: CONTEXT=SEARCH; CONTEXT=SORT
  • RFC 5465: NOTIFY
  • RFC 5466: FILTERS
  • RFC 5738: UTF8 (Very limited support currently)
  • RFC 6237: MULTISEARCH
  • draft-ietf-morg-inthread-01: SEARCH=INTHREAD
    • Appears to be dead
  • draft-krecicki-imap-move-01.txt: MOVE
    • Appears to be dead
Originally based on code from: - auth.php (1.49) - imap_general.php (1.212) - imap_messages.php (revision 13038) - strings.php (1.184.2.35) from the Squirrelmail project. Copyright (c) 1999-2007 The SquirrelMail Project Team Copyright 2005-2012 Horde LLC (http://www.horde.org/) See the enclosed file COPYING for license information (LGPL). If you did not receive this file, see http://www.horde.org/licenses/lgpl21.
Author: Michael Slusarz (slusarz@horde.org)
Inheritance: extends Horde_Imap_Client_Base
コード例 #1
0
ファイル: Catenate.php プロジェクト: jubinpatel/horde
 /**
  * Given an IMAP URL, fetches the corresponding part.
  *
  * @param Horde_Imap_Client_Url_Imap $url  An IMAP URL.
  *
  * @return resource  The section contents in a stream. Returns null if
  *                   the part could not be found.
  *
  * @throws Horde_Imap_Client_Exception
  */
 public function fetchFromUrl(Horde_Imap_Client_Url_Imap $url)
 {
     $ids_ob = $this->_socket->getIdsOb($url->uid);
     // BODY[]
     if (is_null($url->section)) {
         $query = new Horde_Imap_Client_Fetch_Query();
         $query->fullText(array('peek' => true));
         $fetch = $this->_socket->fetch($url->mailbox, $query, array('ids' => $ids_ob));
         return $fetch[$url->uid]->getFullMsg(true);
     }
     $section = trim($url->section);
     // BODY[<#.>HEADER.FIELDS<.NOT>()]
     if (($pos = stripos($section, 'HEADER.FIELDS')) !== false) {
         $hdr_pos = strpos($section, '(');
         $cmd = substr($section, 0, $hdr_pos);
         $query = new Horde_Imap_Client_Fetch_Query();
         $query->headers('section', explode(' ', substr($section, $hdr_pos + 1, strrpos($section, ')') - $hdr_pos)), array('id' => $pos ? substr($section, 0, $pos - 1) : 0, 'notsearch' => stripos($cmd, '.NOT') !== false, 'peek' => true));
         $fetch = $this->_socket->fetch($url->mailbox, $query, array('ids' => $ids_ob));
         return $fetch[$url->uid]->getHeaders('section', Horde_Imap_Client_Data_Fetch::HEADER_STREAM);
     }
     // BODY[#]
     if (is_numeric(substr($section, -1))) {
         $query = new Horde_Imap_Client_Fetch_Query();
         $query->bodyPart($section, array('peek' => true));
         $fetch = $this->_socket->fetch($url->mailbox, $query, array('ids' => $ids_ob));
         return $fetch[$url->uid]->getBodyPart($section, true);
     }
     // BODY[<#.>HEADER]
     if (($pos = stripos($section, 'HEADER')) !== false) {
         $id = $pos ? substr($section, 0, $pos - 1) : 0;
         $query = new Horde_Imap_Client_Fetch_Query();
         $query->headerText(array('id' => $id, 'peek' => true));
         $fetch = $this->_socket->fetch($url->mailbox, $query, array('ids' => $ids_ob));
         return $fetch[$url->uid]->getHeaderText($id, Horde_Imap_Client_Data_Fetch::HEADER_STREAM);
     }
     // BODY[<#.>TEXT]
     if (($pos = stripos($section, 'TEXT')) !== false) {
         $id = $pos ? substr($section, 0, $pos - 1) : 0;
         $query = new Horde_Imap_Client_Fetch_Query();
         $query->bodyText(array('id' => $id, 'peek' => true));
         $fetch = $this->_socket->fetch($url->mailbox, $query, array('ids' => $ids_ob));
         return $fetch[$url->uid]->getBodyText($id, true);
     }
     // BODY[<#.>MIMEHEADER]
     if (($pos = stripos($section, 'MIME')) !== false) {
         $id = $pos ? substr($section, 0, $pos - 1) : 0;
         $query = new Horde_Imap_Client_Fetch_Query();
         $query->mimeHeader($id, array('peek' => true));
         $fetch = $this->_socket->fetch($url->mailbox, $query, array('ids' => $ids_ob));
         return $fetch[$url->uid]->getMimeHeader($id, Horde_Imap_Client_Data_Fetch::HEADER_STREAM);
     }
     return null;
 }
コード例 #2
0
ファイル: account.php プロジェクト: netcon-source/apps
 public function getImapConnection()
 {
     //
     // TODO: cache connections for / within accounts???
     //
     $host = $this->info['host'];
     $user = $this->info['user'];
     $password = $this->info['password'];
     $port = $this->info['port'];
     $ssl_mode = $this->info['ssl_mode'];
     $client = new \Horde_Imap_Client_Socket(array('username' => $user, 'password' => $password, 'hostspec' => $host, 'port' => $port, 'secure' => $ssl_mode, 'timeout' => 2));
     $client->login();
     return $client;
 }
コード例 #3
0
ファイル: attachment.php プロジェクト: matiasdelellis/mail
 private function load()
 {
     $headers = [];
     $fetch_query = new \Horde_Imap_Client_Fetch_Query();
     $fetch_query->bodyPart($this->attachmentId);
     $fetch_query->mimeHeader($this->attachmentId);
     $headers = array_merge($headers, ['importance', 'list-post', 'x-priority']);
     $headers[] = 'content-type';
     $fetch_query->headers('imp', $headers, ['cache' => true]);
     // $list is an array of Horde_Imap_Client_Data_Fetch objects.
     $ids = new \Horde_Imap_Client_Ids($this->messageId);
     $headers = $this->conn->fetch($this->mailBox, $fetch_query, ['ids' => $ids]);
     /** @var $fetch Horde_Imap_Client_Data_Fetch */
     if (!isset($headers[$this->messageId])) {
         throw new DoesNotExistException('Unable to load the attachment.');
     }
     $fetch = $headers[$this->messageId];
     $mimeHeaders = $fetch->getMimeHeader($this->attachmentId, Horde_Imap_Client_Data_Fetch::HEADER_PARSE);
     $this->mimePart = new \Horde_Mime_Part();
     // To prevent potential problems with the SOP we serve all files with the
     // MIME type "application/octet-stream"
     $this->mimePart->setType('application/octet-stream');
     // Serve all files with a content-disposition of "attachment" to prevent Cross-Site Scripting
     $this->mimePart->setDisposition('attachment');
     // Extract headers from part
     $contentDisposition = $mimeHeaders->getValue('content-disposition', \Horde_Mime_Headers::VALUE_PARAMS);
     if (!is_null($contentDisposition)) {
         $vars = ['filename'];
         foreach ($contentDisposition as $key => $val) {
             if (in_array($key, $vars)) {
                 $this->mimePart->setDispositionParameter($key, $val);
             }
         }
     } else {
         $contentDisposition = $mimeHeaders->getValue('content-type', \Horde_Mime_Headers::VALUE_PARAMS);
         $vars = ['name'];
         foreach ($contentDisposition as $key => $val) {
             if (in_array($key, $vars)) {
                 $this->mimePart->setContentTypeParameter($key, $val);
             }
         }
     }
     /* Content transfer encoding. */
     if ($tmp = $mimeHeaders->getValue('content-transfer-encoding')) {
         $this->mimePart->setTransferEncoding($tmp);
     }
     $body = $fetch->getBodyPart($this->attachmentId);
     $this->mimePart->setContents($body);
 }
コード例 #4
0
ファイル: Imap.php プロジェクト: raz0rsdge/horde
 /**
  */
 public function valid(array $opts = array())
 {
     if (empty($opts['users'])) {
         unset($opts['auth']);
         /* We still need a username as it is required by the IMAP
          * object. */
         $opts['users'] = array('testing');
     }
     switch ($this->tls) {
         case 'starttls':
             $secure = 'tls';
             break;
         case 'tls':
             $secure = 'ssl';
             break;
         default:
             $secure = !empty($opts['insecure']) ?: 'tls';
             break;
     }
     foreach ($opts['users'] as $user) {
         try {
             $imap = new Horde_Imap_Client_Socket(array('hostspec' => $this->host, 'password' => isset($opts['auth']) ? $opts['auth'] : null, 'port' => $this->port, 'secure' => $secure, 'timeout' => 2, 'username' => $user));
             if (isset($opts['auth'])) {
                 $imap->login();
                 $this->username = $user;
             } else {
                 $imap->noop();
             }
             if ($secure === 'tls') {
                 $this->tls = 'starttls';
             } elseif ($secure === true) {
                 $this->tls = $imap->isSecureConnection() ? 'starttls' : false;
             }
             $imap->shutdown();
             return true;
         } catch (Horde_Imap_Client_Exception $e) {
         }
     }
     return false;
 }
コード例 #5
0
ファイル: ClientSort.php プロジェクト: netcon-source/apps
 /**
  * Sort search results client side if the server does not support the SORT
  * IMAP extension (RFC 5256).
  *
  * @param Horde_Imap_Client_Ids $res  The search results.
  * @param array $opts                 The options to _search().
  *
  * @return array  The sort results.
  *
  * @throws Horde_Imap_Client_Exception
  */
 public function clientSort($res, $opts)
 {
     if (!count($res)) {
         return $res;
     }
     /* Generate the FETCH command needed. */
     $query = new Horde_Imap_Client_Fetch_Query();
     foreach ($opts['sort'] as $val) {
         switch ($val) {
             case Horde_Imap_Client::SORT_ARRIVAL:
                 $query->imapDate();
                 break;
             case Horde_Imap_Client::SORT_DATE:
                 $query->imapDate();
                 $query->envelope();
                 break;
             case Horde_Imap_Client::SORT_CC:
             case Horde_Imap_Client::SORT_DISPLAYFROM:
             case Horde_Imap_Client::SORT_DISPLAYTO:
             case Horde_Imap_Client::SORT_FROM:
             case Horde_Imap_Client::SORT_SUBJECT:
             case Horde_Imap_Client::SORT_TO:
                 $query->envelope();
                 break;
             case Horde_Imap_Client::SORT_SIZE:
                 $query->size();
                 break;
         }
     }
     if (!count($query)) {
         return $res;
     }
     $mbox = $this->_socket->currentMailbox();
     $fetch_res = $this->_socket->fetch($mbox['mailbox'], $query, array('ids' => $res));
     return $this->_clientSortProcess($res->ids, $fetch_res, $opts['sort']);
 }
コード例 #6
0
ファイル: message.php プロジェクト: jakobsack/mail
 /**
  * @param \Horde_Mime_Part $p
  * @param int $partNo
  * @return string
  * @throws DoesNotExistException
  * @throws \Exception
  */
 private function loadBodyData($p, $partNo)
 {
     // DECODE DATA
     $fetch_query = new \Horde_Imap_Client_Fetch_Query();
     $ids = new \Horde_Imap_Client_Ids($this->messageId);
     $fetch_query->bodyPart($partNo, ['peek' => true]);
     $fetch_query->bodyPartSize($partNo);
     $fetch_query->mimeHeader($partNo, ['peek' => true]);
     $headers = $this->conn->fetch($this->mailBox, $fetch_query, ['ids' => $ids]);
     /** @var $fetch \Horde_Imap_Client_Data_Fetch */
     $fetch = $headers[$this->messageId];
     if (is_null($fetch)) {
         throw new DoesNotExistException("Mail body for this mail({$this->messageId}) could not be loaded");
     }
     $mimeHeaders = $fetch->getMimeHeader($partNo, Horde_Imap_Client_Data_Fetch::HEADER_PARSE);
     if ($enc = $mimeHeaders->getValue('content-transfer-encoding')) {
         $p->setTransferEncoding($enc);
     }
     $data = $fetch->getBodyPart($partNo);
     $p->setContents($data);
     $data = $p->getContents();
     $data = iconv($p->getCharset(), 'utf-8//IGNORE', $data);
     return $data;
 }
コード例 #7
0
ファイル: Auth.php プロジェクト: horde/horde
 /**
  * Returns a Horde_Auth_Base driver for the given driver/configuration.
  *
  * @param string $driver      Driver name.
  * @param array $orig_params  Driver parameters.
  *
  * @return Horde_Auth_Base  Authentication object.
  */
 protected function _create($driver, $orig_params = null)
 {
     /* Get proper driver name now that we have grabbed the
      * configuration. */
     if (strcasecmp($driver, 'application') === 0) {
         $driver = 'Horde_Core_Auth_Application';
     } elseif (strcasecmp($driver, 'httpremote') === 0) {
         /* BC */
         $driver = 'Http_Remote';
     } elseif (strcasecmp($driver, 'composite') === 0) {
         $driver = 'Horde_Core_Auth_Composite';
     } elseif (strcasecmp($driver, 'ldap') === 0) {
         $driver = 'Horde_Core_Auth_Ldap';
     } elseif (strcasecmp($driver, 'msad') === 0) {
         $driver = 'Horde_Core_Auth_Msad';
     } elseif (strcasecmp($driver, 'shibboleth') === 0) {
         $driver = 'Horde_Core_Auth_Shibboleth';
     } elseif (strcasecmp($driver, 'imsp') === 0) {
         $driver = 'Horde_Core_Auth_Imsp';
     } elseif (strcasecmp($driver, 'x509') === 0) {
         $driver = 'Horde_Core_Auth_X509';
     } else {
         $driver = implode('_', array_map('Horde_String::ucwords', explode('_', Horde_String::lower(basename($driver)))));
     }
     $params = is_null($orig_params) ? Horde::getDriverConfig('auth', $driver) : $orig_params;
     $driver = $this->_getDriverName($driver, 'Horde_Auth');
     $lc_driver = Horde_String::lower($driver);
     switch ($lc_driver) {
         case 'horde_core_auth_composite':
             // Both of these params are required, but we need to skip if
             // non-existent to return a useful error message later.
             if (!empty($params['admin_driver'])) {
                 $params['admin_driver'] = $this->_create($params['admin_driver']['driver'], $params['admin_driver']['params']);
             }
             if (!empty($params['auth_driver'])) {
                 $params['auth_driver'] = $this->_create($params['auth_driver']['driver'], $params['auth_driver']['params']);
             }
             break;
         case 'horde_auth_cyrsql':
             $imap_config = array('hostspec' => empty($params['cyrhost']) ? null : $params['cyrhost'], 'password' => $params['cyrpass'], 'port' => empty($params['cyrport']) ? null : $params['cyrport'], 'secure' => $params['secure'] == 'none' ? null : $params['secure'], 'username' => $params['cyradmin']);
             try {
                 $ob = new Horde_Imap_Client_Socket($imap_config);
                 $ob->login();
                 $params['imap'] = $ob;
             } catch (Horde_Imap_Client_Exception $e) {
                 throw new Horde_Auth_Exception($e);
             }
             $params['db'] = $this->_injector->getInstance('Horde_Core_Factory_Db')->create('horde', is_null($orig_params) ? 'auth' : $orig_params);
             break;
         case 'horde_auth_http_remote':
             $params['client'] = $this->_injector->getInstance('Horde_Core_Factory_HttpClient')->create();
             break;
         case 'horde_core_auth_application':
             if (isset($this->_instances[$params['app']])) {
                 return $this->_instances[$params['app']];
             }
             break;
         case 'horde_core_auth_imsp':
             $params['imsp'] = $this->_injector->getInstance('Horde_Core_Factory_Imsp')->create();
             break;
         case 'horde_auth_kolab':
             $params['kolab'] = $this->_injector->getInstance('Horde_Kolab_Session');
             break;
         case 'horde_core_auth_ldap':
         case 'horde_core_auth_msad':
             $params['ldap'] = $this->_injector->getInstance('Horde_Core_Factory_Ldap')->create('horde', is_null($orig_params) ? 'auth' : $orig_params);
             break;
         case 'horde_core_auth_x509':
             if (!empty($params['password_source']) && $params['password_source'] == 'unified') {
                 $params['password'] = $params['unified_password'];
                 unset($params['password_source'], $params['unified_password']);
             }
             // @TODO: Add filters
             break;
         case 'horde_auth_customsql':
         case 'horde_auth_sql':
             $params['db'] = $this->_injector->getInstance('Horde_Core_Factory_Db')->create('horde', is_null($orig_params) ? 'auth' : $orig_params);
             break;
     }
     $params['default_user'] = $GLOBALS['registry']->getAuth();
     $params['logger'] = $this->_injector->getInstance('Horde_Log_Logger');
     if (!empty($params['count_bad_logins'])) {
         $params['history_api'] = $this->_injector->getInstance('Horde_History');
     }
     if (!empty($params['login_block'])) {
         $params['lock_api'] = $this->_injector->getInstance('Horde_Lock');
     }
     $auth_ob = new $driver($params);
     if ($lc_driver == 'horde_core_auth_application') {
         $this->_instances[$params['app']] = $auth_ob;
     }
     return $auth_ob;
 }
コード例 #8
0
ファイル: mailbox.php プロジェクト: netcon-source/apps
 private function getStatus($flags = \Horde_Imap_Client::STATUS_ALL)
 {
     return $this->conn->status($this->folder_id, $flags);
 }
コード例 #9
0
ファイル: mail.php プロジェクト: blablubli/owncloudapps
 private static function getImapConnection($account)
 {
     //
     // TODO: cash connections for / within accounts???
     //
     $host = $account['host'];
     $user = $account['user'];
     $password = $account['password'];
     $port = $account['port'];
     $ssl_mode = $account['ssl_mode'];
     $client = new \Horde_Imap_Client_Socket(array('username' => $user, 'password' => $password, 'hostspec' => $host, 'port' => $port, 'secure' => $ssl_mode));
     $client->login();
     return $client;
 }