Location: PHPKode > scripts > pop3ml > pop3ml-0-1/class.pop3ml.php
<?php
/*
 * @(#) $Header: /var/cvsroot/pop3ml/class.pop3ml.php,v 1.15 2009/03/02 11:38:11 cvs Exp $
 */
/*  pop3ml - php Mailing list/Newsletter manager
    Copyright (C) 2008- Giuseppe Lucarelli <hide@address.com>

    This program is free software; you can redistribute it and/or modify
    it under the terms of version 2 of the GNU General Public License as
    published by the Free Software Foundation.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/
require_once('smtp.php');
require_once('mime_parser.php');
require_once('rfc822_addresses.php');
require_once("pop3.php");
require_once('sasl.php');	/* for gmail */

class MyPop3 extends pop3_class {
	var $decoded;
}

class Pop3Ml
{
/* public */
	var $mltable = '';
	var $messagesTable = '';
	var $listname = '';
	var $listaddress = '';
	var $listhostname = '';
	var $listpost = '';
	var $listport = '';
	var $listtls = '';
	var $listuser = '';
	var $listpassword = '';
	var $allow = array();
	var $deny = array();
	var $removeAfterPop = '';
	var $moderatedlist = '';
	var $modsublist = '';
	var $listowner = '';
	var $maxmsgsize = '';
	var $headersadd = array();
	var $logheader = '';
	var $sublist = '';
	var $mlsmtp = array();
/* private */
	var $dbconn = '';
	var $databaseHost = '';
	var $databaseUsername = '';
	var $databasePassword = '';
	var $dbrow = '';
	var $pop3='';
	var $decoded='';
	var $smtp='';
	var $smtpindex='';
	var $error='';
	
	function init() {
		if(!$this->dbconn=@mysql_connect($this->databaseHost, $this->databaseUsername, $this->databasePassword)) {
			return false;
		}
		@mysql_select_db($this->databaseName,$this->dbconn);

		$query = "select * from ".addslashes($this->mltable)." where listname = '".$this->listname."'";
		$command = @mysql_query($query,$this->dbconn);
		if(!$result = @mysql_fetch_object($command)) {
			echo "no ML found: quit; ";
			return false;
		}
		$this->dbrow = $result;
		$this->listuser=$this->dbrow->listuser;
		$this->listpassword=$this->dbrow->listpoppass;
		$this->maxmsgsize=$this->dbrow->msgsize;
		$this->removeAfterPop=$this->dbrow->removeafterpop;
		$this->moderatedlist=$this->dbrow->moderatedlist;
		$this->listowner=$this->dbrow->listowneremail;
		$this->listaddress=$this->dbrow->listaddr;
		$this->mlsmtp=explode("\n",$this->dbrow->smtpserver);
		$this->dbrow->sublist=trim($this->dbrow->sublist);
		$this->dbrow->allowsublist=trim($this->dbrow->allowsublist);
		$this->dbrow->denysublist=trim($this->dbrow->denysublist);
		$this->sublist=$this->dbrow->sublist;
		$this->modsublist=$this->dbrow->modsublist;
		$this->allow=(strlen($this->dbrow->allowsublist) > 2 ? explode("\n",$this->dbrow->allowsublist) : '');
		$this->deny =(strlen($this->dbrow->denysublist) > 2 ? explode("\n",$this->dbrow->denysublist) : '');
		$result=explode("\n",$this->setText($this->dbrow->headerchange));
		foreach($result as $token) {
			$item=explode('::',$token);
			$this->headersadd[$item[0]] = trim($item[1]);
		}
		$this->smtpindex=0;	// use default smtp server
		//-------------------
		$this->pop3 = new pop3_class;
		stream_wrapper_register('pop3', 'pop3_stream');  /* Register the pop3 stream handler class */
		return true;
	}

	//------------------------------------------------------------------------------
	// if smtp server doesn't require pop auth, set to '' pop3_auth_port, user, password)
	//------------------------------------------------------------------------------
	function smtpinit() {
        	$this->smtp=new smtp_class;

        	$this->smtp->localhost="localhost";
        	$this->smtp->direct_delivery=0;
        	$this->smtp->timeout=10;
        	$this->smtp->data_timeout=0;
        	$this->smtp->debug=0;
        	$this->smtp->html_debug=0;
        	$this->smtp->pop3_auth_host='';
        	$this->smtp->realm="";
        	$this->smtp->workstation="";
        	$this->smtp->authentication_mechanism="";
		$token = explode(':',trim($this->mlsmtp[$this->smtpindex]));
        	$this->smtp->host_name=$token[0];
        	$this->smtp->host_port=$token[1];
        	$this->smtp->ssl=$token[2];
		$this->smtp->pop3authport='';
        	$this->smtp->user='';
        	$this->smtp->password='';
		if($token[3]) $this->smtp->pop3authport=$token[3];
        	if($token[4]) $this->smtp->user=$token[4];
        	if($token[5]) $this->smtp->password=$token[5];
	}

