web/lib/Zend/Mail/Storage/Imap.php
changeset 64 162c1de6545a
parent 19 1c2f13fd785c
child 68 ecaf28ffe26e
equal deleted inserted replaced
63:5b37998e522e 64:162c1de6545a
       
     1 <?php
       
     2 /**
       
     3  * Zend Framework
       
     4  *
       
     5  * LICENSE
       
     6  *
       
     7  * This source file is subject to the new BSD license that is bundled
       
     8  * with this package in the file LICENSE.txt.
       
     9  * It is also available through the world-wide-web at this URL:
       
    10  * http://framework.zend.com/license/new-bsd
       
    11  * If you did not receive a copy of the license and are unable to
       
    12  * obtain it through the world-wide-web, please send an email
       
    13  * to license@zend.com so we can send you a copy immediately.
       
    14  *
       
    15  * @category   Zend
       
    16  * @package    Zend_Mail
       
    17  * @subpackage Storage
       
    18  * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
       
    19  * @license    http://framework.zend.com/license/new-bsd     New BSD License
       
    20  * @version    $Id: Imap.php 20096 2010-01-06 02:05:09Z bkarwin $
       
    21  */
       
    22 
       
    23 
       
    24 /**
       
    25  * @see Zend_Mail_Storage_Abstract
       
    26  */
       
    27 require_once 'Zend/Mail/Storage/Abstract.php';
       
    28 
       
    29 /**
       
    30  * @see Zend_Mail_Protocol_Imap
       
    31  */
       
    32 require_once 'Zend/Mail/Protocol/Imap.php';
       
    33 
       
    34 /**
       
    35  * @see Zend_Mail_Storage_Writable_Interface
       
    36  */
       
    37 require_once 'Zend/Mail/Storage/Writable/Interface.php';
       
    38 
       
    39 /**
       
    40  * @see Zend_Mail_Storage_Folder_Interface
       
    41  */
       
    42 require_once 'Zend/Mail/Storage/Folder/Interface.php';
       
    43 
       
    44 /**
       
    45  * @see Zend_Mail_Storage_Folder
       
    46  */
       
    47 require_once 'Zend/Mail/Storage/Folder.php';
       
    48 
       
    49 /**
       
    50  * @see Zend_Mail_Message
       
    51  */
       
    52 require_once 'Zend/Mail/Message.php';
       
    53 
       
    54 /**
       
    55  * @see Zend_Mail_Storage
       
    56  */
       
    57 require_once 'Zend/Mail/Storage.php';
       
    58 
       
    59 /**
       
    60  * @category   Zend
       
    61  * @package    Zend_Mail
       
    62  * @subpackage Storage
       
    63  * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
       
    64  * @license    http://framework.zend.com/license/new-bsd     New BSD License
       
    65  */
       
    66 class Zend_Mail_Storage_Imap extends Zend_Mail_Storage_Abstract
       
    67                              implements Zend_Mail_Storage_Folder_Interface, Zend_Mail_Storage_Writable_Interface
       
    68 {
       
    69     // TODO: with an internal cache we could optimize this class, or create an extra class with
       
    70     // such optimizations. Especially the various fetch calls could be combined to one cache call
       
    71 
       
    72     /**
       
    73      * protocol handler
       
    74      * @var null|Zend_Mail_Protocol_Imap
       
    75      */
       
    76     protected $_protocol;
       
    77 
       
    78     /**
       
    79      * name of current folder
       
    80      * @var string
       
    81      */
       
    82     protected $_currentFolder = '';
       
    83 
       
    84     /**
       
    85      * imap flags to constants translation
       
    86      * @var array
       
    87      */
       
    88     protected static $_knownFlags = array('\Passed'   => Zend_Mail_Storage::FLAG_PASSED,
       
    89                                           '\Answered' => Zend_Mail_Storage::FLAG_ANSWERED,
       
    90                                           '\Seen'     => Zend_Mail_Storage::FLAG_SEEN,
       
    91                                           '\Deleted'  => Zend_Mail_Storage::FLAG_DELETED,
       
    92                                           '\Draft'    => Zend_Mail_Storage::FLAG_DRAFT,
       
    93                                           '\Flagged'  => Zend_Mail_Storage::FLAG_FLAGGED);
       
    94 
       
    95     /**
       
    96      * map flags to search criterias
       
    97      * @var array
       
    98      */
       
    99     protected static $_searchFlags = array('\Recent'   => 'RECENT',
       
   100                                            '\Answered' => 'ANSWERED',
       
   101                                            '\Seen'     => 'SEEN',
       
   102                                            '\Deleted'  => 'DELETED',
       
   103                                            '\Draft'    => 'DRAFT',
       
   104                                            '\Flagged'  => 'FLAGGED');
       
   105 
       
   106     /**
       
   107      * Count messages all messages in current box
       
   108      *
       
   109      * @return int number of messages
       
   110      * @throws Zend_Mail_Storage_Exception
       
   111      * @throws Zend_Mail_Protocol_Exception
       
   112      */
       
   113     public function countMessages($flags = null)
       
   114     {
       
   115         if (!$this->_currentFolder) {
       
   116             /**
       
   117              * @see Zend_Mail_Storage_Exception
       
   118              */
       
   119             require_once 'Zend/Mail/Storage/Exception.php';
       
   120             throw new Zend_Mail_Storage_Exception('No selected folder to count');
       
   121         }
       
   122 
       
   123         if ($flags === null) {
       
   124             return count($this->_protocol->search(array('ALL')));
       
   125         }
       
   126 
       
   127         $params = array();
       
   128         foreach ((array)$flags as $flag) {
       
   129             if (isset(self::$_searchFlags[$flag])) {
       
   130                 $params[] = self::$_searchFlags[$flag];
       
   131             } else {
       
   132                 $params[] = 'KEYWORD';
       
   133                 $params[] = $this->_protocol->escapeString($flag);
       
   134             }
       
   135         }
       
   136         return count($this->_protocol->search($params));
       
   137     }
       
   138 
       
   139     /**
       
   140      * get a list of messages with number and size
       
   141      *
       
   142      * @param int $id number of message
       
   143      * @return int|array size of given message of list with all messages as array(num => size)
       
   144      * @throws Zend_Mail_Protocol_Exception
       
   145      */
       
   146     public function getSize($id = 0)
       
   147     {
       
   148         if ($id) {
       
   149             return $this->_protocol->fetch('RFC822.SIZE', $id);
       
   150         }
       
   151         return $this->_protocol->fetch('RFC822.SIZE', 1, INF);
       
   152     }
       
   153 
       
   154     /**
       
   155      * Fetch a message
       
   156      *
       
   157      * @param int $id number of message
       
   158      * @return Zend_Mail_Message
       
   159      * @throws Zend_Mail_Protocol_Exception
       
   160      */
       
   161     public function getMessage($id)
       
   162     {
       
   163         $data = $this->_protocol->fetch(array('FLAGS', 'RFC822.HEADER'), $id);
       
   164         $header = $data['RFC822.HEADER'];
       
   165 
       
   166         $flags = array();
       
   167         foreach ($data['FLAGS'] as $flag) {
       
   168             $flags[] = isset(self::$_knownFlags[$flag]) ? self::$_knownFlags[$flag] : $flag;
       
   169         }
       
   170 
       
   171         return new $this->_messageClass(array('handler' => $this, 'id' => $id, 'headers' => $header, 'flags' => $flags));
       
   172     }
       
   173 
       
   174     /*
       
   175      * Get raw header of message or part
       
   176      *
       
   177      * @param  int               $id       number of message
       
   178      * @param  null|array|string $part     path to part or null for messsage header
       
   179      * @param  int               $topLines include this many lines with header (after an empty line)
       
   180      * @param  int $topLines include this many lines with header (after an empty line)
       
   181      * @return string raw header
       
   182      * @throws Zend_Mail_Protocol_Exception
       
   183      * @throws Zend_Mail_Storage_Exception
       
   184      */
       
   185     public function getRawHeader($id, $part = null, $topLines = 0)
       
   186     {
       
   187         if ($part !== null) {
       
   188             // TODO: implement
       
   189             /**
       
   190              * @see Zend_Mail_Storage_Exception
       
   191              */
       
   192             require_once 'Zend/Mail/Storage/Exception.php';
       
   193             throw new Zend_Mail_Storage_Exception('not implemented');
       
   194         }
       
   195 
       
   196         // TODO: toplines
       
   197         return $this->_protocol->fetch('RFC822.HEADER', $id);
       
   198     }
       
   199 
       
   200     /*
       
   201      * Get raw content of message or part
       
   202      *
       
   203      * @param  int               $id   number of message
       
   204      * @param  null|array|string $part path to part or null for messsage content
       
   205      * @return string raw content
       
   206      * @throws Zend_Mail_Protocol_Exception
       
   207      * @throws Zend_Mail_Storage_Exception
       
   208      */
       
   209     public function getRawContent($id, $part = null)
       
   210     {
       
   211         if ($part !== null) {
       
   212             // TODO: implement
       
   213             /**
       
   214              * @see Zend_Mail_Storage_Exception
       
   215              */
       
   216             require_once 'Zend/Mail/Storage/Exception.php';
       
   217             throw new Zend_Mail_Storage_Exception('not implemented');
       
   218         }
       
   219 
       
   220         return $this->_protocol->fetch('RFC822.TEXT', $id);
       
   221     }
       
   222 
       
   223     /**
       
   224      * create instance with parameters
       
   225      * Supported paramters are
       
   226      *   - user username
       
   227      *   - host hostname or ip address of IMAP server [optional, default = 'localhost']
       
   228      *   - password password for user 'username' [optional, default = '']
       
   229      *   - port port for IMAP server [optional, default = 110]
       
   230      *   - ssl 'SSL' or 'TLS' for secure sockets
       
   231      *   - folder select this folder [optional, default = 'INBOX']
       
   232      *
       
   233      * @param  array $params mail reader specific parameters
       
   234      * @throws Zend_Mail_Storage_Exception
       
   235      * @throws Zend_Mail_Protocol_Exception
       
   236      */
       
   237     public function __construct($params)
       
   238     {
       
   239         if (is_array($params)) {
       
   240             $params = (object)$params;
       
   241         }
       
   242 
       
   243         $this->_has['flags'] = true;
       
   244 
       
   245         if ($params instanceof Zend_Mail_Protocol_Imap) {
       
   246             $this->_protocol = $params;
       
   247             try {
       
   248                 $this->selectFolder('INBOX');
       
   249             } catch(Zend_Mail_Storage_Exception $e) {
       
   250                 /**
       
   251                  * @see Zend_Mail_Storage_Exception
       
   252                  */
       
   253                 require_once 'Zend/Mail/Storage/Exception.php';
       
   254                 throw new Zend_Mail_Storage_Exception('cannot select INBOX, is this a valid transport?', 0, $e);
       
   255             }
       
   256             return;
       
   257         }
       
   258 
       
   259         if (!isset($params->user)) {
       
   260             /**
       
   261              * @see Zend_Mail_Storage_Exception
       
   262              */
       
   263             require_once 'Zend/Mail/Storage/Exception.php';
       
   264             throw new Zend_Mail_Storage_Exception('need at least user in params');
       
   265         }
       
   266 
       
   267         $host     = isset($params->host)     ? $params->host     : 'localhost';
       
   268         $password = isset($params->password) ? $params->password : '';
       
   269         $port     = isset($params->port)     ? $params->port     : null;
       
   270         $ssl      = isset($params->ssl)      ? $params->ssl      : false;
       
   271 
       
   272         $this->_protocol = new Zend_Mail_Protocol_Imap();
       
   273         $this->_protocol->connect($host, $port, $ssl);
       
   274         if (!$this->_protocol->login($params->user, $password)) {
       
   275             /**
       
   276              * @see Zend_Mail_Storage_Exception
       
   277              */
       
   278             require_once 'Zend/Mail/Storage/Exception.php';
       
   279             throw new Zend_Mail_Storage_Exception('cannot login, user or password wrong');
       
   280         }
       
   281         $this->selectFolder(isset($params->folder) ? $params->folder : 'INBOX');
       
   282     }
       
   283 
       
   284     /**
       
   285      * Close resource for mail lib. If you need to control, when the resource
       
   286      * is closed. Otherwise the destructor would call this.
       
   287      *
       
   288      * @return null
       
   289      */
       
   290     public function close()
       
   291     {
       
   292         $this->_currentFolder = '';
       
   293         $this->_protocol->logout();
       
   294     }
       
   295 
       
   296     /**
       
   297      * Keep the server busy.
       
   298      *
       
   299      * @return null
       
   300      * @throws Zend_Mail_Storage_Exception
       
   301      */
       
   302     public function noop()
       
   303     {
       
   304         if (!$this->_protocol->noop()) {
       
   305             /**
       
   306              * @see Zend_Mail_Storage_Exception
       
   307              */
       
   308             require_once 'Zend/Mail/Storage/Exception.php';
       
   309             throw new Zend_Mail_Storage_Exception('could not do nothing');
       
   310         }
       
   311     }
       
   312 
       
   313     /**
       
   314      * Remove a message from server. If you're doing that from a web enviroment
       
   315      * you should be careful and use a uniqueid as parameter if possible to
       
   316      * identify the message.
       
   317      *
       
   318      * @param   int $id number of message
       
   319      * @return  null
       
   320      * @throws  Zend_Mail_Storage_Exception
       
   321      */
       
   322     public function removeMessage($id)
       
   323     {
       
   324         if (!$this->_protocol->store(array(Zend_Mail_Storage::FLAG_DELETED), $id, null, '+')) {
       
   325             /**
       
   326              * @see Zend_Mail_Storage_Exception
       
   327              */
       
   328             require_once 'Zend/Mail/Storage/Exception.php';
       
   329             throw new Zend_Mail_Storage_Exception('cannot set deleted flag');
       
   330         }
       
   331         // TODO: expunge here or at close? we can handle an error here better and are more fail safe
       
   332         if (!$this->_protocol->expunge()) {
       
   333             /**
       
   334              * @see Zend_Mail_Storage_Exception
       
   335              */
       
   336             require_once 'Zend/Mail/Storage/Exception.php';
       
   337             throw new Zend_Mail_Storage_Exception('message marked as deleted, but could not expunge');
       
   338         }
       
   339     }
       
   340 
       
   341     /**
       
   342      * get unique id for one or all messages
       
   343      *
       
   344      * if storage does not support unique ids it's the same as the message number
       
   345      *
       
   346      * @param int|null $id message number
       
   347      * @return array|string message number for given message or all messages as array
       
   348      * @throws Zend_Mail_Storage_Exception
       
   349      */
       
   350     public function getUniqueId($id = null)
       
   351     {
       
   352         if ($id) {
       
   353             return $this->_protocol->fetch('UID', $id);
       
   354         }
       
   355 
       
   356         return $this->_protocol->fetch('UID', 1, INF);
       
   357     }
       
   358 
       
   359     /**
       
   360      * get a message number from a unique id
       
   361      *
       
   362      * I.e. if you have a webmailer that supports deleting messages you should use unique ids
       
   363      * as parameter and use this method to translate it to message number right before calling removeMessage()
       
   364      *
       
   365      * @param string $id unique id
       
   366      * @return int message number
       
   367      * @throws Zend_Mail_Storage_Exception
       
   368      */
       
   369     public function getNumberByUniqueId($id)
       
   370     {
       
   371         // TODO: use search to find number directly
       
   372         $ids = $this->getUniqueId();
       
   373         foreach ($ids as $k => $v) {
       
   374             if ($v == $id) {
       
   375                 return $k;
       
   376             }
       
   377         }
       
   378 
       
   379         /**
       
   380          * @see Zend_Mail_Storage_Exception
       
   381          */
       
   382         require_once 'Zend/Mail/Storage/Exception.php';
       
   383         throw new Zend_Mail_Storage_Exception('unique id not found');
       
   384     }
       
   385 
       
   386 
       
   387     /**
       
   388      * get root folder or given folder
       
   389      *
       
   390      * @param  string $rootFolder get folder structure for given folder, else root
       
   391      * @return Zend_Mail_Storage_Folder root or wanted folder
       
   392      * @throws Zend_Mail_Storage_Exception
       
   393      * @throws Zend_Mail_Protocol_Exception
       
   394      */
       
   395     public function getFolders($rootFolder = null)
       
   396     {
       
   397         $folders = $this->_protocol->listMailbox((string)$rootFolder);
       
   398         if (!$folders) {
       
   399             /**
       
   400              * @see Zend_Mail_Storage_Exception
       
   401              */
       
   402             require_once 'Zend/Mail/Storage/Exception.php';
       
   403             throw new Zend_Mail_Storage_Exception('folder not found');
       
   404         }
       
   405 
       
   406         ksort($folders, SORT_STRING);
       
   407         $root = new Zend_Mail_Storage_Folder('/', '/', false);
       
   408         $stack = array(null);
       
   409         $folderStack = array(null);
       
   410         $parentFolder = $root;
       
   411         $parent = '';
       
   412 
       
   413         foreach ($folders as $globalName => $data) {
       
   414             do {
       
   415                 if (!$parent || strpos($globalName, $parent) === 0) {
       
   416                     $pos = strrpos($globalName, $data['delim']);
       
   417                     if ($pos === false) {
       
   418                         $localName = $globalName;
       
   419                     } else {
       
   420                         $localName = substr($globalName, $pos + 1);
       
   421                     }
       
   422                     $selectable = !$data['flags'] || !in_array('\\Noselect', $data['flags']);
       
   423 
       
   424                     array_push($stack, $parent);
       
   425                     $parent = $globalName . $data['delim'];
       
   426                     $folder = new Zend_Mail_Storage_Folder($localName, $globalName, $selectable);
       
   427                     $parentFolder->$localName = $folder;
       
   428                     array_push($folderStack, $parentFolder);
       
   429                     $parentFolder = $folder;
       
   430                     break;
       
   431                 } else if ($stack) {
       
   432                     $parent = array_pop($stack);
       
   433                     $parentFolder = array_pop($folderStack);
       
   434                 }
       
   435             } while ($stack);
       
   436             if (!$stack) {
       
   437                 /**
       
   438                  * @see Zend_Mail_Storage_Exception
       
   439                  */
       
   440                 require_once 'Zend/Mail/Storage/Exception.php';
       
   441                 throw new Zend_Mail_Storage_Exception('error while constructing folder tree');
       
   442             }
       
   443         }
       
   444 
       
   445         return $root;
       
   446     }
       
   447 
       
   448     /**
       
   449      * select given folder
       
   450      *
       
   451      * folder must be selectable!
       
   452      *
       
   453      * @param  Zend_Mail_Storage_Folder|string $globalName global name of folder or instance for subfolder
       
   454      * @return null
       
   455      * @throws Zend_Mail_Storage_Exception
       
   456      * @throws Zend_Mail_Protocol_Exception
       
   457      */
       
   458     public function selectFolder($globalName)
       
   459     {
       
   460         $this->_currentFolder = $globalName;
       
   461         if (!$this->_protocol->select($this->_currentFolder)) {
       
   462             $this->_currentFolder = '';
       
   463             /**
       
   464              * @see Zend_Mail_Storage_Exception
       
   465              */
       
   466             require_once 'Zend/Mail/Storage/Exception.php';
       
   467             throw new Zend_Mail_Storage_Exception('cannot change folder, maybe it does not exist');
       
   468         }
       
   469     }
       
   470 
       
   471 
       
   472     /**
       
   473      * get Zend_Mail_Storage_Folder instance for current folder
       
   474      *
       
   475      * @return Zend_Mail_Storage_Folder instance of current folder
       
   476      * @throws Zend_Mail_Storage_Exception
       
   477      */
       
   478     public function getCurrentFolder()
       
   479     {
       
   480         return $this->_currentFolder;
       
   481     }
       
   482 
       
   483     /**
       
   484      * create a new folder
       
   485      *
       
   486      * This method also creates parent folders if necessary. Some mail storages may restrict, which folder
       
   487      * may be used as parent or which chars may be used in the folder name
       
   488      *
       
   489      * @param  string                          $name         global name of folder, local name if $parentFolder is set
       
   490      * @param  string|Zend_Mail_Storage_Folder $parentFolder parent folder for new folder, else root folder is parent
       
   491      * @return null
       
   492      * @throws Zend_Mail_Storage_Exception
       
   493      */
       
   494     public function createFolder($name, $parentFolder = null)
       
   495     {
       
   496         // TODO: we assume / as the hierarchy delim - need to get that from the folder class!
       
   497         if ($parentFolder instanceof Zend_Mail_Storage_Folder) {
       
   498             $folder = $parentFolder->getGlobalName() . '/' . $name;
       
   499         } else if ($parentFolder != null) {
       
   500             $folder = $parentFolder . '/' . $name;
       
   501         } else {
       
   502             $folder = $name;
       
   503         }
       
   504 
       
   505         if (!$this->_protocol->create($folder)) {
       
   506             /**
       
   507              * @see Zend_Mail_Storage_Exception
       
   508              */
       
   509             require_once 'Zend/Mail/Storage/Exception.php';
       
   510             throw new Zend_Mail_Storage_Exception('cannot create folder');
       
   511         }
       
   512     }
       
   513 
       
   514     /**
       
   515      * remove a folder
       
   516      *
       
   517      * @param  string|Zend_Mail_Storage_Folder $name      name or instance of folder
       
   518      * @return null
       
   519      * @throws Zend_Mail_Storage_Exception
       
   520      */
       
   521     public function removeFolder($name)
       
   522     {
       
   523         if ($name instanceof Zend_Mail_Storage_Folder) {
       
   524             $name = $name->getGlobalName();
       
   525         }
       
   526 
       
   527         if (!$this->_protocol->delete($name)) {
       
   528             /**
       
   529              * @see Zend_Mail_Storage_Exception
       
   530              */
       
   531             require_once 'Zend/Mail/Storage/Exception.php';
       
   532             throw new Zend_Mail_Storage_Exception('cannot delete folder');
       
   533         }
       
   534     }
       
   535 
       
   536     /**
       
   537      * rename and/or move folder
       
   538      *
       
   539      * The new name has the same restrictions as in createFolder()
       
   540      *
       
   541      * @param  string|Zend_Mail_Storage_Folder $oldName name or instance of folder
       
   542      * @param  string                          $newName new global name of folder
       
   543      * @return null
       
   544      * @throws Zend_Mail_Storage_Exception
       
   545      */
       
   546     public function renameFolder($oldName, $newName)
       
   547     {
       
   548         if ($oldName instanceof Zend_Mail_Storage_Folder) {
       
   549             $oldName = $oldName->getGlobalName();
       
   550         }
       
   551 
       
   552         if (!$this->_protocol->rename($oldName, $newName)) {
       
   553             /**
       
   554              * @see Zend_Mail_Storage_Exception
       
   555              */
       
   556             require_once 'Zend/Mail/Storage/Exception.php';
       
   557             throw new Zend_Mail_Storage_Exception('cannot rename folder');
       
   558         }
       
   559     }
       
   560 
       
   561     /**
       
   562      * append a new message to mail storage
       
   563      *
       
   564      * @param  string                                     $message message as string or instance of message class
       
   565      * @param  null|string|Zend_Mail_Storage_Folder       $folder  folder for new message, else current folder is taken
       
   566      * @param  null|array                                 $flags   set flags for new message, else a default set is used
       
   567      * @throws Zend_Mail_Storage_Exception
       
   568      */
       
   569      // not yet * @param string|Zend_Mail_Message|Zend_Mime_Message $message message as string or instance of message class
       
   570     public function appendMessage($message, $folder = null, $flags = null)
       
   571     {
       
   572         if ($folder === null) {
       
   573             $folder = $this->_currentFolder;
       
   574         }
       
   575 
       
   576         if ($flags === null) {
       
   577             $flags = array(Zend_Mail_Storage::FLAG_SEEN);
       
   578         }
       
   579 
       
   580         // TODO: handle class instances for $message
       
   581         if (!$this->_protocol->append($folder, $message, $flags)) {
       
   582             /**
       
   583              * @see Zend_Mail_Storage_Exception
       
   584              */
       
   585             require_once 'Zend/Mail/Storage/Exception.php';
       
   586             throw new Zend_Mail_Storage_Exception('cannot create message, please check if the folder exists and your flags');
       
   587         }
       
   588     }
       
   589 
       
   590     /**
       
   591      * copy an existing message
       
   592      *
       
   593      * @param  int                             $id     number of message
       
   594      * @param  string|Zend_Mail_Storage_Folder $folder name or instance of targer folder
       
   595      * @return null
       
   596      * @throws Zend_Mail_Storage_Exception
       
   597      */
       
   598     public function copyMessage($id, $folder)
       
   599     {
       
   600         if (!$this->_protocol->copy($folder, $id)) {
       
   601             /**
       
   602              * @see Zend_Mail_Storage_Exception
       
   603              */
       
   604             require_once 'Zend/Mail/Storage/Exception.php';
       
   605             throw new Zend_Mail_Storage_Exception('cannot copy message, does the folder exist?');
       
   606         }
       
   607     }
       
   608 
       
   609     /**
       
   610      * move an existing message
       
   611      *
       
   612      * NOTE: imap has no native move command, thus it's emulated with copy and delete
       
   613      *
       
   614      * @param  int                             $id     number of message
       
   615      * @param  string|Zend_Mail_Storage_Folder $folder name or instance of targer folder
       
   616      * @return null
       
   617      * @throws Zend_Mail_Storage_Exception
       
   618      */
       
   619     public function moveMessage($id, $folder) {
       
   620         $this->copyMessage($id, $folder);
       
   621         $this->removeMessage($id);
       
   622     }
       
   623 
       
   624     /**
       
   625      * set flags for message
       
   626      *
       
   627      * NOTE: this method can't set the recent flag.
       
   628      *
       
   629      * @param  int   $id    number of message
       
   630      * @param  array $flags new flags for message
       
   631      * @throws Zend_Mail_Storage_Exception
       
   632      */
       
   633     public function setFlags($id, $flags)
       
   634     {
       
   635         if (!$this->_protocol->store($flags, $id)) {
       
   636             /**
       
   637              * @see Zend_Mail_Storage_Exception
       
   638              */
       
   639             require_once 'Zend/Mail/Storage/Exception.php';
       
   640             throw new Zend_Mail_Storage_Exception('cannot set flags, have you tried to set the recent flag or special chars?');
       
   641         }
       
   642     }
       
   643 }
       
   644