pnd8_rasp/app/engine/core/smtp.class.php

368 lines
12 KiB
PHP

<?php
/**
* KM_Mailer is a SMTP Class for PHP, Version 1.5
* created by KidMoses (Howard Walsh)
*
* This is a smiple SMTP class that supports secure login
* through TLS or SSL connections. Can be used to send email
* through GMail for example.
*
* Email can be sent as either plain text, html text or a
* combination of both.
* Please send support questions to support@kidmoses.com
*
* INSTRUCTIONS
* Create an instance of the class with a call to :
* $mail = new KM_Mailer(server, port, username=null, password=null, secure=null);
*
* server : the name of the server you are connecting to
* port : the port number to use (typically 25, 465 or 587)
* username : your username needed to log into the server
* password : the password needed to log into the server
* secure : can be tls, ssl or none
*
* You can check if your have successfully logged in by checking $mail->isLogin
*
* Once the instance is created, you can send mail by calling :
* $mail->send(from, to, subject, body, headers = optional);
*
* from : sender's email address (myname@mydomain.com OR MyName <myname@mydomain.com>)
* to : recipient's email address (ie: yourname@yourdomain.com OR YourName <yourname@yourdomain.com>)
* subject : email subject
* body : email message body, usually in HTML format
* headers : any special headers required
*
* See example.php for more tips
*
* In this version you can also add multiple recipents, carbon-copies(CC), blind-copies(BCC) and attachments
* For example:
* $mail->addRecipient("yourname@yourdomain.com");
* $mail->addCC("yourname@yourdomain.com");
* $mail->addBCC("yourname@yourdomain.com");
* $mail->addAttachment("pathToAttachment");
*
* To clear recipients and attachments use:
* $mail->clearRecipients();
* $mail->clearCC();
* $mail->clearBCC();
* $mail->clearAttachments();
*
**/
/**
* Copyright (c) 2011, Howard Walsh, KidMoses.com.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* * Neither the names of Howard Walsh or KidMoses.com, nor
* the names of its contributors may be used to endorse or promote
* products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
* WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
**/
//include("strip_html_tags.php"); /* this script provided by David R. Nadeau, NadeauSoftware.com */
class KM_Mailer {
public $server;
public $port;
public $username;
public $password;
public $secure; /* can be tls, ssl, or none */
public $charset = "\"utf-8\""; /* included double quotes on purpose */
public $contentType = "multipart/mixed"; /* can be set to: text/plain, text/html, multipart/mixed */
public $transferEncodeing = "base64"; /* or 8-bit */
public $altBody = "";
public $isLogin = false;
public $recipients = array();
public $cc = array();
public $bcc = array();
public $attachments = array();
private $conn;
private $newline = "\r\n";
private $localhost = 'localhost';
private $timeout = '60';
private $debug = false;
public function __construct($server, $port, $username=null, $password=null, $secure=null) {
$this->server = $server;
$this->port = $port;
$this->username = $username;
$this->password = $password;
$this->secure = $secure;
if(!$this->connect()) return;
if(!$this->auth()) return;
$this->isLogin = true;
return;
}
/* Connect to the server */
private function connect() {
if(strtolower(trim($this->secure)) == 'ssl') {
$this->server = 'ssl://' . $this->server;
}
$this->conn = fsockopen($this->server, $this->port, $errno, $errstr, $this->timeout);
if (substr($this->getServerResponse(),0,3)!='220') { return false; }
return true;
}
/* sign in / authenicate */
private function auth() {
fputs($this->conn, 'HELO ' . $this->localhost . $this->newline);
$this->getServerResponse();
if(strtolower(trim($this->secure)) == 'tls') {
fputs($this->conn, 'STARTTLS' . $this->newline);
if (substr($this->getServerResponse(),0,3)!='220') { return false; }
stream_socket_enable_crypto($this->conn, true, STREAM_CRYPTO_METHOD_TLS_CLIENT);
fputs($this->conn, 'HELO ' . $this->localhost . $this->newline);
if (substr($this->getServerResponse(),0,3)!='250') { return false; }
}
if($this->server != 'localhost') {
fputs($this->conn, 'AUTH LOGIN' . $this->newline);
if (substr($this->getServerResponse(),0,3)!='334') { return false; }
fputs($this->conn, base64_encode($this->username) . $this->newline);
if (substr($this->getServerResponse(),0,3)!='334') { return false; }
fputs($this->conn, base64_encode($this->password) . $this->newline);
if (substr($this->getServerResponse(),0,3)!='235') { return false; }
}
return true;
}
/* send the email message */
public function send($from, $to, $subject, $message, $headers=null) {
/* set up the headers and message body with attachments if necessary */
$email = "Date: " . date("D, j M Y G:i:s") . " +0300" . $this->newline;
$email .= "From: $from" . $this->newline;
$email .= "Reply-To: $from" . $this->newline;
$email .= $this->setRecipients($to);
if ($headers != null) { $email .= $headers . $this->newline; }
$email .= "Subject: $subject" . $this->newline;
$email .= "MIME-Version: 1.0" . $this->newline;
if($this->contentType == "multipart/mixed") {
$boundary = $this->generateBoundary();
$message = $this->multipartMessage($message,$boundary);
$email .= "Content-Type: $this->contentType;" . $this->newline;
$email .= " boundary=\"$boundary\"";
} else {
$email .= "Content-Type: $this->contentType; charset=$this->charset";
}
$email .= $this->newline . $this->newline . $message . $this->newline;
$email .= "." . $this->newline;
/* set up the server commands and send */
fputs($this->conn, 'MAIL FROM: <'. $this->getMailAddr($from) .'>'. $this->newline);
$this->getServerResponse();
if(!$to=='') {
fputs($this->conn, 'RCPT TO: <'. $this->getMailAddr($to) .'>' . $this->newline);
$this->getServerResponse();
}
$this->sendRecipients($this->recipients);
$this->sendRecipients($this->cc);
$this->sendRecipients($this->bcc);
fputs($this->conn, 'DATA'. $this->newline);
$this->getServerResponse();
fputs($this->conn, $email); /* transmit the entire email here */
if (substr($this->getServerResponse(),0,3)!='250') { return false; }
return true;
}
private function setRecipients($to) { /* assumes there is at least one recipient */
$r = 'To: ';
if(!($to=='')) { $r .= $to . ','; }
if(count($this->recipients)>0) {
for($i=0;$i<count($this->recipients);$i++) {
$r .= $this->recipients[$i] . ',';
}
}
$r = substr($r,0,-1) . $this->newline; /* strip last comma */;
if(count($this->cc)>0) { /* now add in any CCs */
$r .= 'CC: ';
for($i=0;$i<count($this->cc);$i++) {
$r .= $this->cc[$i] . ',';
}
$r = substr($r,0,-1) . $this->newline; /* strip last comma */
}
return $r;
}
private function sendRecipients($r) {
if(empty($r)) { return; }
for($i=0;$i<count($r);$i++) {
fputs($this->conn, 'RCPT TO: <'. $this->getMailAddr($r[$i]) .'>'. $this->newline);
$this->getServerResponse();
}
}
public function addRecipient($recipient) {
$this->recipients[] = $recipient;
}
public function clearRecipients() {
unset($this->recipients);
$this->recipients = array();
}
public function addCC($c) {
$this->cc[] = $c;
}
public function clearCC() {
unset($this->cc);
$this->cc = array();
}
public function addBCC($bc) {
$this->bcc[] = $bc;
}
public function clearBCC() {
unset($this->bcc);
$this->bcc = array();
}
public function addAttachment($filePath) {
$this->attachments[] = $filePath;
}
public function clearAttachments() {
unset($this->attachments);
$this->attachments = array();
}
/* Quit and disconnect */
function __destruct() {
fputs($this->conn, 'QUIT' . $this->newline);
$this->getServerResponse();
fclose($this->conn);
}
/* private functions used internally */
private function getServerResponse() {
$data="";
while($str = fgets($this->conn,4096)) {
$data .= $str;
if(substr($str,3,1) == " ") { break; }
}
if($this->debug) echo $data . "<br>";
return $data;
}
private function getMailAddr($emailaddr) {
$addr = $emailaddr;
$strSpace = strrpos($emailaddr,' ');
if($strSpace > 0) {
$addr= substr($emailaddr,$strSpace+1);
$addr = str_replace("<","",$addr);
$addr = str_replace(">","",$addr);
}
return $addr;
}
private function randID($len) {
$index = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
$out = "";
for ($t=0; $t<$len;$t++) {
$r = rand(0,61);
$out = $out . substr($index,$r,1);
}
return $out;
}
private function generateBoundary() {
$boundary = "--=_NextPart_000_";
$boundary .= $this->randID(4) . "_";
$boundary .= $this->randID(8) . ".";
$boundary .= $this->randID(8);
return $boundary;
}
private function multipartMessage($htmlpart,$boundary) {
if($this->altBody == "") { $this->altBody = strip_tags($htmlpart); }
$altBoundary = $this->generateBoundary();
ob_start(); //Turn on output buffering
$parts = "This is a multi-part message in MIME format." . $this->newline . $this->newline;
$parts .= "--" . $boundary . $this->newline;
$parts .= "Content-Type: multipart/alternative;" . $this->newline;
$parts .= " boundary=\"$altBoundary\"" . $this->newline . $this->newline;
$parts .= "--" . $altBoundary . $this->newline;
$parts .= "Content-Type: text/plain; charset=$this->charset" . $this->newline;
$parts .= "Content-Transfer-Encoding: $this->transferEncodeing" . $this->newline . $this->newline;
$parts .= chunk_split(base64_encode($this->altBody)) . $this->newline . $this->newline;
$parts .= "--" . $altBoundary . $this->newline;
$parts .= "Content-Type: text/html; charset=$this->charset" . $this->newline;
$parts .= "Content-Transfer-Encoding: $this->transferEncodeing" . $this->newline . $this->newline;
$parts .= chunk_split(base64_encode($htmlpart)) . $this->newline . $this->newline;
$parts .= "--" . $altBoundary . "--" . $this->newline . $this->newline;
if(count($this->attachments) > 0) {
for($i=0;$i<count($this->attachments);$i++) {
$attachment = chunk_split(base64_encode(file_get_contents($this->attachments[$i])));
$filename = basename($this->attachments[$i]);
$ext = pathinfo($filename, PATHINFO_EXTENSION);
$parts .= "--" . $boundary . $this->newline;
$parts .= "Content-Type: application/$ext; name=\"$filename\"" . $this->newline;
$parts .= "Content-Transfer-Encoding: base64" . $this->newline;
$parts .= "Content-Disposition: attachment; filename=\"$filename\"" . $this->newline . $this->newline;
$parts .= $attachment . $this->newline;
}
}
$parts .= "--" . $boundary . "--";
$message = ob_get_clean(); //Turn off output buffering
return $parts;
}
}
?>