        function &setText(&$text) {
		return(str_replace(array("__LISTADDRESS__","__LISTOWNER__","__LISTHELP__"),
			     array($this->listaddress,$this->listowner,$this->listaddress),$text));
	}
	function smtpsend($mailto, $mailsubject, $mailfrom, &$mailheader, &$mailbody) {
		$this->smtpinit();

		if($this->smtp->direct_delivery)
		{
			if(!function_exists("GetMXRR"))
			{
				/*
				* If possible specify in this array the address of at least on local
				* DNS that may be queried from your network.
				*/
				$_NAMESERVERS=array();
				include("getmxrr.php");
			}
			/*
			* If GetMXRR function is available but it is not functional, to use
			* the direct delivery mode, you may use a replacement function.
			*/
			/*
			else
			{
				$_NAMESERVERS=array();
				if(count($_NAMESERVERS)==0)
					Unset($_NAMESERVERS);
				include("rrcompat.php");
				$this->smtp->getmxrr="_getmxrr";
			}
			*/
		}

		if($this->smtp->SendMessage(
			$mailfrom,
			array(
				$mailto
			),
			explode("\n",$mailheader), $mailbody))
			$retval = "OK.";
		else
			$retval = $this->smtp->error;

		return $retval;
	}

	function sendSubscribeConfirmation($address) {
		$id = md5(uniqid(rand(), true));
		$mailheader = '';
		$mailsubject = 'confirm subscribe to '.$this->listaddress;
		$mailbody = "__SUBSCRIBE__";
		$confirmtext = 'confirm.subscribe.'.$this->listname.'.'.$id.'.'.$address;

        	$mailbody = str_replace("__SUBSCRIBE__", $confirmtext, $this->setText($this->dbrow->submsg));
        	$query="insert into ".$this->subqueue." values ('".$this->listname.":$address','subscription','$id','');";
        	if(!@mysql_query($query,$this->dbconn)) { // there is another request, replace it
        		$query="update ".$this->subqueue." set request = 'subscription', keyvalue = '$id' where code = '".
				$this->listname.":$address';";
        		@mysql_query($query,$this->dbconn);
		}
		foreach($this->headersadd as $hk => $hv) {
			if(strcmp($hv,'')) {
				$mailheader.= $hk.': '.$hv."\r\n";
			}
		}
		$mailheader.='Subject: '.$mailsubject."\r\n";
		$error = $this->smtpsend($address, $mailsubject, $this->listaddress, $mailheader, $mailbody);
		if($error != 'OK.') {
			echo "[$error]";
			return false;
		}
	}

	function sendWelcomeMessage($address) {
		$mailsubject = 'WELCOME to '.$this->listaddress;
		$mailheader = '';
		$mailbody  = '';

        	$mailbody = str_replace("__SUBSCRIBE__", $address, $this->setText($this->dbrow->welcome));
		foreach($this->headersadd as $hk => $hv) {
			if(strcmp($hv,'')) {
				$mailheader.= $hk.': '.$hv."\r\n";
			}
		}
		$mailheader.='Subject: '.$mailsubject."\r\n";
		$error = $this->smtpsend($address, $mailsubject, $this->listaddress, $mailheader, $mailbody);
		if($error != 'OK.') {
			return false;
		}
	}

