If you're using a remote storage and have some long tasks you might need to keep the connection alive via noop:
<?php
foreach ($mail as $message) {
// do some calculations ...
$mail->noop(); // keep alive
// do something else ...
$mail->noop(); // keep alive
}
Zend_Mail_Storage_Mbox,
Zend_Mail_Storage_Folder_Mbox,
Zend_Mail_Storage_Maildir and
Zend_Mail_Storage_Folder_Maildir implement the magic methods
__sleep() and __wakeup(), 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.
<?php
// 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);
Remote storages use two classes:
Zend_Mail_Storage_<Name> and
Zend_Mail_Protocol_<Name>. The protocol class
translates the protocol commands and responses from and to PHP,
like methods for the commands or variables with different structures for data.
The other/main class implements the common interface.
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.
<?php
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)));
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.
Zend_Mail_Storage_Writable_Maildir 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
appendMessage(), removeMessage()
and copyMessage() 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.
There are three methods used for quotas: getQuota(),
setQuota() and checkQuota():
<?php
$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";
checkQuota() can also return a more detailed response:
<?php
$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';
If you want to specify your own quota instead of using the one specified in the
maildirsize file you can do with setQuota():
<?php
// message count and octet size supported, order does matter
$quota = $mail->setQuota(array('size' => 10000, 'count' => 100));
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
Zend_Mail_Storage_Writable_Maildir to define your own quota
only if the maildirsize file is missing (which can happen in Maildir++):
<?php
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);
}
}
}




