[ Index ]
 

Code source de dotProject 2.1 RC1

Accédez au Source d'autres logiciels libres | Soutenez Angelica Josefina !

title

Body

[fermer]

/classes/ -> libmail.class.php (source)

   1  <?php /* CLASSES $Id: libmail.class.php,v 1.14.8.9 2007/01/31 09:36:52 ajdonnison Exp $ */
   2  /**
   3   *    @package dotproject
   4   *    @subpackage utilites
   5  */
   6  
   7  if (!defined('DP_BASE_DIR')){
   8      die('You should not access this file directly');
   9  }
  10  
  11  /**
  12   *    This class encapsulates the PHP mail() function.
  13   *
  14   *    implements CC, Bcc, Priority headers
  15   *    @version    1.3
  16   *    <ul>
  17   *    <li>added ReplyTo( $address ) method
  18   *    <li>added Receipt() method - to add a mail receipt
  19   *    <li>added optionnal charset parameter to Body() method. this should fix charset problem on some mail clients
  20   *    </ul>
  21   *    Example
  22   *    <code>
  23   *    include "libmail.php";
  24   *
  25   *    $m= new Mail; // create the mail
  26   *    $m->From( "leo@isp.com" );
  27   *    $m->To( "destination@somewhere.fr" );
  28   *    $m->Subject( "the subject of the mail" );
  29   *
  30   *    $message= "Hello world!\nthis is a test of the Mail class\nplease ignore\nThanks.";
  31   *    $m->Body( $message);    // set the body
  32   *    $m->Cc( "someone@somewhere.fr");
  33   *    $m->Bcc( "someoneelse@somewhere.fr");
  34   *    $m->Priority(4) ;    // set the priority to Low
  35   *    $m->Attach( "/home/leo/toto.gif", "image/gif" ) ;    // attach a file of type image/gif
  36   *    $m->Send();    // send the mail
  37   *    echo "the mail below has been sent:<br><pre>", $m->Get(), "</pre>";
  38   *    </code>
  39  
  40  LASTMOD
  41      Fri Oct  6 15:46:12 UTC 2000
  42  
  43   *    @author    Leo West - lwest@free.fr
  44   */
  45  class Mail
  46  {
  47  /**
  48   *    list of To addresses
  49   *    @var    array
  50   */
  51      var $sendto = array();
  52  /**
  53   *    @var    array
  54  */
  55      var $acc = array();
  56  /**
  57   *    @var    array
  58  */
  59      var $abcc = array();
  60  /**
  61   *    paths of attached files
  62   *    @var array
  63  */
  64      var $aattach = array();
  65  /**
  66   *    list of message headers
  67   *    @var array
  68      */
  69      var $xheaders = array();
  70      /**
  71   *    message priorities referential
  72   *    @var array
  73      */
  74      var $priorities = array( '1 (Highest)', '2 (High)', '3 (Normal)', '4 (Low)', '5 (Lowest)' );
  75      /**
  76   *    character set of message
  77   *    @var string
  78      */
  79      var $charset = "us-ascii";
  80      var $ctencoding = "7bit";
  81      var $receipt = 0;
  82  
  83      var $useRawAddress = true;
  84  
  85      var $host;
  86      var $port;
  87      var $sasl;
  88      var $username;
  89      var $password;
  90      var $transport;
  91      var $defer;
  92  
  93  /**
  94   *    Mail constructor
  95  */
  96  function Mail()
  97  {
  98      global $dPconfig;
  99  
 100      $this->autoCheck( true );
 101      $this->boundary= "--" . md5( uniqid("myboundary") );
 102      // Grab the current mail handling options
 103      $this->transport = isset($dPconfig['mail_transport']) ? $dPconfig['mail_transport'] : 'php';
 104      $this->host = isset($dPconfig['mail_host']) ? $dPconfig['mail_host'] : 'localhost';
 105      $this->port = isset($dPconfig['mail_port']) ? $dPconfig['mail_port'] : '25';
 106      $this->sasl = isset($dPconfig['mail_auth']) ? $dPconfig['mail_auth'] : false;
 107      $this->username = @$dPconfig['mail_user'];
 108      $this->password = @$dPconfig['mail_pass'];
 109      $this->defer = @$dPconfig['mail_defer'];
 110      $this->timeout = isset($dPconfig['mail_timeout']) ? $dPconfig['mail_timeout'] : 0;
 111  }
 112  
 113  
 114  /**
 115   *    activate or desactivate the email addresses validator
 116   *
 117   *    ex: autoCheck( true ) turn the validator on
 118   *    by default autoCheck feature is on
 119  
 120   *    @param boolean    $bool set to true to turn on the auto validation
 121   *    @access public
 122  */
 123  function autoCheck( $bool )
 124  {
 125      if( $bool ) {
 126          $this->checkAddress = true;
 127      } else {
 128          $this->checkAddress = false;
 129      }
 130  }
 131  
 132  
 133  /**
 134   *    Define the subject line of the email
 135   *    @param string $subject any monoline string
 136   *    @param string $charset encoding to be used for Quoted-Printable encoding of the subject 
 137  */
 138  function Subject( $subject, $charset='' ) {
 139      global $dPconfig;
 140  
 141      if( isset($charset) && $charset != "" ) {
 142          $this->charset = strtolower($charset);
 143      }
 144      
 145      global $AppUI;
 146      
 147      if ( ( $AppUI->user_locale != 'en' || ( $this->charset && $this->charset != 'us-ascii' && $this->charset != 'utf-8') ) && function_exists('imap_8bit')) {
 148          $subject = "=?".$this->charset."?Q?".
 149              str_replace("=\r\n","",imap_8bit($subject))."?=";        
 150      }
 151      $this->xheaders['Subject'] = $dPconfig['email_prefix'].' '.strtr( $subject, "\r\n" , "  " );
 152  }
 153  
 154  
 155  /**
 156   *    set the sender of the mail
 157   *    @param string $from should be an email address
 158  
 159  */
 160  
 161  function From( $from ) {
 162      if( ! is_string($from) ) {
 163          echo "Class Mail: error, From is not a string";
 164          exit;
 165      }
 166      $this->xheaders['From'] = $from;
 167  }
 168  
 169  /**
 170   *    set the Reply-to header
 171   *    @param string $email should be an email address
 172  */
 173  function ReplyTo( $address ) {
 174      if (!is_string($address)) {
 175          return false;
 176      }
 177      $this->xheaders["Reply-To"] = $address;
 178  }
 179  
 180  /**
 181   *    add a receipt to the mail ie.  a confirmation is returned to the "From" address (or "ReplyTo" if defined)
 182   *    when the receiver opens the message.
 183   *    @warning this functionality is *not* a standard, thus only some mail clients are compliants.
 184  */
 185  
 186  function Receipt() {
 187      $this->receipt = 1;
 188  }
 189  
 190  /**
 191   *    set the mail recipient
 192   *
 193   *    The optional reset parameter is useful when looping through records to send individual mails.
 194   *    This prevents the 'to' array being continually stacked with additional addresses.
 195   *
 196   *    @param string $to email address, accept both a single address or an array of addresses
 197   *    @param boolean $reset resets the current array
 198  */
 199  
 200  function To( $to, $reset=false ) {
 201  
 202      // TODO : test validit? sur to
 203      if( is_array( $to ) ) {
 204          $this->sendto = $to;
 205      } else {
 206          if ($this->useRawAddress) {
 207             if( preg_match( "/^(.*)\<(.+)\>$/", $to, $regs ) ) {
 208                $to = $regs[2];
 209             }
 210          }
 211          if ($reset) {
 212              unset( $this->sendto );
 213              $this->sendto = array();
 214          }
 215          $this->sendto[] = $to;
 216      }
 217  
 218      if( $this->checkAddress == true )
 219          $this->CheckAdresses( $this->sendto );
 220  
 221  }
 222  
 223  
 224  /**
 225   *    Cc()
 226   *    set the CC headers ( carbon copy )
 227   *    $cc : email address(es), accept both array and string
 228   */
 229  
 230  function Cc( $cc ) {
 231      if( is_array($cc) )
 232          $this->acc= $cc;
 233      else
 234          $this->acc= explode(',', $cc);
 235  
 236      if( $this->checkAddress == true )
 237          $this->CheckAdresses( $this->acc );
 238  
 239  }
 240  
 241  /**
 242   *    set the Bcc headers ( blank carbon copy ).
 243   *    $bcc : email address(es), accept both array and string
 244   */
 245  
 246  function Bcc( $bcc ) {
 247      if( is_array($bcc) ) {
 248          $this->abcc = $bcc;
 249      } else {
 250          $this->abcc[]= $bcc;
 251      }
 252  
 253      if( $this->checkAddress == true )
 254          $this->CheckAdresses( $this->abcc );
 255  }
 256  
 257  /**
 258   *        set the body (message) of the mail
 259   *        define the charset if the message contains extended characters (accents)
 260   *        default to us-ascii
 261   *        $mail->Body( "m?l en fran?ais avec des accents", "iso-8859-1" );
 262   */
 263  function Body( $body, $charset="" ) {
 264      $this->body = $body;
 265  
 266      if( isset($charset) && $charset != "" ) {
 267          $this->charset = strtolower($charset);
 268          if( $this->charset != "us-ascii" )
 269              $this->ctencoding = "8bit";
 270      }
 271  }
 272  
 273  /**
 274   *        set the Organization header
 275   */
 276  function Organization( $org ) {
 277      if( trim( $org != "" )  )
 278          $this->xheaders['Organization'] = $org;
 279  }
 280  
 281  /**
 282   *        set the mail priority
 283   *        $priority : integer taken between 1 (highest) and 5 ( lowest )
 284   *        ex: $mail->Priority(1) ; => Highest
 285   */
 286  
 287  function Priority( $priority ) {
 288      if( ! intval( $priority ) )
 289          return false;
 290  
 291      if( ! isset( $this->priorities[$priority-1]) )
 292          return false;
 293  
 294      $this->xheaders["X-Priority"] = $this->priorities[$priority-1];
 295  
 296      return true;
 297  }
 298  
 299  /**
 300   *    Attach a file to the mail
 301   *
 302   *    @param string $filename : path of the file to attach
 303   *    @param string $filetype : MIME-type of the file. default to 'application/x-unknown-content-type'
 304   *    @param string $disposition : instruct the Mailclient to display the file if possible ("inline") or always as a link ("attachment") possible values are "inline", "attachment"
 305   */
 306  function Attach( $filename, $filetype = "", $disposition = "inline" ) {
 307      // TODO : si filetype="", alors chercher dans un tablo de MT connus / extension du fichier
 308      if( $filetype == "" )
 309          $filetype = "application/x-unknown-content-type";
 310  
 311      $this->aattach[] = $filename;
 312      $this->actype[] = $filetype;
 313      $this->adispo[] = $disposition;
 314  }
 315  
 316  /**
 317   *    Build the email message
 318   *    @access protected
 319  */
 320  function BuildMail() {
 321  // build the headers
 322      global $AppUI;
 323  
 324      $this->headers = "";
 325  //    $this->xheaders['To'] = implode( ", ", $this->sendto );
 326  
 327      if( count($this->acc) > 0 ) {
 328          $this->xheaders['CC'] = implode( ", ", $this->acc );
 329      }
 330      if( count($this->abcc) > 0 ) {
 331          $this->xheaders['BCC'] = implode( ", ", $this->abcc );
 332      }
 333  
 334      if( $this->receipt ) {
 335          if( isset($this->xheaders["Reply-To"] ) ) {
 336              $this->xheaders["Disposition-Notification-To"] = $this->xheaders["Reply-To"];
 337          } else {
 338              $this->xheaders["Disposition-Notification-To"] = $this->xheaders['From'];
 339          }
 340      }
 341  
 342      if( $this->charset != "" ) {
 343          $this->xheaders["Mime-Version"] = "1.0";
 344          $this->xheaders["Content-Type"] = "text/plain; charset=$this->charset";
 345          $this->xheaders["Content-Transfer-Encoding"] = $this->ctencoding;
 346      }
 347  
 348      $this->xheaders["X-Mailer"] = "dotProject v" . $AppUI->getVersion();
 349  
 350      // include attached files
 351      if( count( $this->aattach ) > 0 ) {
 352          $this->_build_attachement();
 353      } else {
 354          $sep = "\n";
 355          $arr = preg_split("/(\r?\n)|\r/", $this->body);
 356          $this->fullBody = implode($sep, $arr);
 357      }
 358  
 359      reset($this->xheaders);
 360      while( list( $hdr,$value ) = each( $this->xheaders )  ) {
 361          if( $hdr != "Subject" )
 362              $this->headers .= "$hdr: $value\n";
 363      }
 364  }
 365  
 366  /**
 367   *    format and send the mail
 368   *    @access public
 369  */
 370  function Send() {
 371      $this->BuildMail();
 372  
 373      $this->strTo = implode( ", ", $this->sendto );
 374  
 375      if ($this->defer)
 376          return $this->QueueMail();
 377      else if ($this->transport == 'smtp')
 378          return $this->SMTPSend( $this->sendto, $this->xheaders['Subject'], $this->fullBody, $this->xheaders );
 379      else
 380          return @mail( $this->strTo, $this->xheaders['Subject'], $this->fullBody, $this->headers );
 381  }
 382  
 383  /**
 384   * Send email via an SMTP connection.
 385   *
 386   * Work based loosly on that of Bugs Genie, which appears to be in turn based on something from 'Ninebirds'
 387   *
 388   * @access public
 389   */
 390  function SMTPSend($to, $subject, $body, &$headers) {
 391      global $AppUI, $dPconfig;
 392  
 393      // Start the connection to the server
 394      $error_number = 0;
 395      $error_message = '';
 396      $this->socket = fsockopen($this->host, $this->port, $error_number, $error_message, $this->timeout);
 397      if (! $this->socket) {
 398          dprint(__FILE__, __LINE__, 1, "Error on connecting to host {$this->host} at port {$this->port}: $error_message ($error_number)");
 399          $AppUI->setMsg("Cannot connect to SMTP Host: $error_message ($error_number)");
 400          return false;
 401      }
 402      // Read the opening stuff;
 403      $this->socketRead();
 404      // Send the protocol start
 405      $this->socketSend("HELO " . $this->getHostName());
 406      if ($this->sasl && $this->username) {
 407          $this->socketSend("AUTH LOGIN");
 408          $this->socketSend(base64_encode($this->username));
 409          $rcv = $this->socketSend(base64_encode($this->password));
 410          if (strpos($rcv, '235') !== 0) {
 411              dprint(__FILE__, __LINE__, 1, "Authentication failed on server: $rcv");
 412              $AppUI->setMsg("Failed to login to SMTP server: $rcv");
 413              fclose($this->socket);
 414              return false;
 415          }
 416      }
 417      // Determine the mail from address.
 418      if ( ! isset($headers['From'])) {
 419          $from = $dPconfig['admin_user'] . '@' . $dPconfig['site_domain'];
 420      } else {
 421          // Search for the parts of the email address
 422          if (preg_match('/.*<([^@]+@[a-z0-9\._-]+)>/i', $headers['From'], $matches))
 423              $from = $matches[1];
 424          else
 425              $from = $headers['From'];
 426      }
 427      $rcv = $this->socketSend("MAIL FROM: <$from>");
 428      if (substr($rcv,0,1) != '2') {
 429          $AppUI->setMsg("Failed to send email: $rcv", UI_MSG_ERROR);
 430          return false;
 431      }
 432      foreach ($to as $to_address) {
 433          if (strpos($to_address, '<') !== false) {
 434              preg_match('/^.*<([^@]+\@[a-z0-9\._-]+)>/i', $to_address, $matches);
 435              if (isset($matches[1]))
 436                  $to_address = $matches[1];
 437          }
 438          $rcv = $this->socketSend("RCPT TO: <$to_address>");
 439          if (substr($rcv,0,1) != '2') {
 440              $AppUI->setMsg("Failed to send email: $rcv", UI_MSG_ERROR);
 441              return false;
 442          }
 443      }
 444      $this->socketSend("DATA");
 445      foreach ($headers as $hdr =>$val) {
 446          $this->socketSend("$hdr: $val", false);
 447      }
 448      // Now build the To Headers as well.
 449      $this->socketSend("To: " . implode(', ', $to), false);
 450      $this->socketSend("Date: " . date('r'), false);
 451      $this->socketSend("", false);
 452      $this->socketSend($body, false);
 453      $result = $this->socketSend(".\r\nQUIT");
 454      if (strpos($result, '250') === 0)
 455          return true;
 456      else {
 457          dprint(__FILE__, __LINE__, 1, "Failed to send email from $from to $to_address: $result");
 458          $AppUI->setMsg("Failed to send email: $result");
 459          return false;
 460      }
 461  }
 462  
 463  function socketRead()
 464  {
 465      $result = fgets($this->socket, 4096);
 466      dprint(__FILE__, __LINE__, 12, "server said: $result");
 467      return $result;
 468  }
 469  
 470  function socketSend($msg, $rcv = true)
 471  {
 472      dprint(__FILE__, __LINE__, 12, "sending: $msg");
 473      $sent = fputs($this->socket, $msg . "\r\n");
 474      if ($rcv)
 475          return $this->socketRead();
 476      else
 477          return $sent;
 478  }
 479  
 480  function getHostName()
 481  {
 482    // Grab the server address, return a hostname for it.
 483    if ($host = gethostbyaddr($_SERVER['SERVER_ADDR']))
 484      return $host;
 485    else
 486      return '[' . $_SERVER['SERVER_ADDR'] . ']';
 487  }
 488  
 489  /**
 490   * Queue mail to allow the queue manager to trigger
 491   * the email transfer.
 492   *
 493   * @access private
 494   */
 495  function QueueMail() {
 496      global $AppUI;
 497  
 498      require_once $AppUI->getSystemClass('event_queue');
 499      $ec = new EventQueue;
 500      $vars = get_object_vars($this);
 501      return $ec->add(array('Mail', 'SendQueuedMail'), $vars, 'libmail', true);
 502  }
 503  
 504  /**
 505   * Dequeue the email and transfer it.  Called from the queue manager.
 506   *
 507   * @access private
 508   */
 509  function SendQueuedMail($mod, $type, $originator, $owner, &$args) {
 510      extract($args);
 511      if ($this->transport == 'smtp') {
 512          return $this->SMTPSend($sendto, $xheaders['Subject'], $fullBody, $xheaders);
 513      } else {
 514          return @mail( $strTo, $xheaders['Subject'], $fullBody, $headers );
 515      }
 516  }
 517  
 518  /**
 519   *    Returns the whole e-mail , headers + message
 520   *
 521   *    can be used for displaying the message in plain text or logging it
 522   *
 523   *    @return string
 524   */
 525  function Get() {
 526      $this->BuildMail();
 527      $mail = "To: " . $this->strTo . "\r\n";
 528      $mail .= $this->headers . "\r\n";
 529      $mail .= $this->fullBody;
 530      return $mail;
 531  }
 532  
 533  /**
 534   *    check an email address validity
 535   *    @access public
 536   *    @param string $address : email address to check
 537   *    @return true if email adress is ok
 538   */
 539  function ValidEmail($address) {
 540     if( preg_match( "/^(.*)\<(.+)\>$/", $address, $regs ) ) {
 541        $address = $regs[2];
 542     }
 543     if( preg_match( "/^[^@ ]+@([a-zA-Z0-9.\-.]+)$/",$address) ) {
 544        return true;
 545     } else {
 546        return false;
 547     }
 548  }
 549  
 550  /**
 551   *    check validity of email addresses
 552   *    @param    array $aad -
 553   *    @return if unvalid, output an error message and exit, this may -should- be customized
 554   */
 555  
 556  function CheckAdresses( $aad ) {
 557      for($i=0;$i< count( $aad); $i++ ) {
 558          if( ! $this->ValidEmail( $aad[$i]) ) {
 559              echo "Class Mail, method Mail : invalid address $aad[$i]";
 560              exit;
 561          }
 562      }
 563      return true;
 564  }
 565      /**
 566       * alias for the mispelled CheckAdresses
 567       */
 568  	function CheckAddresses($aad) {
 569          return $this->CheckAdresses($aad);
 570      }
 571  
 572  /**
 573   *    check and encode attach file(s) . internal use only
 574   *    @access private
 575  */
 576  function _build_attachement() {
 577      $this->xheaders["Content-Type"] = "multipart/mixed;\r\n boundary=\"$this->boundary\"";
 578  
 579      $this->fullBody = "This is a multi-part message in MIME format.\r\n--$this->boundary\r\n";
 580      $this->fullBody .= "Content-Type: text/plain; charset=$this->charset\r\nContent-Transfer-Encoding: $this->ctencoding\r\n\r\n";
 581  
 582      $sep= "\r\n";
 583      $body = preg_split("/\r?\n/", $this->body);
 584      $this->fullBody .= implode($sep, $body) ."\r\n";
 585  
 586      $ata= array();
 587      $k=0;
 588  
 589      // for each attached file, do...
 590      for( $i=0; $i < count( $this->aattach); $i++ ) {
 591          $filename = $this->aattach[$i];
 592          $basename = basename($filename);
 593          $ctype = $this->actype[$i];    // content-type
 594          $disposition = $this->adispo[$i];
 595  
 596          if( ! file_exists( $filename) ) {
 597              echo "Class Mail, method attach : file $filename can't be found"; exit;
 598          }
 599          $subhdr= "--$this->boundary\r\nContent-type: $ctype;\r\n name=\"$basename\"\r\nContent-Transfer-Encoding: base64\r\nContent-Disposition: $disposition;\r\n  filename=\"$basename\"\r\n";
 600          $ata[$k++] = $subhdr;
 601          // non encoded line length
 602          $linesz= filesize( $filename)+1;
 603          $fp= fopen( $filename, 'r' );
 604          $ata[$k++] = chunk_split(base64_encode(fread( $fp, $linesz)));
 605          fclose($fp);
 606      }
 607      $this->fullBody .= implode($sep, $ata);
 608  }
 609  
 610  } // class Mail
 611  
 612  
 613  ?>


Généré le : Sun Feb 18 19:46:52 2007 par Balluche grâce à PHPXref 0.7