	function setConfirmedAddress($address) {
		$this->dbrow->sublist=$this->sublist=trim($this->sublist)."\n".$address;
		$query = 'update '.$this->mltable.' set sublist = \''.
			trim($this->sublist).'\' where listname = \''.$this->listname.'\'';
		if($command = @mysql_query($query,$this->dbconn)) {
			echo "confirmed subscription [$address]\n";
			$this->sendWelcomeMessage($address);
		}
	}
	function isNewSubscription($address) {
		$bodytest = $this->decoded[0]['Body'];

		if(strstr(trim($this->decoded[0]['Headers']['content-type:']),'alternative')) {
			$pos=strpos($bodytest,"text/plain");
			$bodytest=substr($bodytest,$pos);
			$pos=strpos($bodytest,"\r\n\r\n");
			$bodytest=substr($bodytest,$pos+4);
			if(!$pos) {
				$pos=strpos($bodytest,"\n\n");
				$bodytest=substr($bodytest,$pos+2);
			}
		}

		if(eregi("^subscribe",preg_replace("/\n|\r|=/",'',$bodytest))) {
			if(strcasecmp($this->dbrow->confirmsub,'yes')) {
				$this->setConfirmedAddress($address);
			} else {
				echo "subscribe [$address]. require confirmation: ";
				$this->sendSubscribeConfirmation($address);
			}
			return true;
		}
		$query = "select * from ".addslashes($this->subqueue)." where code = '".
			$this->listname.':'.$address."' and request = 'subscription'";
		$command = @mysql_query($query,$this->dbconn);
		if(!$result = @mysql_fetch_object($command)) {
			return false;
		}
                if(!ereg("confirm.*subscribe.*".$this->listname.'.*'.$result->keyvalue.'.*'.$address,
                        preg_replace("/\n|\r|=/",'',$this->decoded[0]['Body']))) {
			return false;
		}
		$query = "delete from ".addslashes($this->subqueue)." where code = '".
			$this->listname.':'.$address."' and request = 'subscription'";
		$command = @mysql_query($query,$this->dbconn);
		$this->setConfirmedAddress($address);
		return true;
	}

	function sendUnsubscribeConfirmation($address) {
		$id = md5(uniqid(rand(), true));
		$mailheader = '';
		$mailsubject = 'confirm unsubscribe from '.$this->listaddress;
		$mailbody = "__UNSUBSCRIBE__";
		$confirmtext = 'confirm.unsubscribe.'.$this->listname.'.'.$id.'.'.$address;

        	$mailbody = str_replace("__UNSUBSCRIBE__", $confirmtext, $this->setText($this->dbrow->unsubmsg));
        	$query="insert into ".$this->subqueue." values ('".$this->listname.":$address','unsubscription','$id','');";
        	if(!@mysql_query($query,$this->dbconn)) { // there is another request, replace it
        		$query="update ".$this->subqueue." set request = 'unsubscription', keyvalue = '$id' where code = '".
				$this->listname.":$address';";
        		@mysql_query($query,$this->dbconn);
		}
		foreach($this->headersadd as $hk => $hv) {
			if(strcmp($hv,'')) {
				$mailheader.= $hk.': '.$hv."\r\n";
			}
		}
		$mailheader.='Subject: '.$mailsubject."\r\n";
		$error = $this->smtpsend($address, $mailsubject, $this->listaddress, $mailheader, $mailbody);
		if($error != 'OK.') {
			return false;
		}
	}

	function sendGoodbyeMessage($address) {
		$mailsubject = 'GOODBYE from '.$this->listaddress;
		$mailheader = '';
		$mailbody  = '';

        	$mailbody = str_replace("__UNSUBSCRIBE__", $address, $this->setText($this->dbrow->goodbye));
		foreach($this->headersadd as $hk => $hv) {
			if(strcmp($hv,'')) {
				$mailheader.= $hk.': '.$hv."\r\n";
			}
		}
		$mailheader.='Subject: '.$mailsubject."\r\n";
		$error = $this->smtpsend($address, $mailsubject, $this->listaddress, $mailheader, $mailbody);
		if($error != 'OK.') {
			return false;
		}
	}

	function unsetRegisteredAddress($address) {
		$this->dbrow->sublist=$this->sublist=preg_replace('/'.$address.'(\n|)/','',trim($this->sublist));
		$query = 'update '.$this->mltable.' set sublist = \''.
			trim($this->sublist).'\' where listname = \''.$this->listname.'\'';
		if($command = @mysql_query($query,$this->dbconn)) {
			echo "confirmed unsubscription [$address]\n";
			$this->sendGoodbyeMessage($address);
		}
	}

