/**
* 邮件发送类
*/
class Mail
{
// SMTP服务器名称
private $SmtpHost;
/* SMTP服务端口
+ 标准服务端口,默认为25
*/
private $SmtpPort = 25;
// SMTP用户名
private $SmtpUser = '';
// SMTP用户密码
private $SmtpPassword = '';
/* 超时时间
+ 用于fsockopen()函数,超过该时间未连上则中断
*/
private $TimeOut = 30;
/* 用户身份
+ 用于HELO指令
*/
private $HostName = 'localhost';
/* 开启调试模式 */
private $Debug = false;
/* 是否进行身份验证 */
private $Authentication = false;
/* Private Variables */
private $Socket = false;
/**
* 构造方法
*/
public function __construct($smtpHost = '', $smtpUser = '', $smtpPassword = '', $authentication = false, $smtpPort = 25)
{
$this->SmtpHost = $smtpHost;
$this->SmtpPort = $smtpPort;
$this->SmtpUser = $smtpUser;
$this->SmtpPassword = $smtpPassword;
$this->Authentication = $authentication;
}
/** 发送邮件
* @param string $maiTo 收件人
* @param string $mailFrom 发件人(支持名称:Email)
* @param string $subject 主题
* @param string $body 内容
* @param string $mailType 邮件类型
* @param string $cc 抄送邮件地址
* @param string $bcc 隐藏抄送邮件地址
* @param string $additionalHeaders 附加内容
* @return boolean
*/
public function SendMail($maiTo, $mailFrom, $subject = '', $body = '', $mailType = 'HTML', $cc = '', $bcc = '', $additionalHeaders = '')
{
$header = '';
$header .= "MIME-Version:1.0\r\n";
if ($mailType == 'HTML') {
$header .= "Content-Type:text/html;";
}
$header .= "charset='utf-8'\r\n";
$header .= "Content-Language='zh-cn'\r\n";
$header .= "To: " . $maiTo . "\r\n";
if ($cc != '') {
$header .= "Cc: " . $cc . "\r\n";
}
$header .= "From:" . $mailFrom . "\r\n";
$header .= "Subject:=?UTF-8?B?" . base64_encode($subject). "?=\r\n";
$header .= $additionalHeaders;
$header .= "Date: " . date("r") . "\r\n";
$header .= "X-Mailer:By Redhat (PHP/" . phpversion() . ")\r\n";
list($msec, $sec) = explode(' ', microtime());
$header .= "Message-ID: \r\n";
//收件人地址解析
$maiTo = explode(",", $maiTo);
if ($cc != "") {
$maiTo = array_merge($maiTo, explode(",", $cc));
}
if ($bcc != "") {
$maiTo = array_merge($maiTo, explode(",", $bcc));
}
//邮件是否发送成功标志
$mailSent = true;
foreach ($maiTo as $value) {
if (!$this->SmtpSockopen($value)) {
$this->SmtpDebug("[错误]: 无法发送邮件至 \"" . $value . "\"\n");
$mailSent = false;
continue;
}
if ($this->SmtpSend($this->HostName, $mailFrom, $value, $header, $body)) {
$this->SmtpDebug("[成功]: E-mail已经成功发送至 \n");
} else {
$this->SmtpDebug("[失败]: E-mail无法发送至 \n");
$mailSent = false;
}
fclose($this->Socket);
//$this->SmtpDebug("[失败]: 连接服务器失败\n");
}
$this->SmtpDebug($header);
return $mailSent;
}
/**
* 发送邮件
* @param $helo
* @param $maiFrom
* @param $maiTo
* @param $header
* @param string $body
* @return bool
*/
function SmtpSend($helo, $maiFrom, $maiTo, $header, $body = "")
{
//发送连接命令
if (!$this->SmtpPutcmd("HELO", $helo)) {
return $this->SmtpError("发送 HELO 命令");
}
//身份验证
if ($this->Authentication) {
if (!$this->SmtpPutcmd("AUTH LOGIN", base64_encode($this->SmtpUser))) {
return $this->SmtpError("发送 HELO 命令");
}
if (!$this->SmtpPutcmd("", base64_encode($this->SmtpPassword))) {
return $this->SmtpError("发送 HELO 命令");
}
}
//发件人信息
if (!$this->SmtpPutcmd("MAIL", "FROM:")) {
return $this->SmtpError("发送 MAIL FROM 命令");
}
//收件人信息
if (!$this->SmtpPutcmd("RCPT", "TO:")) {
return $this->SmtpError("发送 RCPT TO 命令");
}
//发送数据
if (!$this->SmtpPutcmd("DATA")) {
return $this->SmtpError("发送 DATA 命令");
}
//发送消息
if (!$this->SmtpMessage($header, $body)) {
return $this->SmtpError("发送 信息");
}
//发送EOM
if (!$this->SmtpEom()) {
return $this->SmtpError("发送 . [EOM]");
}
//发送退出命令
if (!$this->SmtpPutcmd("QUIT")) {
return $this->SmtpError("发送 QUIT 命令");
}
return true;
}
/** 发送SMTP命令
* @param $cmd
* @param $arg
* @return bool
*/
function SmtpPutcmd($cmd, $arg = "")
{
if ($arg != '') {
if ($cmd == '') {
$cmd = $arg;
} else {
$cmd = $cmd . ' ' . $arg;
}
}
fputs($this->Socket, $cmd . "\r\n");
$this->SmtpDebug("> " . $cmd . "\n");
return $this->SmtpOk();
}
/** SMTP错误信息
* @param string $string 错误信息
* @return bool
*/
function SmtpError($string)
{
$this->SmtpDebug("[错误]: 在 " . $string . " 时发生了错误\n");
return false;
}
/** SMTP信息
* @param string $header 头部消息
* @param string $body 内容
* @return bool
*/
function SmtpMessage($header, $body)
{
fputs($this->Socket, $header . "\r\n" . $body);
$this->SmtpDebug("> " . str_replace("\r\n", "\n" . "> ", $header . "\n> " . $body . "\n> "));
return true;
}
/* EOM */
function SmtpEom()
{
fputs($this->Socket, "\r\n.\r\n");
$this->SmtpDebug(". [EOM]\n");
return $this->SmtpOk();
}
/* SMTP OK */
function SmtpOk()
{
$response = str_replace("\r\n", "", fgets($this->Socket, 512));
$this->SmtpDebug($response . "\n");
if (preg_match("/^[23]/", $response) == 0) {
fputs($this->Socket, "QUIT\r\n");
fgets($this->Socket, 512);
$this->SmtpDebug("[错误]: 服务器返回 \"" . $response . "\"\n");
return false;
}
return true;
}
/* debug
* @param string $message 错误消息
*/
private function SmtpDebug($message)
{
if ($this->Debug) {
echo $message . "
";
}
}
/** 网络Socket链接准备
* @param string $address 邮件地址
* @return boolean
*/
private function SmtpSockopen($address)
{
if ($this->SmtpHost == '') {
return $this->SmtpSockopenMx($address);
} else {
return $this->SmtpSockopenRelay($this->SmtpHost);
}
}
/** 获取MX记录
* @param string $address 邮件地址
* @return boolean
*/
private function SmtpSockopenMx($address)
{
$domain = ereg_replace("^.+@([^@]+)$", "\\1", $address);
if (!$this->MyCheckdnsrr($domain, 'mx')) {
$this->SmtpDebug("[错误]: 无法找到 MX记录 \"" . $domain . "\"\n");
return false;
}
$this->SmtpSockopenRelay($domain);
$this->SmtpDebug('[错误]: 无法连接 MX主机 (' . $domain . ")\n");
return false;
}
/** 打开网络Socket链接
* @param string $smtpHost 服务器名称
* @return boolean
*/
private function SmtpSockopenRelay($smtpHost)
{
$this->SmtpDebug('[操作]: 尝试连接 "' . $smtpHost . ':' . $this->SmtpPort . "\"\n");
$this->Socket = @stream_socket_client('tcp://' . $smtpHost . ':' . $this->SmtpPort, $errno, $errstr, $this->TimeOut);
if (!($this->Socket && $this->SmtpOk())) {
$this->SmtpDebug('[错误]: 无法连接服务器 "' . $smtpHost . "\n");
$this->SmtpDebug('[错误]: ' . $errstr . " (" . $errno . ")\n");
return false;
}
$this->SmtpDebug('[成功]: 成功连接 ' . $smtpHost . ':' . $this->SmtpPort . "\"\n");
return true;;
}
/** 自定义邮箱有效性验证
* + 解决window下checkdnsrr函数无效情况
* @param string $hostName 主机名
* @param string $recType 类型(可以是MX、NS、SOA、PTR、CNAME 或 ANY)
* @return boolean
*/
function MyCheckdnsrr($hostName, $recType = 'MX')
{
if ($hostName != '') {
$recType = $recType == '' ? 'MX' : $recType;
exec("nslookup -type=$recType $hostName", $result);
foreach ($result as $line) {
if (preg_match("/^$hostName/", $line) > 0) {
return true;
}
}
return false;
}
return false;
}
}
//邮件配置
$title = 'xxx';
$sm = new Mail('xxx.xxx.xxx', 'xxx', 'xxx',true);
$sendTo = "xxx@xxx.xxx";
$end = $sm->SendMail($sendTo,'xxx@xxx.xxx',$title,$content);
if ($end) echo $end;
else echo "发送成功!";