mirror of
https://github.com/lkddi/nexusphp.git
synced 2026-04-03 14:10:57 +08:00
532 lines
9.1 KiB
PHP
532 lines
9.1 KiB
PHP
<?php
|
|
|
|
/**
|
|
* Allows users to send email without e-mailserver on the localmachine
|
|
* @package SMTP
|
|
* @author Fredrik Haugbergsmyr <smtp.lib@lagnut.net>
|
|
*/
|
|
|
|
require_once ('net.const.php');
|
|
|
|
/**
|
|
* @version 0.0.2.2
|
|
* @access public
|
|
* @todo split messages, attachments
|
|
*/
|
|
class smtp
|
|
{
|
|
|
|
|
|
/**
|
|
* lagnut-smtp version, send in the headers
|
|
*
|
|
* @var string
|
|
* @access private
|
|
*/
|
|
var $_version = '0.0.2.2';
|
|
|
|
|
|
/**
|
|
* Turn debugon / off
|
|
*
|
|
* @var bool
|
|
* @access private
|
|
*/
|
|
var $_debug = false;
|
|
|
|
|
|
/**
|
|
* Serverconnection resource
|
|
*
|
|
* @var resource
|
|
* @access private
|
|
*/
|
|
var $_connection = null;
|
|
|
|
|
|
/**
|
|
* E-mailheaders
|
|
*
|
|
* @var array headers
|
|
* @access private
|
|
*/
|
|
var $_hdrs = array();
|
|
|
|
|
|
/**
|
|
* E-mailbody
|
|
*
|
|
* @var string
|
|
* @access private
|
|
*/
|
|
var $_body = '';
|
|
|
|
|
|
/**
|
|
* Default Content type
|
|
*
|
|
* @var string
|
|
* @access private
|
|
*/
|
|
var $_mime = 'text/html';
|
|
|
|
|
|
/**
|
|
* Default Charset
|
|
*
|
|
* @var string
|
|
* @access private
|
|
*/
|
|
var $_charset = 'UTF-8';
|
|
|
|
/**
|
|
* Default Transfer-Content-Encoding
|
|
*
|
|
* @var string
|
|
* @access private
|
|
*/
|
|
var $_CTEncoding = 'base64';
|
|
|
|
// These are actually not necessary, but for the shitty eYou email system
|
|
/**
|
|
* Charset for Special Case
|
|
*
|
|
* @var string
|
|
* @access private
|
|
*/
|
|
var $_charset_eYou = 'GBK';
|
|
|
|
/**
|
|
* Charset for Special Case
|
|
*
|
|
* @var string
|
|
* @access private
|
|
*/
|
|
var $_specialcase = 'eYou';
|
|
|
|
/**
|
|
* Class contruction, sets client headers
|
|
*
|
|
* @access public
|
|
*/
|
|
function smtp($charset = 'UTF-8', $specialcase = "")
|
|
{
|
|
$this->_specialcase = $specialcase;
|
|
$this->_charset = $charset;
|
|
$this->_add_hdr('X-Mailer', sprintf('LAGNUT-SMTP/%s', $this->_version));
|
|
$this->_add_hdr('User-Agent', sprintf('LAGNUT-SMTP/%s', $this->_version));
|
|
$this->_add_hdr('MIME-Version', '1.0');
|
|
}
|
|
|
|
|
|
/**
|
|
* Turn debugging on/off
|
|
*
|
|
* @access public
|
|
* @param bool $debug command
|
|
*/
|
|
function debug($debug)
|
|
{
|
|
$this->_debug = (bool)$debug;
|
|
}
|
|
|
|
|
|
/**
|
|
* Clean input to prevent injection
|
|
*
|
|
* @param string $input User data
|
|
*/
|
|
function _clean(&$input)
|
|
{
|
|
if (!is_string($input)) {
|
|
return false;
|
|
}
|
|
$input = urldecode($input);
|
|
$input = str_replace("\n", '', str_replace("\r", '', $input));
|
|
}
|
|
|
|
|
|
/**
|
|
* Send command to server
|
|
*
|
|
* @access private
|
|
* @param string $cmdcommand
|
|
* @param optional $data data
|
|
*/
|
|
function _cmd($cmd, $data = false)
|
|
{
|
|
$this->_clean($cmd);
|
|
$this->_clean($data);
|
|
|
|
if ($this->_is_closed()) {
|
|
return false;
|
|
}
|
|
|
|
if (!$data) {
|
|
$command = sprintf("%s\r\n", $cmd);
|
|
}else {
|
|
$command = sprintf("%s: %s\r\n", $cmd,$data);
|
|
}
|
|
|
|
fwrite($this->_connection, $command);
|
|
$resp = $this->_read();
|
|
if ($this->_debug){
|
|
printf($command);
|
|
printf($resp);
|
|
}
|
|
if ($this->_is_closed($resp)) {
|
|
return false;
|
|
}
|
|
return $resp;
|
|
}
|
|
|
|
|
|
/**
|
|
* Collects header
|
|
*
|
|
* @access private
|
|
* @param string$key
|
|
* @param string $data
|
|
*/
|
|
function _add_hdr($key, $data)
|
|
{
|
|
$this->_clean($key);
|
|
$this->_clean($data);
|
|
$this->_hdrs[$key] = sprintf("%s: %s\r\n", $key, $data);
|
|
}
|
|
|
|
|
|
/**
|
|
* Read server output
|
|
*
|
|
* @access private
|
|
* @return string
|
|
*/
|
|
function _read()
|
|
{
|
|
if ($this->_is_closed()) {
|
|
return false;
|
|
}
|
|
$o = '';
|
|
do {
|
|
$str = @fgets($this->_connection, 515);
|
|
if (!$str) {
|
|
break;
|
|
}
|
|
$o .= $str;
|
|
if (substr($str, 3, 1) == ' ') {
|
|
break;
|
|
}
|
|
} while (true);
|
|
return $o;
|
|
}
|
|
|
|
|
|
/**
|
|
* Checks if server denies more commands
|
|
*
|
|
* @access private
|
|
* @param $int
|
|
* @return bool true if connection is closed
|
|
*/
|
|
function _is_closed($response = false)
|
|
{
|
|
if (!$this->_connection) {
|
|
return true;
|
|
}
|
|
if (isset($response{0}) && ($response{0} == 4|| $response{0}== 5)) {
|
|
$this->close();
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
/**
|
|
* Open connection to server
|
|
*
|
|
* @access public
|
|
* @param string $server SMTP server
|
|
* @param int $port Server port
|
|
*/
|
|
function open($server, $port = 25)
|
|
{
|
|
$this->_connection = fsockopen($server, $port, $e, $er, 8);
|
|
|
|
if ($this->_is_closed()) {
|
|
return false;
|
|
}
|
|
|
|
$init= $this->_read();
|
|
if ($this->_debug){
|
|
printf($init);
|
|
}
|
|
|
|
if ($this->_is_closed($init)) {
|
|
return false;
|
|
}
|
|
|
|
$lhost = (isset($_SERVER['SERVER_ADDR']) ? $_SERVER['SERVER_ADDR'] : '127.0.0.1');
|
|
|
|
if (strpos($init,'ESMTP') === false){
|
|
$this->_cmd('HELO '. gethostbyaddr($lhost));
|
|
} else {
|
|
$this->_cmd('EHLO '. gethostbyaddr($lhost));
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* Start TLS communication
|
|
*
|
|
* @access public
|
|
*/
|
|
function start_tls()
|
|
{
|
|
if (!function_exists('stream_socket_enable_crypto')) {
|
|
trigger_error('TLS is not supported', E_USER_ERROR);
|
|
return false;
|
|
}
|
|
$this->_cmd('STARTTLS');
|
|
stream_socket_enable_crypto($this->_connection, true, STREAM_CRYPTO_METHOD_TLS_CLIENT);
|
|
}
|
|
|
|
|
|
/**
|
|
* Performs SMTP authentication
|
|
*
|
|
* @access public
|
|
* @param string $username username
|
|
* @param string $password password
|
|
* @param int authentication mecanism
|
|
*/
|
|
function auth($username, $password, $type = LOGIN)
|
|
{
|
|
|
|
include_once ('sasl.lib.php');
|
|
$sasl =& new sasl($sasl, $username, $password);
|
|
switch ($type) {
|
|
case PLAIN:
|
|
$this->_cmd('AUTH PLAIN');
|
|
$this->_cmd($sasl->plain($username, $password));
|
|
break;
|
|
case LOGIN:
|
|
$this->_cmd('AUTH LOGIN');
|
|
$this->_cmd($sasl->login($username));
|
|
$this->_cmd($sasl->login($password));
|
|
break;
|
|
case CRAM_MD5:
|
|
$resp = explode(' ', $this->_cmd('AUTH CRAM-MD5'));
|
|
$this->_cmd($sasl->cram_md5($username, $password, trim($resp[1])));
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* Closes connection to the server
|
|
*
|
|
* @access public
|
|
*/
|
|
function close()
|
|
{
|
|
if ($this->_is_closed()) {
|
|
return false;
|
|
}
|
|
|
|
$this->_cmd('RSET');
|
|
$this->_cmd('QUIT');
|
|
fclose($this->_connection);
|
|
$this->_connection = null;
|
|
}
|
|
|
|
|
|
/**
|
|
* E-mail sender
|
|
*
|
|
* @access public
|
|
* @param string $from Sender
|
|
*/
|
|
function from($email, $name = '')
|
|
{
|
|
$from = !empty($name) ? sprintf('%s <%s>', $name, $email) : $email;
|
|
$this->_cmd('MAIL FROM', sprintf('<%s>', $email));
|
|
$this->_add_hdr('FROM', $from);
|
|
$this->_add_hdr('Return-path', $email);
|
|
}
|
|
|
|
/**
|
|
* Set BCC header
|
|
*
|
|
* @access public
|
|
* @param string $tolist recipients whose email address should be concealed
|
|
*/
|
|
function bcc($tolist)
|
|
{
|
|
$this->_add_hdr('Bcc', $tolist);
|
|
}
|
|
|
|
|
|
/**
|
|
* Send reply-to header
|
|
*
|
|
* @param string $to
|
|
*/
|
|
function reply_to($email, $name = '')
|
|
{
|
|
$to = !empty($name) ? sprintf('%s <%s>', $name, $email) : $email;
|
|
$this->_add_hdr('REPLY-TO', $to);
|
|
}
|
|
|
|
|
|
/**
|
|
* E-mail reciever
|
|
*
|
|
* @access public
|
|
* @param string $to Reciever
|
|
*/
|
|
function to($email, $name = '')
|
|
{
|
|
$to = !empty($name) ? sprintf('%s <%s>', $name, $email) : $email;
|
|
$this->_cmd('RCPT TO', sprintf('<%s>', $email));
|
|
$this->_add_hdr('TO', $to);
|
|
}
|
|
|
|
/**
|
|
* Multiple E-mail reciever
|
|
*
|
|
* @access public
|
|
* @param string $email Reciever, with out other recepients info disclosed
|
|
*/
|
|
function multi_to($email)
|
|
{
|
|
$this->_cmd('RCPT TO', sprintf('<%s>', $email));
|
|
}
|
|
|
|
/**
|
|
* E-mail reciever
|
|
*
|
|
* @access public
|
|
* @param string $email TO head on mass mailing
|
|
*/
|
|
function multi_to_head($to)
|
|
{
|
|
$this->_add_hdr('TO', $to);
|
|
}
|
|
|
|
/**
|
|
* MIME type
|
|
*
|
|
* @access public
|
|
* @param string $mime MIME type
|
|
*/
|
|
function mime_charset($mime = 'text/html',$charset = 'UTF-8')
|
|
{
|
|
$this->_charset = $charset;
|
|
$this->_mime = $mime;
|
|
$this->_add_hdr('Content-type', sprintf('%s; charset=%s', $this->_mime, $this->_charset));
|
|
}
|
|
|
|
/**
|
|
* MIME Content-Transfer-Encoding
|
|
*
|
|
* @access public
|
|
* @param string $mime MIME type
|
|
*/
|
|
function mime_content_transfer_encoding($CTEncoding = 'base64')
|
|
{
|
|
$this->_CTEncoding = $CTEncoding;
|
|
$this->_add_hdr('Content-Transfer-Encoding', sprintf('%s', $this->_CTEncoding));
|
|
}
|
|
|
|
/**
|
|
* E-mail subject
|
|
*
|
|
* @access public
|
|
* @param string $subject subject
|
|
*/
|
|
function subject($subject)
|
|
{
|
|
$this->_clean($subject);
|
|
|
|
if($this->_specialcase = "")
|
|
$this->_add_hdr('SUBJECT', $this->encode_hdrs($subject));
|
|
elseif($this->_specialcase = "eYou")
|
|
{
|
|
$temp = $this->_charset;
|
|
$this->_charset = $this->_charset_eYou;
|
|
$this->_add_hdr('SUBJECT', $this->encode_hdrs($subject));
|
|
$this->_charset = $temp;
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* E-mail body
|
|
*
|
|
* @access public
|
|
* @param string $body body
|
|
*/
|
|
function body($body)
|
|
{
|
|
$body = preg_replace("/([\n|\r])\.([\n|\r])/", "$1..$2", $body);
|
|
|
|
if($this->_CTEncoding == 'base64')
|
|
$this->_body = sprintf("\r\n%s", base64_encode($body));
|
|
}
|
|
|
|
|
|
/**
|
|
* Send the mail
|
|
*
|
|
* @access public
|
|
*/
|
|
function send()
|
|
{
|
|
$resp = $this->_cmd('DATA');
|
|
if ($this->_is_closed($resp)) {
|
|
$this->close();
|
|
return false;
|
|
}
|
|
foreach ($this->_hdrs as $header) {
|
|
fwrite($this->_connection, $header);
|
|
if ($this->_debug) {
|
|
printf($header);
|
|
}
|
|
}
|
|
fwrite($this->_connection,$this->_body);
|
|
fwrite($this->_connection, "\r\n.\r\n");
|
|
$resp = trim($this->_read());
|
|
if ($this->_debug){
|
|
printf("%s\r\n", $this->_body);
|
|
printf("\r\n.\r\n");
|
|
printf('%s', $resp);
|
|
}
|
|
if ((int)$resp{0} != 2) {
|
|
return false;
|
|
} else {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* encode headers
|
|
*
|
|
* @access private
|
|
* @param string $input
|
|
* @return string
|
|
*/
|
|
function encode_hdrs($input)
|
|
{
|
|
$replacement = preg_replace('/([\x80-\xFF])/e', '"=" . strtoupper(dechex(ord("\1")))', $input);
|
|
|
|
$input = str_replace($input, sprintf('=?%s?Q?%s?=', $this->_charset, $replacement), $input);
|
|
return $input;
|
|
}
|
|
|
|
|
|
}
|
|
|
|
?>
|