<?php

define('DISPOSITION_INLINE', 'inline');
define('DISPOSITION_ATTACHMENT', 'attachment');

define('CHARSET_ASCII', 'us-ascii');
define('CHARSET_UTF8', 'utf-8');

class Mail
{
  var $Priorities;
  var $Subject;
  var $From;
  var $Recipients;
  var $Bodies;	
  var $Attachments;
  var $AgentIdent;
  var $Organization;
  var $ReplyTo;
  var $Headers;
  
  function __construct()
  {
    $this->Priorities = array('1 (Highest)', '2 (High)', '3 (Normal)', '4 (Low)', '5 (Lowest)');           
    $this->Boundary = md5(date('r', time()));
    $this->AgentIdent = 'PHP/Mail';
    $this->Clear();
  }
  
  function Clear()
  {
    $this->Bodies = array();
    $this->Attachments = array();
    $this->Recipients = array();
    $this->SenderAddress = '';
    $this->SenderName = '';
    $this->Subject = '';
    $this->Organization = '';
    $this->ReplyTo = '';
    $this->Headers = array();
  }

  function AddToCombined($Address)
  {
    $this->Recipients[] = array('Address' => $Address, 'Type' => 'SendCombined');
  }

  function AddTo($Address, $Name)
  {
    $this->Recipients[] = array('Address' => $Address, 'Name' => $Name, 'Type' => 'Send');
  }

  function AddCc($Address, $Name)
  {
    $this->Recipients[] = array('Address' => $Address, 'Name' => $Name, 'Type' => 'Copy');
  }

  function AddBcc($bcc)
  {
    $this->Recipients[] = array('Address' => $Address, 'Name' => $Name, 'Type' => 'HiddenCopy');
  }

  function AddBody($Content, $MimeType = 'text/plain', $Charset = 'utf-8')
  {
    $this->Bodies[] = array('Content' => $Content, 'Type' => strtolower($MimeType), 
      'Charset' => strtolower($Charset));
  }

  function Organization($org)
  {
    if(trim($org != '')) $this->xheaders['Organization'] = $org;
  }

  function Priority($Priority)
  {
    if(!intval($Priority)) return(false);
		
    if(!isset($this->priorities[$Priority - 1])) return(false);

    $this->xheaders['X-Priority'] = $this->priorities[$Priority - 1];	
    return(true);
  }

  function AttachFile($FileName, $FileType, $Disposition = DISPOSITION_ATTACHMENT)
  {	
    $this->Attachments[] = array('FileName' => $FileName, 'FileType' => $FileType, 
      'Disposition' => $Disposition, 'Type' => 'File');
  }

  function AttachData($FileName, $FileType, $Data, $Disposition = DISPOSITION_ATTACHMENT)
  {
    $this->Attachments[] = array('FileName' => $FileName, 'FileType' => $FileType, 
      'Disposition' => $Disposition, 'Type' => 'Data', 'Data' => $Data);
  }

  function Send()
  {
    if(count($this->Bodies) == 0) throw new Exception('Mail: Need at least one text body');
    
    $Body = $this->BuildAttachment($this->BuildBody());
    
    $To = '';
    $this->Headers['CC'] = '';
    $this->Headers['BCC'] = '';
    foreach($this->Recipients as $Index => $Recipient)      
    {
      if($Recipient['Type'] == 'SendCombined')
      {
        if($Index > 0) $To .= ', ';
        $To .= $Recipient['Address'];
      } else
      if($Recipient['Type'] == 'Send')
      {
        if($Index > 0) $To .= ', ';
        $To .= $Recipient['Name'].' <'.$Recipient['Address'].'>';
      } else
      if($Recipient['Type'] == 'Copy')
      {
        if($Index > 0) $this->Headers['CC'] .= ', ';
        $this->Headers['CC'] .= $Recipient['Name'].' <'.$To['Address'].'>';
      } else
      if($Recipient['Type'] == 'HiddenCopy')
      {
        if($Index > 0) $this->Headers['BCC'] .= ', ';
        $this->Headers['BCC'] .= $Recipient['Name'].' <'.$To['Address'].'>';
      }
    }
    if($To == '') throw new Exception('Mail: Need at least one recipient address');
    
    $this->Headers['Mime-Version'] = '1.0';
    
    if($this->AgentIdent != '') $this->Headers['X-Mailer'] = $this->AgentIdent;
    if($this->ReplyTo != '') $this->Headers['Reply-To'] = $this->ReplyTo;
    if($this->From != '') $this->Headers['From'] = $this->From;

    $Headers = '';
    foreach($this->Headers as $Header => $Value) 
    {
      if(($Header != 'Subject') and ($Value != '')) $Headers .= $Header.': '.$Value."\n";
    }   

    $this->Subject = strtr($this->Subject, "\r\n", '  ');

    if($this->Subject == '') throw new Exception('Mail: Missing Subject');
    

    $res = mail($To, $this->Subject, $Body, $Headers);
    return($res);
  }

