Source for file mbox.php
Documentation is available at mbox.php
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
// +----------------------------------------------------------------------+
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2004 The PHP Group |
// +----------------------------------------------------------------------+
// | This source file is subject to version 3.0 of the PHP license, |
// | that is bundled with this package in the file LICENSE, and is |
// | available through the world-wide-web at the following url: |
// | http://www.php.net/license/3_0.txt. |
// | If you did not receive a copy of the PHP license and are unable to |
// | obtain it through the world-wide-web, please send a note to |
// | license@php.net so we can mail you a copy immediately. |
// +----------------------------------------------------------------------+
// | Authors: Roberto Berto <darkelder.php.net> |
// +----------------------------------------------------------------------+
// $Id: mbox.php,v 1.13 2004/10/19 16:41:04 darkelder Exp $
* Mbox PHP class to Unix MBOX parsing and using
* int resource mbox->open(string file)
* open a mbox and return a resource id
* bool mbox->close(resource)
* close a mbox resource id
* int mbox->size(resource)
* return mbox number of messages
* string mbox->get(int resource, messageNumber)
* return the message number of the resource
* bool mbox->update(int resource, int messageNumber, string message)
* update the message offset to message (need write permission)
* bool mbox->remove(int resource, int messageNumber)
* remove the message messageNumber (need write permission)
* bool mbox->insert(int resource, string message[, $offset = null])
* add message to the end of the mbox. Offset == 0 message will
* be append at first message. If after == null will be the last
* one message. (need write permission)
* - CPAN Perl Mail::Folder::Mbox Module
* Used as a start point to create this class.
* http://search.cpan.org/author/KJOHNSON/MailFolder-0.07/Mail/Folder/Mbox.pm
* - PHP Mime Decode PEAR Module
* Use it to parse headers and body.
* http://pear.php.net/package-info.php?pacid=21
*From Foo@example.com Fri Dec 27 14:31:10 2002
*Received: from [unix socket] by campos.example.com (LMTP); Fri, 27 Dec
* 2002 14:31:10 -0200 (BRST)
*Date: Fri, 27 Dec 2002 14:31:21 -0500
*Message-Id: <200212271931.gBRJVL012289@example.com>
*Received: from pcp128525pcs.foo.example.com (
* pcp128525pcs.example.com [99.99.99.99]) by/
* serjolen6com.example.com (v64.19) with ESMTP id
* MAILRELAYINZA98-3601058302; Fri, 08 Nov 2002 06:39:05 -0500
*Subject: This is A SPAM!!
* require_once "mbox.php";
* $mbox = new Mail_Mbox();
* // uncomment to see lots of things
* $mid = $mbox->open("mbox");
* // uncomment to see internal vars
* // deleting a message (uncomment to test)
* #$res1 = $mbox->remove($mid,0);
* if (PEAR::isError($res1))
* print $res1->getMessage();
* // changing a message (uncomment to test)
* #$res2 = $mbox->update($mid,0,$content);
* if (PEAR::isError($res2))
* print $res2->getMessage();
* // adding a message (uncomment to test)
* $res3 = $mbox->insert($mid,$content,0);
* if (PEAR::isError($res3))
* print $res3->getMessage();
* require_once "Mail/mimeDecode.php";
* // showing current messages with Mail Mime
* for ($x = 0; $x < $mbox->size($mid); $x++)
* printf("Message: %08d<pre>",$x);
* $thisMessage = $mbox->get($mid,$x);
* $decode = new Mail_mimeDecode($thisMessage, "\r\n");
* $structure = $decode->decode();
* print "</pre><hr /><hr /><hr />";
* @author Roberto Berto <darkelder@php.net>
* Resources data like file name, file resource, mbox number, and other
* cacheds things are stored here.
* Note that it isnt really a valid resource type. It is of array type.
* Set to true to turn on debug mode
* Open the Mbox file and return an resource identificator.
* Also, this function will process the Mbox and create a cache
* that tells each message start and end bytes.
* @param int $file Mbox file to open
* @return mixed ResourceID on success else pear error class
// check if file exists else return pear error
return PEAR ::raiseError ("Cannot open the mbox file: file doesnt exists.");
// getting next resource it to set
$resourceId = sizeof($this->_resources) + 1;
// setting filename to the resource id
$this->_resources[$resourceId]["filename"] = $file;
$this->_resources[$resourceId]["fresource"] = fopen($file, "r");
if (!is_resource($this->_resources[$resourceId]["fresource"])) {
return PEAR ::raiseError ("Cannot open the mbox file: maybe without permission.");
// process the file and get the messages bytes offsets
$this->_process ($resourceId);
* Close the Mbox file opened by open()
* @param int $resourceId Mbox resouce id created by open
* @return mixed true on success else pear error class
function close($resourceId)
if (!is_resource($this->_resources[$resourceId]["fresource"])) {
return PEAR ::raiseError ("Cannot close the mbox file because it wanst open.");
if (!fclose($this->_resources[$resourceId]["fresource"])) {
return PEAR ::raiseError ("Cannot close the mbox, maybe file is being used (?)");
* Get Mbox Number of Messages
* @param int $resourceId Mbox resouce id created by open
* @return int Number of messages on Mbox (starting on 1,
* 0 if no message exists)
function size($resourceId)
return sizeof($this->_resources[$resourceId]["messages"]);
* Get a Message from Mbox
* Note: Message number start from 0.
* @param int $resourceId Mbox resouce id created by open
* @param int $message The number of Message
* @return string Return the message else pear error class
function get($resourceId, $message)
// checking if we have bytes locations for this message
if (!is_array($this->_resources[$resourceId]["messages"][$message])) {
return PEAR ::raiseError ("Message doesnt exists.");
// getting bytes locations
$bytesStart = $this->_resources[$resourceId]["messages"][$message][0 ];
$bytesEnd = $this->_resources[$resourceId]["messages"][$message][1 ];
// a debug feature to show the bytes locations
printf("%08d=%08d<br />", $bytesStart, $bytesEnd);
// seek to start of message
if (@fseek($this->_resources[$resourceId]["fresource"], $bytesStart) == -1 ) {
return PEAR ::raiseError ("Cannot read message bytes");
if ($bytesEnd - $bytesStart > 0 ) {
// reading and returning message (bytes to read = difference of bytes locations)
$msg = fread($this->_resources[$resourceId]["fresource"],
$bytesEnd - $bytesStart) . "\n";
* Remove a message from Mbox and save it.
* Note: messages start with 0.
* @param int $resourceId Mbox resouce id created by open
* @param int $message The number of Message to remove, or
* array of message ids to remove
* @return mixed Return true else pear error class
function remove($resourceId, $message)
// convert single message to array
$message = array ($message);
// checking if we have bytes locations for this message
foreach ($message as $msg) {
if (!is_array($this->_resources[$resourceId]["messages"][$msg])) {
return PEAR ::raiseError (" Message $msg doesn't exist." );
// changing umask for security reasons
// returning to old umask
$ftemp = fopen($ftempname, "w");
return PEAR ::raiseError ("Cannot create a temp file. Cannot handle this error.");
// writing only undeleted messages
$messages = $this->size($resourceId);
for ($x = 0; $x < $messages; $x++ ) {
$messageThis = $this->get($resourceId, $x);
$filename = $this->_resources[$resourceId]["filename"];
$this->close($resourceId);
return $this->_move ($resourceId, $ftempname, $filename);
* Note: Mail_Mbox auto adds \n\n at end of the message
* Note: messages start with 0.
* @param int $resourceId Mbox resouce id created by open
* @param int $message The number of Message to updated
* @param string $content The new content of the Message
* @return mixed Return true else pear error class
function update($resourceId, $message, $content)
// checking if we have bytes locations for this message
if (!is_array($this->_resources[$resourceId]["messages"][$message])) {
return PEAR ::raiseError ("Message doesnt exists.");
$ftemp = fopen($ftempname, "w");
return PEAR ::raiseError ("Cannot create a temp file. Cannot handle this error.");
// writing only undeleted messages
$messages = $this->size($resourceId);
for ($x = 0; $x < $messages; $x++ ) {
$messageThis = $content . "\n\n";
$messageThis = $this->get($resourceId, $x);
$filename = $this->_resources[$resourceId]["filename"];
$this->close($resourceId);
return $this->_move ($resourceId, $ftempname, $filename);
* PEAR::Mail_Mbox will insert the message according its offset.
* 0 means before the actual message 0. 3 means before the message 3
* (Remember: message 3 is the forth message). The default is put
* AFTER the last message.
* Note: PEAR::Mail_Mbox auto adds \n\n at end of the message
* @param int $resourceId Mbox resouce id created by open
* @param string $content The content of the new Message
* @param int offset Before the offset. Default: last message
* @return mixed Return true else pear error class
function insert($resourceId, $content, $offset = NULL )
// checking if we have bytes locations for this message
if (!is_array($this->_resources[$resourceId])) {
return PEAR ::raiseError ("ResourceId doesnt exists.");
$ftemp = fopen($ftempname, "w");
return PEAR ::raiseError ("Cannot create a temp file. Cannot handle this error.");
// writing only undeleted messages
$messages = $this->size($resourceId);
if ($messages == 0 && $offset !== NULL ) {
for ($x = 0; $x < $messages; $x++ ) {
if ($offset !== NULL && $x == $offset) {
$messageThis = $this->get($resourceId, $x);
$filename = $this->_resources[$resourceId]["filename"];
$this->close($resourceId);
return $this->_move ($resourceId, $ftempname, $filename);
* Used internally to copy the content of the temp file to the mbox file
* @parm int $resourceId Resource file
* @parm string $ftempname Source file - will be removed
* @param string $filename Output file
function _move ($resourceId, $ftempname, $filename)
$ftemp = fopen($ftempname, "r");
return PEAR ::raiseError ("Cannot open temp file.");
$fp = @fopen($filename, "w");
return PEAR ::raiseError ("Cannot write on mbox file.");
while (feof($ftemp) != true ) {
$strings = fread($ftemp, 4096 );
return PEAR ::raiseError ("Cannot write to file.");
// open another resource and substitute it to the old one
$mid = $this->open($filename);
$this->_resources[$resourceId] = $this->_resources[$mid];
unset ($this->_resources[$mid]);
* - Get start bytes and end bytes of each messages
* @param int $resourceId Mbox resouce id created by open
function _process ($resourceId)
if (!is_resource($this->_resources[$resourceId]['fresource'])) {
return PEAR ::raiseError ("Resource isn't valid.");
if (@fseek($this->_resources[$resourceId]['fresource']) == -1 ) {
return PEAR ::raiseError ("Cannot read mbox");
// current start byte position
// last start byte position
// there aren't any message
while ($line = fgets($this->_resources[$resourceId]['fresource'], 4096 )) {
// if line start with "From ", it is a new message
if (0 === strncmp($line, 'From ', 5 )) {
// save last start byte position
// new start byte position is the start of the line
$start = ftell($this->_resources[$resourceId]['fresource']) - strlen($line);
// if it is not the first message add message positions
$this->_resources[$resourceId]["messages"][] = array ($laststart, $start - 1 );
// tell that there is really a message on the file
// if there are just one message, or if it's the last one,
// add it to messages positions
if (($start == 0 && $hasmessage === true ) || ($start > 0 )) {
$this->_resources[$resourceId]["messages"][] = array ($start, ftell($this->_resources[$resourceId]['fresource']));
Documentation generated on Mon, 11 Mar 2019 13:58:17 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.
|