	function isUnsubscription($address) {
		$bodytest = $this->decoded[0]['Body'];

		if(strstr(trim($this->decoded[0]['Headers']['content-type:']),'alternative')) {
			$pos=strpos($bodytest,"text/plain");
			$bodytest=substr($bodytest,$pos);
			$pos=strpos($bodytest,"\r\n\r\n");
			$bodytest=substr($bodytest,$pos+4);
			if(!$pos) {
				$pos=strpos($bodytest,"\n\n");
				$bodytest=substr($bodytest,$pos+2);
			}
		}

		if(eregi("^unsubscribe",preg_replace("/\n|\r|=/",'',$bodytest))) {
			if(strcasecmp($this->dbrow->confirmunsub,'yes')) {
				$this->unsetRegisteredAddress($address);
			} else {
				echo "unsubscribe [$address]. require confirmation\n";
				$this->sendUnsubscribeConfirmation($address);
			}
			return true;
		}
		$query = "select * from ".addslashes($this->subqueue)." where code = '".
			$this->listname.':'.$address."' and request = 'unsubscription'";
		$command = @mysql_query($query,$this->dbconn);
		if(!$result = @mysql_fetch_object($command)) {
			return false;
		}
		echo "[$address] unsubscription request pending, ";
                if(!ereg("confirm.*unsubscribe.*".$this->listname.'.*'.$result->keyvalue.'.*'.$address,
                        preg_replace("/\n|\r|=/",'',$this->decoded[0]['Body']))) {
			return true;
		}
		$query = "delete from ".addslashes($this->subqueue)." where code = '".
			$this->listname.':'.$address."' and request = 'unsubscription'";
		$command = @mysql_query($query,$this->dbconn);
		$this->unsetRegisteredAddress($address);
		return true;
	}

	function implodeHeaders($headkey,$token) {
		$retval = '';
		if(!is_array($token)) {
			return $retval;
		}
		foreach($token as $key => $val) {
			if(!is_array($val)) {
				$retval.= (strcmp($headkey,'') ? $headkey : $key).' '.$val."\r\n";
			} else {
				$retval.= $this->implodeHeaders($key,$val);
			}
		}
		return $retval;
	}

	function removeMessage($message) {
		$this->error = '';
	
		$this->error=$this->pop3->DeleteMessage($message);
		return true;
	}

	function checkSender($address) {
		$retval = 'deny';
		
		if(!strcmp($address,$this->listowner)
		|| eregi("(^|\n)$address(\n|$)",$this->modsublist)
		|| strcmp($this->dbrow->subscribersonly,'yes')) {
			$retval = 'allow';
		}
		if(is_array($this->allow)) {
			foreach($this->allow as $pattern) {
				if(eregi($pattern, $address)) {
					$retval = 'allow';
				}
			}
		}
		if(is_array($this->deny)) {
			foreach($this->deny as $pattern) {
				if(eregi($pattern, $address)) {
					$retval = 'deny';
				}
			}
		}
		if(!preg_match('/(^|\n)'.$address.'(\n|$)/',$this->sublist)) {
			if($this->isNewSubscription($address) != true && $retval != 'allow') {
				echo "sorry, you are not subscribed yet and/or not allowed to post. Sender [$address] message-id [$messageid]";
			}
			return $retval;
		}
		if($this->isUnsubscription($address) == true) {
			return 'deny';
		}
		// if newsletter don't accept others then allowed sender
		if($this->dbrow->mltype != 'm' || !strstr($retval,'deny')) {
			return $retval;
		}
		return 'allow';
	}

	function listMessages() {

		$result=$this->pop3->ListMessages("",0);
		if(GetType($result)=="array") {
			for(Reset($result),$message=0;$message<count($result);Next($result),$message++) {
					echo "Message ",Key($result)," - ",$result[Key($result)]," bytes.\n";
			}
			$result=$this->pop3->ListMessages("",1);
			if(GetType($result)=="array") {
				for(Reset($result),$message=0;$message<count($result);Next($result),$message++) {
					echo "Message ",Key($result),", Unique ID - \"",$result[Key($result)],"\"\n";
				}
			}
		}
	}

	function pop3Start() {

		$temp = explode(':',$this->dbrow->hostname);
        	$this->pop3->hostname=$this->listhostname=$temp[0];           /* POP 3 server host name                      */
        	$this->pop3->port=$this->listport=$temp[1];                   /* POP 3 server host port,
                                                    	usually 110 but some servers use other ports
                                                    	Gmail uses 995                              */
        	$this->pop3->tls=$this->listtls=$temp[2];                     /* Establish secure connections using TLS      */
        	$this->pop3->realm="";                         /* Authentication realm or domain              */
        	$this->pop3->workstation="";                   /* Workstation for NTLM authentication         */
        	$this->pop3->authentication_mechanism="USER";  /* SASL authentication mechanism               */
        	//$this->pop3->debug=1;                          /* Output debug information                    */
        	//$this->pop3->html_debug=1;                     /* Debug information is in HTML                */
        	//$this->pop3->join_continuation_header_lines=1; /* Concatenate headers split in multiple lines */
		//return $pop3;
	}

