Click to See Complete Forum and Search --> : mail class


suepahfly
06-07-2005, 07:40 AM
This is my very first class, so i'm guessing there are al sorts of things wrong with it ;) I'd like to know if I did exception handling right


<?php
/**
* @package tld.domain.packageName
* @file class.mail.php
* @author J.Kesseler <jkesseler@gmail.com>
* @copyright J.Kesseler
* @version 0.1
* @comments Based upon libMail.php by Leo West <lwest@free.fr>
*
*/


class SendMail
{

/**
* Main class constructor
*
* Set default class options
*
* @param void
* @return void
*/

private function __construct()
{
$this->autoCheck(true);
$this->boundary= "--" . md5(uniqid("myboundary"));
}


/**
* Sets from address
*
*
* @param string from address
* @return void
* @access public
* @since 0.1
*/
public function setFrom($from)
{
if(!is_string($from))
throw new Exception("From adress is not a string");

$this->xheaders['From'] = $from;
}


/**
* Sets Reply-To header
*
*
* @param string Reply-To adress
* @return void
* @access public
* @since 0.1
*/
public function setReplyTo($address)
{
if(!is_string($address))
throw new Exception("ReplyTo addres is not a string");

$this->xheaders['Reply-To'] = $address;
}


/**
* Sets reciepent adresses
*
* @param array Array containing reciepent adresses
* @return void
* @access public
* @since 0.1
*/
public function setTo($to)
{
if( is_array($to) )
$this->sendto= $to;
else
$this->sendto[] = $to;

if( $this->checkAddress == true )
$this->CheckAdresses($this->sendto);
}


/**
* Sets Carbon Copy adresses
*
* @param array Array containing address too CC to
* @return void
* @throws Execption
* @access public
* @since 0.1
*/
public function setCC($cc)
{
if(is_array($cc))
$this->acc= $cc;
else
$this->acc[]= $cc;

if( $this->checkAddress == true )
{
try
{
$this->CheckAdresses($this->acc);
}
catch(Exception $e)
{
echo "Exception caught: ".$e;
}
}
}


/**
* Sets Blind Carbon Copy adresses
*
* @param array Array containing address too BCC to
* @return void
* @throws Exception
* @access public
* @since 0.1
*/
public function setBCC($bcc)
{
if(is_array($bcc))
$this->abcc = $bcc;
else
$this->abcc[]= $bcc;


if( $this->checkAddress == true )
{
try
{
$this->CheckAdresses($this->abcc);
}
catch(Exception $e)
{
echo "Exception caught: ".$e;
}
}
}


/**
* Sets the subject line
*
* @param string The subject of your email
* @return void
* @access public
* @since 0.1
*/
public function setSubject($subject)
{
$this->xheaders['Subject'] = strtr( $subject, "\r\n" , " " );
}


/**
* Sets the body of the email
*
*
* @param string body of email
* @param string optional character set
* @return void
* @access public
* @since 0.1
*/
public function setBody($body, $charSet="")
{
$this->body = $body;

if( $charset != "" ) {
$this->charSet = strtolower($charSet);
if( $this->charSet != "us-ascii" )
$this->ctencoding = "8bit";
}

}


/**
* Attach a file to the email
*
*
* @param string Filename to attach
* @param string Mime type off the file
* @param string Content disposition, either inline or attach
* @todo autodetect mime types
* @return void
* @access public
* @since 0.1
*/
public function setAttachment($filename, $filetype = "", $disposition = "inline")
{
/**
* TODO: autodetect mimetype
*/
if( $filetype == "" )
$filetype = "application/x-unknown-content-type";

$this->aattach[] = $filename;
$this->actype[] = $filetype;
$this->adispo[] = $disposition;
}


/**
* Sets mail priority
*
*
* @param integer Integer betweeen 1 and 5, with 1 beeing the highest
* @return bool
* @access public
* @since 0.1
*/
function setPriority($priority)
{
if(!intval($priority))
return false;

if(!isset($this->priorities[$priority-1]))
return false;

$this->xheaders["X-Priority"] = $this->priorities[$priority-1];
return true;

}


/**
* Sets Organisation header
*
*
* @param string Organistation
* @return void
* @access public
* @since 0.1
*/
public function setOrganization( $org )
{
if( trim( $org != "" ) )
$this->xheaders['Organization'] = $org;
}


/**
* Autovalidate mail adresses
*
*
* @param bool set too true to automaticly validate email adresses
* @return void
* @access public
* @since 0.1
*/
public function autoCheck($bool)
{
if(!empty($bool))
$this->checkAdress = true;
else
$this->checkAdress = false;
}


/**
*Send the mail
*
*
* @access public
* @since 0.1
*/
public function Send()
{
$this->BuildMail();

$this->strTo = implode( ", ", $this->sendto );

/**
* Send the mail
*/
$res = @mail( $this->strTo, $this->xheaders['Subject'], $this->fullBody, $this->headers );
}

/**
* Return the entire email
*
* This function can be used for logging
* or dusplayoing th entire email
*
*
* @access public
* @since 0.1
*/
public function getMail()
{
$this->BuildMail();
$mail = "To: " . $this->strTo . "\n";
$mail .= $this->headers . "\n";
$mail .= $this->fullBody;
return $mail;
}




/**
* Build the email
*
* @param void
* @return void
* @access private
* @since 0.1
*/
function BuildMail()
{

// build the headers
$this->headers = "";

if( count($this->acc) > 0 )
$this->xheaders['CC'] = implode( ", ", $this->acc );

if( count($this->abcc) > 0 )
$this->xheaders['BCC'] = implode( ", ", $this->abcc );

if( $this->charset != "" )
{
$this->xheaders["Mime-Version"] = "1.0";
$this->xheaders["Content-Type"] = "text/plain; charset=$this->charset";
$this->xheaders["Content-Transfer-Encoding"] = $this->ctencoding;
}

$this->xheaders["X-Mailer"] = "PHP/Mailer-Class - By Jorgen v0.1";

/**
* Attach files
*/
if( count( $this->aattach ) > 0 )
$this->buildAttachement();
else
$this->fullBody = $this->body;

reset($this->xheaders);
while(list($hdr,$value) = each($this->xheaders ))
{
if( $hdr != "Subject" )
$this->headers .= $hdr . ": " . $value ."\n";
}
}


/**
* Validate email adresses
*
*
* @param string Email address too valide
* @return void
* @throws exception
* @access private
* @since 0.1
*/
private function validateAdress($address)
{
if( ereg( ".*<(.+)>", $address, $regs ) ) {
$address = $regs[1];
}
if(ereg( "^[^@ ]+@([a-zA-Z0-9\-]+\.)+([a-zA-Z0-9\-]{2}|net|com|gov|mil|org|edu|int)\$",$address) )
return true;
else
throw new Exception("The e-mail adress is malformed");
}


/**
* Check adresses
*
*
* @param array araay with addresses to check
* @return void
* @throws Exception
* @access private
* @since 0.1
*/
private function checkAdresses($aad)
{
if(!is_array($aad))
throw new Exception("Passed parameter is not an array");
$n = count($aad);
for($i=0;$i<$n; $i++ )
{
try
{
$this->validateAdress($aad[$i]) ;
}
catch(Exception $e)
{
echo "Exception caught: ". $e;
}
}
}


/**
* Build Attachment
*
* Attaches files to email
*
*
* @param void
* @return void
* @throws Exception
* @access private
* @since 0.1
*/

private function buildAttachement()
{

$this->xheaders["Content-Type"] = "multipart/mixed;\n boundary=\"". $this->boundary ."\n";

$this->fullBody = "This is a multi-part message in MIME format.\n--" . $this->boundary . "\n";
$this->fullBody .= "Content-Type: text/plain; charset=$this->charset\nContent-Transfer-Encoding: $this->ctencoding\n\n" . $this->body ."\n";

$sep= chr(13) . chr(10);

$ata= array();
$k=0;

// for each attached file, do...
for( $i=0; $i < count( $this->aattach); $i++ )
{

$filename = $this->aattach[$i];
$basename = basename($filename);
$ctype = $this->actype[$i]; // content-type
$disposition = $this->adispo[$i];

if( ! file_exists( $filename) )
{
throw new Exception("File: " . $filename ." cannot be found");
}

$subhdr= "--$this->boundary\nContent-type: " . $ctype >";\n name=\"" . $basename . "\"\nContent-Transfer-Encoding: base64\nContent-Disposition: " . $disposition . ";\n filename=\"" . $basename . "\"\n";
$ata[$k++] = $subhdr;

/**
* non encoded line length
*/
$linesz= filesize( $filename)+1;
$fp= fopen( $filename, 'r' );
$ata[$k++] = chunk_split(base64_encode(fread( $fp, $linesz)));
fclose($fp);
}
$this->fullBody .= implode($sep, $ata);
}


/**
* @var array Array containing adresses to send mail to
* @seesetTo()
*/
var $sendto = array();


/**
* @var array Array containing adresses to cc
* @see setCc()
*/
var $acc = array();


/**
* @var array Array containing adresses to BCC
* @see setBcc()
*/
var $abcc = array();


/**
* @var array Array containing files to attach
* @see setAttachment()
*/
var $aattach = array();


/**
* @var array Array containing extra headers
*/
var $xheaders = array();


/**
* @var integer Priority with 1 beeing highest
* @see setPriority()
*/
var $priorities = array( '1 (Highest)', '2 (High)', '3 (Normal)', '4 (Low)', '5 (Lowest)' );


/**
* @var string Characterset
* @see setBody()
*/
var $charset = "us-ascii";


/**
* @var string Bit encoding
* @see setBody()
*/
var $ctencoding = "7bit";

}
?>

bubblenut
06-13-2005, 08:45 PM
That looks really cool. I've got a couple of points, all of which just layout so they're completely non-essential.

1. Class attributes generally go at the start of a class. It doesn't really matter (you could put them in the middle of the class if you wanted) it's just a convention.

2. I can see one private "helper" method you could create.

private function setCCs($type, $addys) {
//Also here, you should really be doing
//your validation first shouldn't you?
if( $this->checkAddress == true ) {
//Allow this exception to bubble up as there's nothing
//you can do about it here
$this->CheckAdresses($addys);
}
if(is_array($this->$type)) {
//merge the arrays so that users can append arrays of addresses
$this->$type = array_merge($this->$type, $addys);
} else {
$this->$type[] = $addys;
}
}
public function setCC($cc) {
$this->setCCs('acc', $cc);
}


3. The exception handling thing done above there. Not everyone agrees with this (I'd like to hear other peoples views on this particular case) but I'm a fan of allowing exceptions to bubble up and handling them at a higher level. In this case it may actually be better to handle it in the function and build an error log which can then be output when al together at the end.