| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839 |
- <?xml version="1.0" encoding="UTF-8"?>
- <!-- Reviewed: no -->
- <sect1 id="zend.mail.read">
- <title>Reading Mail Messages</title>
- <para>
- <classname>Zend_Mail</classname> can read mail messages from several local or remote mail
- storages. All of them have the same basic <acronym>API</acronym> to count and fetch messages
- and some of them implement additional interfaces for not so common features. For a feature
- overview of the implemented storages, see the following table.
- </para>
- <table id="zend.mail.read.table-1">
- <title>Mail Read Feature Overview</title>
- <tgroup cols="5">
- <thead>
- <row>
- <entry>Feature</entry>
- <entry>Mbox</entry>
- <entry>Maildir</entry>
- <entry>Pop3</entry>
- <entry><constant>IMAP</constant></entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry>Storage type</entry>
- <entry>local</entry>
- <entry>local</entry>
- <entry>remote</entry>
- <entry>remote</entry>
- </row>
- <row>
- <entry>Fetch message</entry>
- <entry>Yes</entry>
- <entry>Yes</entry>
- <entry>Yes</entry>
- <entry>Yes</entry>
- </row>
- <row>
- <entry>Fetch <acronym>MIME</acronym>-part</entry>
- <entry>emulated</entry>
- <entry>emulated</entry>
- <entry>emulated</entry>
- <entry>emulated</entry>
- </row>
- <row>
- <entry>Folders</entry>
- <entry>Yes </entry>
- <entry>Yes</entry>
- <entry>No</entry>
- <entry>Yes</entry>
- </row>
- <row>
- <entry>Create message/folder</entry>
- <entry>No</entry>
- <entry>todo</entry>
- <entry>No</entry>
- <entry>todo</entry>
- </row>
- <row>
- <entry>Flags</entry>
- <entry>No</entry>
- <entry>Yes</entry>
- <entry>No</entry>
- <entry>Yes</entry>
- </row>
- <row>
- <entry>Quota</entry>
- <entry>No</entry>
- <entry>Yes</entry>
- <entry>No</entry>
- <entry>No</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- <sect2 id="zend.mail.read-example">
- <title>Simple example using Pop3</title>
- <programlisting language="php"><![CDATA[
- $mail = new Zend_Mail_Storage_Pop3(array('host' => 'localhost',
- 'user' => 'test',
- 'password' => 'test'));
- echo $mail->countMessages() . " messages found\n";
- foreach ($mail as $message) {
- echo "Mail from '{$message->from}': {$message->subject}\n";
- }
- ]]></programlisting>
- </sect2>
- <sect2 id="zend.mail.read-open-local">
- <title>Opening a local storage</title>
- <para>
- Mbox and Maildir are the two supported formats for local mail storages, both in their
- most simple formats.
- </para>
- <para>
- If you want to read from a Mbox file you only need to give the filename to the
- constructor of <classname>Zend_Mail_Storage_Mbox</classname>:
- </para>
- <programlisting language="php"><![CDATA[
- $mail = new Zend_Mail_Storage_Mbox(array('filename' =>
- '/home/test/mail/inbox'));
- ]]></programlisting>
- <para>Maildir is very similar but needs a dirname:</para>
- <programlisting language="php"><![CDATA[
- $mail = new Zend_Mail_Storage_Maildir(array('dirname' =>
- '/home/test/mail/'));
- ]]></programlisting>
- <para>
- Both constructors throw a <classname>Zend_Mail_Exception</classname> if the storage
- can't be read.
- </para>
- </sect2>
- <sect2 id="zend.mail.read-open-remote">
- <title>Opening a remote storage</title>
- <para>
- For remote storages the two most popular protocols are supported: Pop3 and Imap. Both
- need at least a host and a user to connect and login. The default password is an empty
- string, the default port as given in the protocol <acronym>RFC</acronym>.
- </para>
- <programlisting language="php"><![CDATA[
- // connecting with Pop3
- $mail = new Zend_Mail_Storage_Pop3(array('host' => 'example.com',
- 'user' => 'test',
- 'password' => 'test'));
- // connecting with Imap
- $mail = new Zend_Mail_Storage_Imap(array('host' => 'example.com',
- 'user' => 'test',
- 'password' => 'test'));
- // example for a none standard port
- $mail = new Zend_Mail_Storage_Pop3(array('host' => 'example.com',
- 'port' => 1120
- 'user' => 'test',
- 'password' => 'test'));
- ]]></programlisting>
- <para>
- For both storages <acronym>SSL</acronym> and TLS are supported. If you use
- <acronym>SSL</acronym> the default port changes as given in the <acronym>RFC</acronym>.
- </para>
- <programlisting language="php"><![CDATA[
- // examples for Zend_Mail_Storage_Pop3, same works for Zend_Mail_Storage_Imap
- // use SSL on different port (default is 995 for Pop3 and 993 for Imap)
- $mail = new Zend_Mail_Storage_Pop3(array('host' => 'example.com',
- 'user' => 'test',
- 'password' => 'test',
- 'ssl' => 'SSL'));
- // use TLS
- $mail = new Zend_Mail_Storage_Pop3(array('host' => 'example.com',
- 'user' => 'test',
- 'password' => 'test',
- 'ssl' => 'TLS'));
- ]]></programlisting>
- <para>
- Both constructors can throw <classname>Zend_Mail_Exception</classname> or
- <classname>Zend_Mail_Protocol_Exception</classname> (extends
- <classname>Zend_Mail_Exception</classname>), depending on the type of error.
- </para>
- </sect2>
- <sect2 id="zend.mail.read-fetching">
- <title>Fetching messages and simple methods</title>
- <para>
- Messages can be fetched after you've opened the storage . You need the message number,
- which is a counter starting with 1 for the first message. To fetch the message, you use
- the method <methodname>getMessage()</methodname>:
- </para>
- <programlisting language="php"><![CDATA[
- $message = $mail->getMessage($messageNum);
- ]]></programlisting>
- <para>
- Array access is also supported, but this access method won't supported any additional
- parameters that could be added to <methodname>getMessage()</methodname>. As long as you
- don't mind, and can live with the default values, you may use:
- </para>
- <programlisting language="php"><![CDATA[
- $message = $mail[$messageNum];
- ]]></programlisting>
- <para>For iterating over all messages the Iterator interface is implemented:</para>
- <programlisting language="php"><![CDATA[
- foreach ($mail as $messageNum => $message) {
- // do stuff ...
- }
- ]]></programlisting>
- <para>
- To count the messages in the storage, you can either use the method
- <methodname>countMessages()</methodname> or use array access:
- </para>
- <programlisting language="php"><![CDATA[
- // method
- $maxMessage = $mail->countMessages();
- // array access
- $maxMessage = count($mail);
- ]]></programlisting>
- <para>
- To remove a mail, you use the method <methodname>removeMessage()</methodname> or again
- array access:
- </para>
- <programlisting language="php"><![CDATA[
- // method
- $mail->removeMessage($messageNum);
- // array access
- unset($mail[$messageNum]);
- ]]></programlisting>
- </sect2>
- <sect2 id="zend.mail.read-message">
- <title>Working with messages</title>
- <para>
- After you fetch the messages with <methodname>getMessage()</methodname> you want to
- fetch headers, the content or single parts of a multipart message. All headers can be
- accessed via properties or the method <methodname>getHeader()</methodname> if you want
- more control or have unusual header names. The header names are lower-cased internally,
- thus the case of the header name in the mail message doesn't matter. Also headers with a
- dash can be written in camel-case. If no header is found for both notations an exception
- is thrown. To encounter this the method <methodname>headerExists()</methodname> can be
- used to check the existence of a header.
- </para>
- <programlisting language="php"><![CDATA[
- // get the message object
- $message = $mail->getMessage(1);
- // output subject of message
- echo $message->subject . "\n";
- // get content-type header
- $type = $message->contentType;
- // check if CC isset:
- if( isset($message->cc) ) { // or $message->headerExists('cc');
- $cc = $message->cc;
- }
- ]]></programlisting>
- <para>
- If you have multiple headers with the same name- i.e. the Received headers- you might
- want an array instead of a string. In this case, use the
- <methodname>getHeader()</methodname> method.
- </para>
- <programlisting language="php"><![CDATA[
- // get header as property - the result is always a string,
- // with new lines between the single occurrences in the message
- $received = $message->received;
- // the same via getHeader() method
- $received = $message->getHeader('received', 'string');
- // better an array with a single entry for every occurrences
- $received = $message->getHeader('received', 'array');
- foreach ($received as $line) {
- // do stuff
- }
- // if you don't define a format you'll get the internal representation
- // (string for single headers, array for multiple)
- $received = $message->getHeader('received');
- if (is_string($received)) {
- // only one received header found in message
- }
- ]]></programlisting>
- <para>
- The method <methodname>getHeaders()</methodname> returns all headers as array with the
- lower-cased name as key and the value as and array for multiple headers or as string for
- single headers.
- </para>
- <programlisting language="php"><![CDATA[
- // dump all headers
- foreach ($message->getHeaders() as $name => $value) {
- if (is_string($value)) {
- echo "$name: $value\n";
- continue;
- }
- foreach ($value as $entry) {
- echo "$name: $entry\n";
- }
- }
- ]]></programlisting>
- <para>
- If you don't have a multipart message, fetching the content is easily done via
- <methodname>getContent()</methodname>. Unlike the headers, the content is only fetched
- when needed (aka late-fetch).
- </para>
- <programlisting language="php"><![CDATA[
- // output message content for HTML
- echo '<pre>';
- echo $message->getContent();
- echo '</pre>';
- ]]></programlisting>
- <para>
- Checking for multipart messages is done with the method
- <methodname>isMultipart()</methodname>. If you have multipart message you can get an
- instance of <classname>Zend_Mail_Part</classname> with the method
- <methodname>getPart()</methodname>. <classname>Zend_Mail_Part</classname> is the base
- class of <classname>Zend_Mail_Message</classname>, so you have the same methods:
- <methodname>getHeader()</methodname>, <methodname>getHeaders()</methodname>,
- <methodname>getContent()</methodname>, <methodname>getPart()</methodname>,
- <methodname>isMultipart()</methodname> and the properties for headers.
- </para>
- <programlisting language="php"><![CDATA[
- // get the first none multipart part
- $part = $message;
- while ($part->isMultipart()) {
- $part = $message->getPart(1);
- }
- echo 'Type of this part is ' . strtok($part->contentType, ';') . "\n";
- echo "Content:\n";
- echo $part->getContent();
- ]]></programlisting>
- <para>
- <classname>Zend_Mail_Part</classname> also implements
- <classname>RecursiveIterator</classname>, which makes it easy to scan through all
- parts. And for easy output, it also implements the magic method
- <methodname>__toString()</methodname>, which returns the content.
- </para>
- <programlisting language="php"><![CDATA[
- // output first text/plain part
- $foundPart = null;
- foreach (new RecursiveIteratorIterator($mail->getMessage(1)) as $part) {
- try {
- if (strtok($part->contentType, ';') == 'text/plain') {
- $foundPart = $part;
- break;
- }
- } catch (Zend_Mail_Exception $e) {
- // ignore
- }
- }
- if (!$foundPart) {
- echo 'no plain text part found';
- } else {
- echo "plain text part: \n" . $foundPart;
- }
- ]]></programlisting>
- </sect2>
- <sect2 id="zend.mail.read-flags">
- <title>Checking for flags</title>
- <para>
- Maildir and IMAP support storing flags. The class
- <classname>Zend_Mail_Storage</classname> has constants for all known maildir and IMAP
- system flags, named <classname>Zend_Mail_Storage::FLAG_<flagname></classname>. To
- check for flags <classname>Zend_Mail_Message</classname> has a method called
- <methodname>hasFlag()</methodname>. With <methodname>getFlags()</methodname> you'll get
- all set flags.
- </para>
- <programlisting language="php"><![CDATA[
- // find unread messages
- echo "Unread mails:\n";
- foreach ($mail as $message) {
- if ($message->hasFlag(Zend_Mail_Storage::FLAG_SEEN)) {
- continue;
- }
- // mark recent/new mails
- if ($message->hasFlag(Zend_Mail_Storage::FLAG_RECENT)) {
- echo '! ';
- } else {
- echo ' ';
- }
- echo $message->subject . "\n";
- }
- // check for known flags
- $flags = $message->getFlags();
- echo "Message is flagged as: ";
- foreach ($flags as $flag) {
- switch ($flag) {
- case Zend_Mail_Storage::FLAG_ANSWERED:
- echo 'Answered ';
- break;
- case Zend_Mail_Storage::FLAG_FLAGGED:
- echo 'Flagged ';
- break;
- // ...
- // check for other flags
- // ...
- default:
- echo $flag . '(unknown flag) ';
- }
- }
- ]]></programlisting>
- <para>
- As IMAP allows user or client defined flags, you could get flags that don't have a
- constant in <classname>Zend_Mail_Storage</classname>. Instead, they are returned as
- strings and can be checked the same way with <methodname>hasFlag()</methodname>.
- </para>
- <programlisting language="php"><![CDATA[
- // check message for client defined flags $IsSpam, $SpamTested
- if (!$message->hasFlag('$SpamTested')) {
- echo 'message has not been tested for spam';
- } else if ($message->hasFlag('$IsSpam')) {
- echo 'this message is spam';
- } else {
- echo 'this message is ham';
- }
- ]]></programlisting>
- </sect2>
- <sect2 id="zend.mail.read-folders">
- <title>Using folders</title>
- <para>
- All storages, except Pop3, support folders, also called mailboxes. The interface
- implemented by all storages supporting folders is called
- <classname>Zend_Mail_Storage_Folder_Interface</classname>. Also all of these classes
- have an additional optional parameter called <property>folder</property>, which is the
- folder selected after login, in the constructor.
- </para>
- <para>
- For the local storages you need to use separate classes called
- <classname>Zend_Mail_Storage_Folder_Mbox</classname> or
- <classname>Zend_Mail_Storage_Folder_Maildir</classname>. Both need one parameter called
- <property>dirname</property> with the name of the base dir. The format for maildir is as
- defined in maildir++ (with a dot as default delimiter), Mbox is a directory hierarchy
- with Mbox files. If you don't have a Mbox file called INBOX in your Mbox base dir you
- need to set another folder in the constructor.
- </para>
- <para>
- <classname>Zend_Mail_Storage_Imap</classname> already supports folders by default.
- Examples for opening these storages:
- </para>
- <programlisting language="php"><![CDATA[
- // mbox with folders
- $mail = new Zend_Mail_Storage_Folder_Mbox(array('dirname' =>
- '/home/test/mail/'));
- // mbox with a default folder not called INBOX, also works
- // with Zend_Mail_Storage_Folder_Maildir and Zend_Mail_Storage_Imap
- $mail = new Zend_Mail_Storage_Folder_Mbox(array('dirname' =>
- '/home/test/mail/',
- 'folder' =>
- 'Archive'));
- // maildir with folders
- $mail = new Zend_Mail_Storage_Folder_Maildir(array('dirname' =>
- '/home/test/mail/'));
- // maildir with colon as delimiter, as suggested in Maildir++
- $mail = new Zend_Mail_Storage_Folder_Maildir(array('dirname' =>
- '/home/test/mail/',
- 'delim' => ':'));
- // imap is the same with and without folders
- $mail = new Zend_Mail_Storage_Imap(array('host' => 'example.com',
- 'user' => 'test',
- 'password' => 'test'));
- ]]></programlisting>
- <para>
- With the method getFolders($root = null) you can get the folder hierarchy starting with
- the root folder or the given folder. It's returned as an instance of
- <classname>Zend_Mail_Storage_Folder</classname>, which implements
- <classname>RecursiveIterator</classname> and all children are also instances of
- <classname>Zend_Mail_Storage_Folder</classname>. Each of these instances has a local and
- a global name returned by the methods <methodname>getLocalName()</methodname> and
- <methodname>getGlobalName()</methodname>. The global name is the absolute name from the
- root folder (including delimiters), the local name is the name in the parent folder.
- </para>
- <table id="zend.mail.read-folders.table-1">
- <title>Mail Folder Names</title>
- <tgroup cols="2">
- <thead>
- <row>
- <entry>Global Name</entry>
- <entry>Local Name</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry>/INBOX</entry>
- <entry>INBOX</entry>
- </row>
- <row>
- <entry>/Archive/2005</entry>
- <entry>2005</entry>
- </row>
- <row>
- <entry>List.ZF.General</entry>
- <entry>General</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- <para>
- If you use the iterator, the key of the current element is the local name. The global
- name is also returned by the magic method <methodname>__toString()</methodname>. Some
- folders may not be selectable, which means they can't store messages and selecting them
- results in an error. This can be checked with the method
- <methodname>isSelectable()</methodname>. So it's very easy to output the whole tree in a
- view:
- </para>
- <programlisting language="php"><![CDATA[
- $folders = new RecursiveIteratorIterator($this->mail->getFolders(),
- RecursiveIteratorIterator::SELF_FIRST);
- echo '<select name="folder">';
- foreach ($folders as $localName => $folder) {
- $localName = str_pad('', $folders->getDepth(), '-', STR_PAD_LEFT) .
- $localName;
- echo '<option';
- if (!$folder->isSelectable()) {
- echo ' disabled="disabled"';
- }
- echo ' value="' . htmlspecialchars($folder) . '">'
- . htmlspecialchars($localName) . '</option>';
- }
- echo '</select>';
- ]]></programlisting>
- <para>
- The current selected folder is returned by the method
- <methodname>getCurrentFolder()</methodname>. Changing the folder is done with the
- method <methodname>selectFolder()</methodname>, which needs the global name as
- parameter. If you want to avoid to write delimiters you can also use the properties of a
- <classname>Zend_Mail_Storage_Folder</classname> instance:
- </para>
- <programlisting language="php"><![CDATA[
- // depending on your mail storage and its settings $rootFolder->Archive->2005
- // is the same as:
- // /Archive/2005
- // Archive:2005
- // INBOX.Archive.2005
- // ...
- $folder = $mail->getFolders()->Archive->2005;
- echo 'Last folder was '
- . $mail->getCurrentFolder()
- . "new folder is $folder\n";
- $mail->selectFolder($folder);
- ]]></programlisting>
- </sect2>
- <sect2 id="zend.mail.read-advanced">
- <title>Advanced Use</title>
- <sect3 id="zend.mail.read-advanced.noop">
- <title>Using NOOP</title>
- <para>
- If you're using a remote storage and have some long tasks you might need to keep
- the connection alive via noop:
- </para>
- <programlisting language="php"><![CDATA[
- foreach ($mail as $message) {
- // do some calculations ...
- $mail->noop(); // keep alive
- // do something else ...
- $mail->noop(); // keep alive
- }
- ]]></programlisting>
- </sect3>
- <sect3 id="zend.mail.read-advanced.caching">
- <title>Caching instances</title>
- <para>
- <classname>Zend_Mail_Storage_Mbox</classname>,
- <classname>Zend_Mail_Storage_Folder_Mbox</classname>,
- <classname>Zend_Mail_Storage_Maildir</classname> and
- <classname>Zend_Mail_Storage_Folder_Maildir</classname> implement the magic methods
- <methodname>__sleep()</methodname> and <methodname>__wakeup()</methodname>, which
- means they are serializable. This avoids parsing the files or directory tree more
- than once. The disadvantage is that your Mbox or Maildir storage should not change.
- Some easy checks may be done, like reparsing the current Mbox file if the
- modification time changes, or reparsing the folder structure if a folder has
- vanished (which still results in an error, but you can search for another folder
- afterwards). It's better if you have something like a signal file for changes and
- check it before using the cached instance.
- </para>
- <programlisting language="php"><![CDATA[
- // there's no specific cache handler/class used here,
- // change the code to match your cache handler
- $signal_file = '/home/test/.mail.last_change';
- $mbox_basedir = '/home/test/mail/';
- $cache_id = 'example mail cache ' . $mbox_basedir . $signal_file;
- $cache = new Your_Cache_Class();
- if (!$cache->isCached($cache_id) ||
- filemtime($signal_file) > $cache->getMTime($cache_id)) {
- $mail = new Zend_Mail_Storage_Folder_Pop3(array('dirname' =>
- $mbox_basedir));
- } else {
- $mail = $cache->get($cache_id);
- }
- // do stuff ...
- $cache->set($cache_id, $mail);
- ]]></programlisting>
- </sect3>
- <sect3 id="zend.mail.read-advanced.extending">
- <title>Extending Protocol Classes</title>
- <para>
- Remote storages use two classes:
- <classname>Zend_Mail_Storage_<Name></classname> and
- <classname>Zend_Mail_Protocol_<Name></classname>. The protocol class
- translates the protocol commands and responses from and to <acronym>PHP</acronym>,
- like methods for the commands or variables with different structures for data.
- The other/main class implements the common interface.
- </para>
- <para>
- If you need additional protocol features, you can extend the protocol class and use
- it in the constructor of the main class. As an example, assume we need to knock
- different ports before we can connect to POP3.
- </para>
- <programlisting language="php"><![CDATA[
- class Example_Mail_Exception extends Zend_Mail_Exception
- {
- }
- class Example_Mail_Protocol_Exception extends Zend_Mail_Protocol_Exception
- {
- }
- class Example_Mail_Protocol_Pop3_Knock extends Zend_Mail_Protocol_Pop3
- {
- private $host, $port;
- public function __construct($host, $port = null)
- {
- // no auto connect in this class
- $this->host = $host;
- $this->port = $port;
- }
- public function knock($port)
- {
- $sock = @fsockopen($this->host, $port);
- if ($sock) {
- fclose($sock);
- }
- }
- public function connect($host = null, $port = null, $ssl = false)
- {
- if ($host === null) {
- $host = $this->host;
- }
- if ($port === null) {
- $port = $this->port;
- }
- parent::connect($host, $port);
- }
- }
- class Example_Mail_Pop3_Knock extends Zend_Mail_Storage_Pop3
- {
- public function __construct(array $params)
- {
- // ... check $params here! ...
- $protocol = new Example_Mail_Protocol_Pop3_Knock($params['host']);
- // do our "special" thing
- foreach ((array)$params['knock_ports'] as $port) {
- $protocol->knock($port);
- }
- // get to correct state
- $protocol->connect($params['host'], $params['port']);
- $protocol->login($params['user'], $params['password']);
- // initialize parent
- parent::__construct($protocol);
- }
- }
- $mail = new Example_Mail_Pop3_Knock(array('host' => 'localhost',
- 'user' => 'test',
- 'password' => 'test',
- 'knock_ports' =>
- array(1101, 1105, 1111)));
- ]]></programlisting>
- <para>
- As you see, we always assume we're connected, logged in and, if supported, a folder
- is selected in the constructor of the main class. Thus if you assign your own
- protocol class, you always need to make sure that's done or the next method will
- fail if the server doesn't allow it in the current state.
- </para>
- </sect3>
- <sect3 id="zend.mail.read-advanced.quota">
- <title>Using Quota (since 1.5)</title>
- <para>
- <classname>Zend_Mail_Storage_Writable_Maildir</classname> has support for Maildir++
- quotas. It's disabled by default, but it's possible to use it manually, if the
- automatic checks are not desired (this means
- <methodname>appendMessage()</methodname>, <methodname>removeMessage()</methodname>
- and <methodname>copyMessage()</methodname> do no checks and do not add entries to
- the maildirsize file). If enabled, an exception is thrown if you try to write to the
- maildir and it's already over quota.
- </para>
- <para>
- There are three methods used for quotas: <methodname>getQuota()</methodname>,
- <methodname>setQuota()</methodname> and <methodname>checkQuota()</methodname>:
- </para>
- <programlisting language="php"><![CDATA[
- $mail = new Zend_Mail_Storage_Writable_Maildir(array('dirname' =>
- '/home/test/mail/'));
- $mail->setQuota(true); // true to enable, false to disable
- echo 'Quota check is now ', $mail->getQuota() ? 'enabled' : 'disabled', "\n";
- // check quota can be used even if quota checks are disabled
- echo 'You are ', $mail->checkQuota() ? 'over quota' : 'not over quota', "\n";
- ]]></programlisting>
- <para>
- <methodname>checkQuota()</methodname> can also return a more detailed response:
- </para>
- <programlisting language="php"><![CDATA[
- $quota = $mail->checkQuota(true);
- echo 'You are ', $quota['over_quota'] ? 'over quota' : 'not over quota', "\n";
- echo 'You have ',
- $quota['count'],
- ' of ',
- $quota['quota']['count'],
- ' messages and use ';
- echo $quota['size'], ' of ', $quota['quota']['size'], ' octets';
- ]]></programlisting>
- <para>
- If you want to specify your own quota instead of using the one specified in the
- maildirsize file you can do with <methodname>setQuota()</methodname>:
- </para>
- <programlisting language="php"><![CDATA[
- // message count and octet size supported, order does matter
- $quota = $mail->setQuota(array('size' => 10000, 'count' => 100));
- ]]></programlisting>
- <para>
- To add your own quota checks use single letters as keys, and they will be preserved
- (but obviously not checked). It's also possible to extend
- <classname>Zend_Mail_Storage_Writable_Maildir</classname> to define your own quota
- only if the maildirsize file is missing (which can happen in Maildir++):
- </para>
- <programlisting language="php"><![CDATA[
- class Example_Mail_Storage_Maildir extends Zend_Mail_Storage_Writable_Maildir {
- // getQuota is called with $fromStorage = true by quota checks
- public function getQuota($fromStorage = false) {
- try {
- return parent::getQuota($fromStorage);
- } catch (Zend_Mail_Storage_Exception $e) {
- if (!$fromStorage) {
- // unknown error:
- throw $e;
- }
- // maildirsize file must be missing
- list($count, $size) = get_quota_from_somewhere_else();
- return array('count' => $count, 'size' => $size);
- }
- }
- }
- ]]></programlisting>
- </sect3>
- </sect2>
- </sect1>
- <!--
- vim:se ts=4 sw=4 et:
- -->
|