	/* check for new messages */
	function pop3Read() {
		$retval = '';
		$apop=0;
		$user=$this->listuser;
		$password=$this->listpassword;
		$this->error='';
		$messages='';
		$address = '';
		$substate = -1;
		$messageid = '';

		if(($this->error=$this->pop3->Open())!="") {
			return $this->error;
		}
		if(($this->error=$this->pop3->Login($user,$password,$apop))!="") {
			echo "Connection error: $this->error\n<br>";
			return $this->error;
		}
		if(($this->error=$this->pop3->Statistics($messages,$size))=="")
		{
			echo "$messages mess.".($size > 0 ? " total size [$size]" : '');
			for($i=0; $i < $messages; $i++)
			{
				$error = '';
				$this->pop3->GetConnectionName($connection_name);
				$message=$i + 1;
				$size = $this->pop3->ListMessages($message,0);
				echo " # $message, size [$size]: ";
				$message_file='pop3://'.$connection_name.'/'.$message;
				$mime=new mime_parser_class;
				$mime->decode_bodies = 0;
				if($size > $this->maxmsgsize) {
					$mime->decode_bodies = 1;
					echo " Warning [exceeding].";
				}
				$parameters=array(
					'File'=>$message_file //, 'SaveBody'=>1,
				);
				$success=$mime->Decode($parameters, $this->decoded);
				if(!$success) {
					echo 'MIME message decoding error: '.HtmlSpecialChars($mime->error)." .";
				} else {
					if(!strcasecmp($this->removeAfterPop,'yes')) {
						$this->error.=$this->removeMessage($message)."\n";
					}
					$address = $this->decoded[0]['ExtractedAddresses']['from:'][0]['address'];
					if(isset($this->decoded[0]['Headers']['message-id:'])) {
						$messageid = $this->decoded[0]['Headers']['message-id:'];
					}
					if(isset($this->decoded[0]['Headers']['precedence:']) &&
					$this->decoded[0]['Headers']['precedence:'] == 'bulk') {
						echo "sorry, bulk message. Sender [$address] message-id [$messageid]";
					}
					if(!strcmp($this->checkSender($address),'allow')) {
						$this->sendMessage($address,$size);
					}
				}
			}
		}
		echo $this->logcr."\n";
		$this->error=$this->pop3->Close();
		$retval = $this->error;
		return $retval;
	}

	function addTrailer() {
		$retval = '';

		if(strlen($this->dbrow->trailerfile) <= 0) {
			return $retval;
		}
		$content_type = explode(';',$this->decoded[0]['Headers']['content-type:']);
		$content_type[0] = trim($content_type[0]);
/*---------------------------------------------------------
 * non enabled 
		if(strcasecmp(trim($content_type[0]),'text/plain')) {
			if(strstr($content_type[1],'boundary=')) {
				$retval = "\r\n--".
				($content_type[1][9] == '"' ?
					substr($content_type[1],10,-1) :
					substr($content_type[1],9)).
				"\r\nContent-Type: text/plain; charset=ISO-8859-1; format=flowed".
				"\r\nContent-Transfer-Encoding: 7bit\r\n\r\n";
			}
		}
---------------------------------------------------------*/
		if(strstr($content_type[0],'alternative')) {
			if(strstr($content_type[1],'boundary=')) {
				$retval = "\r\n--".
				($content_type[1][9] == '"' ?
					substr($content_type[1],10,-1) :
					substr($content_type[1],9)).
				"\r\nContent-Type: text/plain; charset=ISO-8859-1; format=flowed".
				"\r\nContent-Transfer-Encoding: 7bit\r\n\r\n";
				return $this->setText($retval);
			}
		}
		if(!strstr($content_type[0],'mixed') && !strstr($content_type[0],'digest')) {
			$retval="\r\n".$this->dbrow->trailerfile."\r\n";
			return $this->setText($retval);
		}
		return $retval;
	}