  function ValidEmail($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 return(false);
  }

  function CheckAdresses($Addresses)
  {
    foreach($Addresses as $Address) 
    {
      if(!$this->ValidEmail($Address)) 
	throw new Exception('Mail: Invalid address '.$Address);
    }
  } 
  
  private function ContentEncoding($Charset)
  {
    if($Charset != CHARSET_ASCII) return('8bit');
      else return('7bit');
  }

  private function BuildAttachment($Body)
  {
    if(count($this->Attachments) > 0)
    {        
      $this->Headers['Content-Type'] = "multipart/mixed;\n boundary=\"PHP-mixed-".$this->Boundary."\"";
      $Result = "This is a multi-part message in MIME format.\n".
        "--PHP-mixed-".$this->Boundary."\n";    
      $Result .= $Body;
    
      foreach($this->Attachments as $Attachment) 
      {
        $FileName = $Attachment['FileName'];
        $BaseName = basename($FileName);
        $ContentType = $Attachment['FileType'];
        $Disposition = $Attachment['Disposition'];
        if($Attachment['Type'] == 'File')
        {
          if(!file_exists($FileName)) 
            throw new Exception('Mail: Attached file '.$FileName.' can\'t be found');
          $Data = file_get_contents($FileName);
        } else 
        if($Attachment['Type'] == 'Data') $Data = $Attachment['Data'];
          else $Data = '';
		
        $Result .= "\n".'--PHP-mixed-'.$this->Boundary."\n".
          "Content-Type: ".$ContentType."; name=\"".$BaseName."\"\n".
          "Content-Transfer-Encoding: base64\n".
          "Content-Disposition: ".$Disposition."\n\n";
        $Result .= chunk_split(base64_encode($Data))."\r\n";
      }
    } else $Result = $Body;
    return($Result);    
  }
  
  private function BuildBody()
  {
    $Result = '';
    if(count($this->Bodies) > 1) 
    {
      $this->Headers['Content-Type'] = 'multipart/alternative; boundary="PHP-alt-'.$this->Boundary.'"';
      $Result .= 'Content-Type: multipart/alternative; boundary="PHP-alt-'.$this->Boundary.'"'.
        "\n\n";
    } else 
    {
      $this->Headers['Content-Type'] = $this->Bodies[0]['Type'].'; charset='.$this->Bodies[0]['Charset'];
      $this->Headers['Content-Transfer-Encoding'] = $this->ContentEncoding($this->Bodies[0]['Charset']);
    }

        
    foreach($this->Bodies as $Body)
    {
      if(count($this->Bodies) > 1) $Result .= "\n\n".'--PHP-alt-'.$this->Boundary."\n";           
      $Result .= 'Content-Type: '.$Body['Type'].'; charset='.$Body['Charset'].
        "\nContent-Transfer-Encoding: ".$this->ContentEncoding($Body['Charset'])."\n\n".$Body['Content']."\n";          
    }
    return($Result);
  }  
}

/*
// Example
$Mail = new Mail();
$Mail->AddTo('nobody@nodomain', 'Recipient');
$Mail->From = 'No reply <noreply@nodomain>';
$Mail->Subject = 'Test message';
$Mail->AddBody('This is sample message sent by PHP Mail class');
$Mail->AddBody('This is sample <strong>HTML</strong> message sent by <i>PHP Mail class</i>', 'text/html');
$Mail->AttachFile('mailtest.php', 'text/plain');
$Mail->AttachData('DataFile.txt', 'text/plain', 'Sample text');
$Mail->Send();
*/

?>