Author: Alexandru Stanoi Date: 2007-02-28 13:42:42 +0100 (Wed, 28 Feb 2007) New Revision: 4696
Log: - Implemented feature request #8485: added the ezcMailStorageSet which wraps around another set and provides saving of mail sources. Added: trunk/Mail/src/transports/storage/ trunk/Mail/src/transports/storage/storage_set.php trunk/Mail/tests/transports/transport_storage_test.php Modified: trunk/Mail/ChangeLog trunk/Mail/src/mail_autoload.php trunk/Mail/src/transports/file/file_set.php trunk/Mail/src/transports/mbox/mbox_set.php trunk/Mail/src/transports/pop3/pop3_set.php trunk/Mail/src/transports/variable/var_set.php trunk/Mail/tests/suite.php Modified: trunk/Mail/ChangeLog =================================================================== --- trunk/Mail/ChangeLog 2007-02-28 08:25:07 UTC (rev 4695) +++ trunk/Mail/ChangeLog 2007-02-28 12:42:42 UTC (rev 4696) @@ -26,8 +26,10 @@ Based on a patch from Mikko Koppanen. - Implemented feature request #10091: added SSL/TLS support for the SMTP transport. Based on a patch from Christian Michel. +- Implemented feature request #8485: added the ezcMailStorageSet which wraps + around another set and provides saving of mail sources. - + 1.2.1 - [RELEASEDATE] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Modified: trunk/Mail/src/mail_autoload.php =================================================================== --- trunk/Mail/src/mail_autoload.php 2007-02-28 08:25:07 UTC (rev 4695) +++ trunk/Mail/src/mail_autoload.php 2007-02-28 12:42:42 UTC (rev 4696) @@ -44,6 +44,7 @@ 'ezcMailMboxSet' => 'Mail/transports/mbox/mbox_set.php', 'ezcMailFileSet' => 'Mail/transports/file/file_set.php', 'ezcMailVariableSet' => 'Mail/transports/variable/var_set.php', + 'ezcMailStorageSet' => 'Mail/transports/storage/storage_set.php', 'ezcMailException' => 'Mail/exceptions/mail_exception.php', 'ezcMailTransportException' => 'Mail/exceptions/transport_exception.php', Modified: trunk/Mail/src/transports/file/file_set.php =================================================================== --- trunk/Mail/src/transports/file/file_set.php 2007-02-28 08:25:07 UTC (rev 4695) +++ trunk/Mail/src/transports/file/file_set.php 2007-02-28 12:42:42 UTC (rev 4696) @@ -45,6 +45,16 @@ private $files = array(); /** + * This variable is true if there is more data in the mail that is being fetched. + * + * It is false if there is no mail being fetched currently or if all the data of the current mail + * has been fetched. + * + * @var bool + */ + private $hasMoreMailData = false; + + /** * Constructs a new set that servers the files specified by $files. * * The set will start on the first file in the the array. @@ -55,8 +65,7 @@ { $this->files = $files; reset( $this->files ); - - $this->openFile( true ); + $this->hasMoreMailData = false; } /** @@ -80,7 +89,7 @@ */ public function hasData() { - return count( $this->files ); + return ( count( $this->files ) >= 1 ) && ( filesize( $this->files[0] ) > 0 ); } /** @@ -93,6 +102,10 @@ */ public function getNextLine() { + if ( $this->hasMoreMailData === false ) + { + $this->nextMail(); + } // finished? if ( $this->fp == null || feof( $this->fp ) ) { @@ -122,6 +135,11 @@ */ public function nextMail() { + if ( $this->hasMoreMailData === false ) + { + $this->hasMoreMailData = true; + return $this->openFile( true ); + } return $this->openFile(); } Modified: trunk/Mail/src/transports/mbox/mbox_set.php =================================================================== --- trunk/Mail/src/transports/mbox/mbox_set.php 2007-02-28 08:25:07 UTC (rev 4695) +++ trunk/Mail/src/transports/mbox/mbox_set.php 2007-02-28 12:42:42 UTC (rev 4696) @@ -79,7 +79,6 @@ $this->hasMoreMailData = true; $this->messagePositions = $messages; $this->currentMessagePosition = 0; - $this->nextMail(); } /** @@ -103,6 +102,10 @@ */ public function getNextLine() { + if ( $this->currentMessagePosition === 0 ) + { + $this->nextMail(); + } if ( $this->hasMoreMailData ) { $data = fgets( $this->fh ); @@ -124,7 +127,7 @@ */ public function hasData() { - return $this->hasMoreMailData; + return ( $this->hasMoreMailData === true && count( $this->messagePositions ) > 0 ); } /** @@ -148,5 +151,15 @@ return true; } + + /** + * Returns message numbers for current set. + * + * @return array(int=>int) + */ + public function getMessageNumbers() + { + return array_keys( $this->messagePositions ); + } } ?> Modified: trunk/Mail/src/transports/pop3/pop3_set.php =================================================================== --- trunk/Mail/src/transports/pop3/pop3_set.php 2007-02-28 08:25:07 UTC (rev 4695) +++ trunk/Mail/src/transports/pop3/pop3_set.php 2007-02-28 12:42:42 UTC (rev 4696) @@ -52,6 +52,8 @@ /** * Holds if mail should be deleted from the server after retrieval. + * + * @var bool */ private $deleteFromServer = false; @@ -75,7 +77,6 @@ $this->connection = $connection; $this->messages = $messages; $this->deleteFromServer = $deleteFromServer; - $this->nextMail(); } /** @@ -98,6 +99,10 @@ */ public function getNextLine() { + if ( $this->currentMessage === null ) + { + $this->nextMail(); + } if ( $this->hasMoreMailData ) { $data = $this->connection->getLine(); @@ -110,7 +115,6 @@ $this->connection->sendData( "DELE {$this->currentMessage}" ); $response = $this->connection->getLine(); // ignore response } - return null; } return $data; @@ -137,8 +141,7 @@ { $this->currentMessage = next( $this->messages ); } - - if ( is_integer( $this->currentMessage ) ) + if ( $this->currentMessage !== false ) { $this->connection->sendData( "RETR {$this->currentMessage}" ); $response = $this->connection->getLine(); Added: trunk/Mail/src/transports/storage/storage_set.php =================================================================== --- trunk/Mail/src/transports/storage/storage_set.php 2007-02-28 08:25:07 UTC (rev 4695) +++ trunk/Mail/src/transports/storage/storage_set.php 2007-02-28 12:42:42 UTC (rev 4696) @@ -0,0 +1,223 @@ +<?php +/** + * File containing the ezcMailStorageSet class + * + * @package Mail + * @version //autogen// + * @copyright Copyright (C) 2005-2007 eZ systems as. All rights reserved. + * @license http://ez.no/licenses/new_bsd New BSD License + */ + +/** + * ezcMailStorageSet is a wrapper around other mail sets and provides saving of + * mail sources to files. + * + * Example: + * + * <code> + * // create a new POP3 transport object and a mail parser object + * $transport = new ezcMailPop3Transport( "server" ); + * $transport->authenticate( "username", "password" ); + * $parser = new ezcMailParser(); + * + * // wrap around the set returned by fetchAll() + * // and specify that the sources are to be saved in the folder /tmp/cache + * $set = new ezcMailStorageSet( $transport->fetchAll(), '/tmp/cache' ); + * + * // parse the storage set + * $mail = $parser->parseMail( $set ); + * + * // get the filenames of the saved mails in the set + * // this must be saved somewhere so it can be used on a subsequent request + * $files = $set->getSourceFiles(); + * + * // get the source of a the 4th saved mail + * // this can be on a subsequent request if the $files array was saved from + * // a previous request + * $source = file_get_contents( $files[3] ); + * </code> + * + * @package Mail + * @version //autogen// + */ +class ezcMailStorageSet implements ezcMailParserSet +{ + /** + * Holds the pointer to the current file which holds the mail source. + * + * @var filepointer + */ + private $writer = null; + + /** + * Holds the temporary file name where contents are being initially written + * (until set is parsed and Message-ID is extracted). + * + * @var string + */ + private $file = null; + + /** + * Holds the path where the files are written (specified in the constructor). + * + * @var string + */ + private $path = null; + + /** + * Holds the Message-ID of the current message, used to rename the mail source file. + * + * @var string + */ + private $id = null; + + /** + * This variable is true if there is more data in the mail that is being fetched. + * + * @var bool + */ + private $hasMoreMailData = false; + + /** + * Holds the location where to store the message sources. + * + * @var string + */ + private $location; + + /** + * Holds the filenames holding the sources of the mails in this set. + * + * @var array(string) + */ + private $files = null; + + /** + * Constructs a new storage set around the provided set. + * + * $location specifies where to save the message sources. This directory MUST + * exist and must be writable. + * + * @param ezcMailParserSet $set + * @param array(string=>mixed) $options + */ + public function __construct( ezcMailParserSet $set, $location ) + { + $this->set = $set; + $this->location = $location; + $this->path = rtrim( $this->location, DIRECTORY_SEPARATOR ) . DIRECTORY_SEPARATOR; + $this->hasMoreMailData = false; + } + + /** + * Destructs the set. + * + * Closes any open files. + */ + public function __destruct() + { + if ( $this->writer !== null ) + { + fclose( $this->writer ); + $this->writer = null; + } + } + + /** + * Returns one line of data from the current mail in the set. + * + * Null is returned if there is no current mail in the set or + * the end of the mail is reached, + * + * It also writes the line of data to the current file. If the line contains + * a Message-ID header then the value in the header will be used to rename the + * file. + * + * @return string + */ + public function getNextLine() + { + if ( $this->hasMoreMailData === false ) + { + $this->nextMail(); + $this->hasMoreMailData = true; + } + $line = $this->set->getNextLine(); + if ( $this->id === null && stripos( $line, 'message-id' ) !== false ) + { + // Temporary value in case the Message-ID cannot be extracted from $line + $this->id = $this->file; + preg_match_all( "/^([\w-_]*): (.*)/", $line, $matches, PREG_SET_ORDER ); + if ( count( $matches ) > 0 ) + { + $this->id = trim( trim( $matches[0][2] ), '<>' ); + } + } + fputs( $this->writer, $line ); + return $line; + } + + /** + * Moves the set to the next mail and returns true upon success. + * + * False is returned if there are no more mail in the set. + * + * @return bool + */ + public function nextMail() + { + if ( $this->writer !== null ) + { + fclose( $this->writer ); + if ( $this->id !== null ) + { + rename( $this->path . $this->file, $this->path . $this->id ); + $this->files[] = $this->path . $this->id; + } + else + { + $this->files[] = $this->path . $this->file; + } + $this->writer = null; + } + $this->id = null; + $mail = $this->set->nextMail(); + if ( $mail === true || $this->hasMoreMailData === false ) + { + // Temporary file name until message is parsed and Message-ID is extracted. + // It could remain the same if the mail doesn't contain a Message-ID header + $this->file = getmypid() . '.' . time(); + $writer = fopen( $this->path . $this->file, 'w' ); + if ( $writer !== false ) + { + $this->writer = $writer; + } + return $mail; + } + return false; + } + + /** + * Returns whether the set has mails. + * + * @return bool + */ + public function hasData() + { + return $this->set->hasData(); + } + + /** + * Returns an array of the filenames holding the sources of the mails in this set. + * + * The format of the returned array is: + * array( 0 => 'location/filename1', 1 => 'location/filename2',...) + * + * @return array(string) + */ + public function getSourceFiles() + { + return $this->files; + } +} +?> Property changes on: trunk/Mail/src/transports/storage/storage_set.php ___________________________________________________________________ Name: svn:eol-style + native Modified: trunk/Mail/src/transports/variable/var_set.php =================================================================== --- trunk/Mail/src/transports/variable/var_set.php 2007-02-28 08:25:07 UTC (rev 4695) +++ trunk/Mail/src/transports/variable/var_set.php 2007-02-28 12:42:42 UTC (rev 4696) @@ -88,7 +88,7 @@ */ public function hasData() { - return true; + return ( count( $this->mail ) > 1 ); } } ?> Modified: trunk/Mail/tests/suite.php =================================================================== --- trunk/Mail/tests/suite.php 2007-02-28 08:25:07 UTC (rev 4695) +++ trunk/Mail/tests/suite.php 2007-02-28 12:42:42 UTC (rev 4696) @@ -33,6 +33,7 @@ require_once( "transports/transport_mbox_test.php" ); require_once( "transports/transport_file_test.php" ); require_once( "transports/transport_imap_test.php" ); +require_once( "transports/transport_storage_test.php" ); require_once( "transports/transport_variable_test.php" ); require_once( "tutorial_examples.php" ); require_once( "parser/parser_test.php" ); @@ -75,6 +76,7 @@ $this->addTest( ezcMailTransportImapTest::suite() ); $this->addTest( ezcMailTransportMboxTest::suite() ); $this->addTest( ezcMailTransportFileTest::suite() ); + $this->addTest( ezcMailTransportStorageTest::suite() ); $this->addTest( ezcMailTransportVariableTest::suite() ); $this->addTest( ezcMailTutorialExamples::suite() ); $this->addTest( ezcMailParserTest::suite() ); Added: trunk/Mail/tests/transports/transport_storage_test.php =================================================================== --- trunk/Mail/tests/transports/transport_storage_test.php 2007-02-28 08:25:07 UTC (rev 4695) +++ trunk/Mail/tests/transports/transport_storage_test.php 2007-02-28 12:42:42 UTC (rev 4696) @@ -0,0 +1,236 @@ +<?php +/** + * @copyright Copyright (C) 2005-2007 eZ systems as. All rights reserved. + * @license http://ez.no/licenses/new_bsd New BSD License + * @version //autogentag// + * @filesource + * @package Mail + * @subpackage Tests + */ + +/** + * @package Mail + * @subpackage Tests + */ +class ezcMailTransportStorageTest extends ezcTestCase +{ + public function testImapMessageSource() + { + $transport = new ezcMailImapTransport( "dolly.ez.no" ); + $transport->authenticate( "ezcomponents", "ezcomponents" ); + $transport->selectMailbox( "Inbox" ); + $parser = new ezcMailParser(); + + $set = new ezcMailStorageSet( $transport->fetchByMessageNr( 1 ), $this->tempDir ); + $mail = $parser->parseMail( $set ); + $files = $set->getSourceFiles(); + + $source = file_get_contents( $files[0] ); + $this->assertEquals( 1542, strlen( $source ) ); + } + + public function testImapMessageSourceFetchAll() + { + $transport = new ezcMailImapTransport( "dolly.ez.no" ); + $transport->authenticate( "ezcomponents", "ezcomponents" ); + $transport->selectMailbox( "Inbox" ); + $parser = new ezcMailParser(); + + $set = new ezcMailStorageSet( $transport->fetchAll(), $this->tempDir ); + $mail = $parser->parseMail( $set ); + $files = $set->getSourceFiles(); + + $source = file_get_contents( $files[0] ); + $this->assertEquals( 1542, strlen( $source ) ); + } + + public function testImapMessageSourceEmptySet() + { + $transport = new ezcMailImapTransport( "dolly.ez.no" ); + $transport->authenticate( "ezcomponents", "ezcomponents" ); + $transport->createMailbox( "Guybrush" ); + $transport->selectMailbox( "Guybrush" ); + $parser = new ezcMailParser(); + + $set = new ezcMailStorageSet( $transport->fetchAll(), $this->tempDir ); + $mail = $parser->parseMail( $set ); + $this->assertEquals( array(), $mail ); + $transport->selectMailbox( "Inbox" ); + $transport->deleteMailbox( "Guybrush" ); + } + + public function testPop3MessageSource() + { + $transport = new ezcMailPop3Transport( "dolly.ez.no" ); + $transport->authenticate( "ezcomponents", "ezcomponents" ); + $parser = new ezcMailParser(); + + $set = new ezcMailStorageSet( $transport->fetchByMessageNr( 1 ), $this->tempDir ); + $mail = $parser->parseMail( $set ); + $files = $set->getSourceFiles(); + + $source = file_get_contents( $files[0] ); + $this->assertEquals( 1542, strlen( $source ) ); + } + + public function testPop3MessageSourceFetchAll() + { + $transport = new ezcMailPop3Transport( "dolly.ez.no" ); + $transport->authenticate( "ezcomponents", "ezcomponents" ); + $parser = new ezcMailParser(); + + $set = new ezcMailStorageSet( $transport->fetchAll(), $this->tempDir ); + $mail = $parser->parseMail( $set ); + $files = $set->getSourceFiles(); + + $source = file_get_contents( $files[0] ); + $this->assertEquals( 1542, strlen( $source ) ); + } + + public function testMboxMessageSource() + { + $transport = new ezcMailMboxTransport( dirname( __FILE__ ) . "/data/testlimit-mbox" ); + $parser = new ezcMailParser(); + + $set = new ezcMailStorageSet( $transport->fetchByMessageNr( 1 ), $this->tempDir ); + $mail = $parser->parseMail( $set ); + $files = $set->getSourceFiles(); + + $source = file_get_contents( $files[0] ); + $this->assertEquals( 2609, strlen( $source ) ); + } + + public function testMboxMessageSourceFetchAll() + { + $transport = new ezcMailMboxTransport( dirname( __FILE__ ) . "/data/testlimit-mbox" ); + $parser = new ezcMailParser(); + + $set = new ezcMailStorageSet( $transport->fetchAll(), $this->tempDir ); + $mail = $parser->parseMail( $set ); + $files = $set->getSourceFiles(); + + $source = file_get_contents( $files[0] ); + $this->assertEquals( 2925, strlen( $source ) ); + } + + public function testMboxMessageEmpty() + { + $transport = new ezcMailMboxTransport( dirname( __FILE__ ) . "/data/empty.mbox" ); + $parser = new ezcMailParser(); + + $set = new ezcMailStorageSet( $transport->fetchAll(), $this->tempDir ); + $mail = $parser->parseMail( $set ); + $this->assertEquals( 0, count( $mail ) ); + } + + public function testVariableMessageSource() + { + $parser = new ezcMailParser(); + $message = file_get_contents( dirname( __FILE__ ) . "/data/test-variable" ); + + $set = new ezcMailStorageSet( new ezcMailVariableSet( $message ), $this->tempDir ); + $mail = $parser->parseMail( $set ); + $files = $set->getSourceFiles(); + + $source = file_get_contents( $files[0] ); + $this->assertEquals( 1445, strlen( $source ) ); + } + + public function testVariableMessageSourceEmpty() + { + $parser = new ezcMailParser(); + $message = ""; + + $set = new ezcMailStorageSet( new ezcMailVariableSet( $message ), $this->tempDir ); + $mail = $parser->parseMail( $set ); + $this->assertEquals( array(), $mail ); + } + + public function testFileMessageSource() + { + $parser = new ezcMailParser(); + $messages = array( dirname( __FILE__ ) . "/data/test-variable" ); + + $set = new ezcMailStorageSet( new ezcMailFileSet( $messages ), $this->tempDir ); + $mail = $parser->parseMail( $set ); + $files = $set->getSourceFiles(); + + $source = file_get_contents( $files[0] ); + $this->assertEquals( 1444, strlen( $source ) ); + } + + public function testFileMessageSourceMultiple() + { + $parser = new ezcMailParser(); + $messages = array( dirname( __FILE__ ) . "/data/test-variable", dirname( __FILE__ ) . "/data/test-variable" ); + + $set = new ezcMailStorageSet( new ezcMailFileSet( $messages ), $this->tempDir ); + $mail = $parser->parseMail( $set ); + $files = $set->getSourceFiles(); + + $source = file_get_contents( $files[0] ); + $this->assertEquals( 1444, strlen( $source ) ); + $source = file_get_contents( $files[1] ); + $this->assertEquals( 1444, strlen( $source ) ); + } + + public function testFileMessageSourceEmpty() + { + $parser = new ezcMailParser(); + $fileName = $this->tempDir . "/empty-message"; + $fileHandle = fopen( $fileName, "w" ); + fwrite( $fileHandle, "" ); + fclose( $fileHandle ); + $messages = array( $fileName ); + + $set = new ezcMailStorageSet( new ezcMailFileSet( $messages ), $this->tempDir ); + $mail = $parser->parseMail( $set ); + $this->assertEquals( array(), $mail ); + } + + public function testGetSourceFileNames() + { + $transport = new ezcMailImapTransport( "dolly.ez.no" ); + $transport->authenticate( "ezcomponents", "ezcomponents" ); + $transport->selectMailbox( "Inbox" ); + $parser = new ezcMailParser(); + + $set = new ezcMailStorageSet( $transport->fetchAll(), $this->tempDir ); + $mail = $parser->parseMail( $set ); + $files = $set->getSourceFiles(); + $expected = array( "[EMAIL PROTECTED]", + "[EMAIL PROTECTED]", + "[EMAIL PROTECTED]", + "[EMAIL PROTECTED]" ); + for ( $i = 0; $i < count( $files ); $i++ ) + { + $this->assertEquals( $expected[$i], basename( $files[$i] ) ); + } + } + + public function setUp() + { + $this->tempDir = $this->createTempDir( 'ezcMailTransportStorageTest' ); + } + + public function tearDown() + { + $this->removeTempDir(); + + $transport = new ezcMailImapTransport( "dolly.ez.no" ); + $transport->authenticate( "ezcomponents", "ezcomponents" ); + try + { + $transport->deleteMailbox( "Guybrush" ); + } + catch ( ezcMailTransportException $e ) + { + } + } + + public static function suite() + { + return new PHPUnit_Framework_TestSuite( "ezcMailTransportStorageTest" ); + } +} +?> Property changes on: trunk/Mail/tests/transports/transport_storage_test.php ___________________________________________________________________ Name: svn:eol-style + native -- svn-components mailing list svn-components@lists.ez.no http://lists.ez.no/mailman/listinfo/svn-components