	function sendFromQueue() {
		$query = "select * from $this->queue where mltable = '$this->listname'";
		$result = @mysql_query($query,$this->dbconn);
		while($row = @mysql_fetch_object($result)) {
			// change smtp server
			$this->smtpindex = $row->smtp + 1;
			if($this->smtpindex > (sizeof($this->mlsmtp) - 1)) {
				$this->smtpindex = 0;
			}
			$addresses = explode(',', $row->addresses);
			$messageid = $row->messageid;
			$query = "select * from $this->messagesTable where id = $messageid";
			$msgresult = @mysql_query($query,$this->dbconn);
			if(!$msgrow = @mysql_fetch_object($msgresult)) {
				break;
			}
			echo "sending from queue # $messageid; ";
			$addresserror = '';
			foreach($addresses as $address) {
				$pos=strpos($msgrow->message,"\r\n\r\n");
				if(!$pos) $pos=strpos($msgrow->message,"\n\n");
				$error = $this->smtpsend($address, $msgrow->subject, $this->listaddress,
					substr($msgrow->message,0,$pos),
					substr($msgrow->message,$pos+2));
				if($error != 'OK.') {
					echo " error [$error] for [$address];";
					$addresserror.=((strlen($addresserror) <= 0) ? '': ',').$address;
				} else {
					$ok++;
				}
			}
			if(strlen($addresserror) > 1) {
				$query = "update queue set mldate = '".date(Ymd).
					"', addresses = '".str_replace("'","\\'",$addresserror).
					"', smtp = $this->smtpindex where id = $row->id";
				$command = @mysql_query($query,$this->dbconn);
			} else {
				$query = "update messages set state = 'sent', smtp = '".
					$this->smtpindex."' where id = $messageid";
				$command = @mysql_query($query,$this->dbconn);
				$query = "delete from queue where id = $row->id";
				$command = @mysql_query($query,$this->dbconn);
			}
			@mysql_free_result($msgresult);
		}
		@mysql_free_result($result);
		$this->smtpindex = 0;
		return true;
	}
	/* send section */
	function sendMessage($sender,$msgsize) {
		$error = '';
		$messageid = -1;
		$origmailheader = '';
		$mailheader = '';
		$mailbody = '';
		$oksum = 0;
		$sqlid = -1;

		$modstate = 'sent';
		if(!strcmp($this->moderatedlist,'yes')) {
			$modstate = 'pending';
		}
		if($msgsize > $this->maxmsgsize) {
			$this->headersadd['Content-Type'] = '';
			$this->headersadd['Boundary'] = '';
		}
		$mailbody=&$this->decoded[0]['Body'];
		$mailbody.=$this->addTrailer();
		$mailsender = $this->listaddress; // if smtp require authentication
		$mailsubject = stripslashes($this->decoded[0]['Headers']['subject:']);
		if(!strcmp($modstate,'pending')) {
			if(eregi("(^|\n)$sender(\n|$)",$this->modsublist)) {
				$keyvalue=preg_replace('/(.*)\[(MOD#[a-zA-Z0-9]+)\](.*)/','\2',$mailsubject);
				$query="select * from $this->messagesTable where state = 'pending' && subject REGEXP '$keyvalue'";
				if($result = @mysql_query($query,$this->dbconn)) {
					if($row = @mysql_fetch_object($result)) {
						preg_match('/(^|\n|\r)subject:(.*)(\n|\r|$)/i',$row->header, $match);
						if($match[2]) {
							$mailsubject=trim($match[2]);
						} else {
							$mailsubject=preg_replace('/(.*)\[(MOD#[a-zA-Z0-9]+)\](.*)/','\3',$mailsubject);
						}
						$pos=strpos($row->message,"\r\n\r\n");
						if(!$pos) $pos=strpos($row->message,"\n\n");
						$mailbody = substr($row->message,$pos);
						$query = "update $this->messagesTable set state = 'queued', subject = '$mailsubject'  where id = $row->id";
						@mysql_query($query,$this->dbconn);
						$messageid = $row->id;
					}
					@mysql_free_result($result);
				}
				$modstate = 'sent';
			} else {
				$mailsubject = '[MOD#'.md5(uniqid(rand(), true)).']'.$mailsubject;
			}
			$this->headersadd['Subject'] = $mailsubject;
		}

		foreach($this->decoded[0]['Headers'] as $key => $val) {
			foreach($this->headersadd as $hk => $hv) {
				if(eregi("^$hk($|:)",$key)) {
					if(strlen($hv) <= 0) {
						$val = '';
					} else {
						$val = $hv;
					}
					unset($this->headersadd[$hk]);
					$hv = '';
					break;
				}
			}
			if(is_array($val)) {
				foreach($val as $token) {
					$mailheader .= $key.' '.$token."\r\n";
				}
			} else if(strlen($val) > 0) {
				$mailheader .= $key.' '.$val."\r\n";
			}
		}
		foreach($this->headersadd as $hk => $hv) {
			if(strlen($hv) > 0) {
				$mailheader .= $hk . ': '.$hv."\r\n";
			}
		}
		if($msgsize > $this->maxmsgsize) {
			$mailbody = "Your message [$msgsize] was not sent because it exceed maximum size allowed [$this->maxmsgsize]\n";
			$error = $this->smtpsend($sender, $mailsubject, $mailsender, $mailheader, $mailbody);
			if($error != 'OK.') {
				echo " error [$error] for [$sender];";
			} else {
				echo " resent to [$sender];";
			}
			return;
		}
		$addresserror = '';
		echo "Sending ID # ";
		if(!strcmp($modstate,'sent')) {
			$sublist = explode("\n",$this->sublist);
		} else {
			echo "(moderation) ";
			$sublist = explode("\n",$this->modsublist);
		}
		if(sizeof($sublist) > 0) {
			foreach($sublist as $mailaddress) {
				if(strlen($mailaddress) < 5) continue;
				$mailaddress = stripslashes($mailaddress);
				$error = $this->smtpsend($mailaddress, $mailsubject, $mailsender, $mailheader, $mailbody);
				if($error != 'OK.') {
					echo " error [$error] for [$mailaddress];";
					$addresserror.=((strlen($addresserror) <= 0) ? '': ',').$mailaddress;
				} else {
					$ok++;
				}
			}
		}
		if(!strcmp($modstate,'sent') && strlen($addresserror) > 1) {
				$modstate = 'queued';
		}
		// ok, insert message into archive
		if($messageid > 0) {
			$query = "update $this->messagesTable set state = '$modstate' where id = $messageid";
		} else {
			$query = "insert into ".$this->messagesTable.
				" (id,mldate,state,mltable,smtp,mailfrom,subject,message,header,rowlock) values(0,now(),'".
				"$modstate','$this->listname','$this->smtpindex','$sender','".
				str_replace("'","\\'",$mailsubject)."','".
				str_replace("'","\\'",$mailheader)."\r\n".str_replace("'","\\'",$mailbody)."','".
				str_replace("'","\\'",$this->implodeHeaders('',$this->decoded[0]['Headers'])).
					"','')";
		}
		$command = @mysql_query($query,$this->dbconn);
		$sqlid = @mysql_insert_id($this->dbconn);
		echo "$sqlid:";
		if(strlen($addresserror) > 1) {
			$query = "insert into queue (id, mldate, smtp, mltable, messageid, addresses, rowlock) values(0,now(),'".
				"$this->smtpindex','$this->listname',$sqlid,'".
				str_replace("'","\\'",$addresserror)."','')";
			$command = @mysql_query($query,$this->dbconn);
		}
		echo " sent # $ok. End";
	}

	function lockml() {
		if(strlen($this->dbrow->rowlock) > 1) {
			return false;
		}
		$query = "update ".addslashes($this->mltable)." set rowlock = '".
			$_SERVER['REMOTE_ADDR'].'-'.date('Y/m/d-H:i:s')."' where listname = '".$this->listname."'";
		if(!@mysql_query($query,$this->dbconn)) {
			return false;
		}
		return true;
	}
	function unlockml() {
		$query = "update ".addslashes($this->mltable)." set rowlock = '' where listname = '".$this->listname."'";
		if(!@mysql_query($query,$this->dbconn)) {
			return false;
		}
	}
	function run() {
		echo $this->logheader;
		echo date("Y/m/d H:i:s").". ".$this->listname.": ";
		if($this->init() != true) {
			echo $this->logfooter;
			return;
		}
		if(!strcmp($this->dbrow->shutdown,'yes')) {
			echo "ML disabled. quit";
		} else if($this->lockml() != true) {
			echo "already locked. quit";
		} else {
			$this->sendFromQueue();
			$this->pop3Start();
			$this->error=$this->pop3Read();
			$this->unlockml();
		}
		echo $this->logfooter;
	}
};

?>
Return current item: pop3ml