PHP laravel使用自定义邮件类实现发送邮件

2022-10-12 10:10:45

当登录邮箱为腾讯企业邮箱的时候。Phpmailer发送邮件就不好用了,具体哪里不好用,我没真没找到。但是,邮件得发啊,怎么办呢?我这里搞了一个自定义的发送邮件类,腾讯企业邮箱也可用。但是,邮件发送失败...

当登录邮箱为腾讯企业邮箱的时候。

phpmailer发送邮件就不好用了,具体哪里不好用,我没真没找到。

但是,邮件得发啊,怎么办呢?

我这里搞了一个自定义的发送邮件类,腾讯企业邮箱也可用。

但是,邮件发送失败,不会返回报错信息,这个可能是有点坑。

源码如下:

<?php

namespaceApp\Extend;
useException;
/**
*一个简单的PHPSMTP发送邮件类
*/

classSmtpMail
{
/**
*@varstring邮件传输代理用户名
*@Accessprivate
*/
private$_userName;

/**
*@varstring邮件传输代理密码
*@accessprivate
*/
private$_password;

/**
*@varstring邮件传输代理服务器地址
*@accessprivate
*/
private$_sendServer;

/**
*@varint邮件传输代理服务器端口
*@accessprivate
*/
private$_port;

/**
*@varstring发件人
*@accessprotected
*/
protected$_from;

/**
*@varstring收件人
*@accessprotected
*/
protected$_to;

/**
*@varstring抄送
*@accessprotected
*/
protected$_cc;

/**
*@varstring秘密抄送
*@accessprotected
*/
protected$_bcc;

/**
*@varstring主题
*@accessprotected
*/
protected$_subject;

/**
*@varstring邮件正文
*@accessprotected
*/
protected$_body;

/**
*@varstring附件
*@accessprotected
*/
protected$_attachment;

/**
*@varreourcesocket资源
*@accessprotected
*/
protected$_socket;

/**
*@varreource是否是安全连接
*@accessprotected
*/
protected$_isSecurity;

/**
*@varstring错误信息
*@accessprotected
*/
protected$_errorMessage;

protected$_debug=false;
/*输出调试信息*/
privatefunctiondebug($msg)
{
if($this->_debug){
echo$msg,'<br>',"\n";
}
}
publicfunctionsetDebug($val=true)
{
$this->_debug=$val;
}

/**
*设置邮件传输代理,如果是可以匿名发送有邮件的服务器,只需传递代理服务器地址就行
*@accesspublic
*@paramstring$server代理服务器的ip或者域名
*@paramstring$username认证账号
*@paramstring$password认证密码
*@paramint$port代理服务器的端口,smtp默认25号端口
*@paramboolean$isSecurity到服务器的连接是否为安全连接,默认false
*@returnboolean
*/
publicfunctionsetServer($server,$username="",$password="",$port=25,$isSecurity=false)
{
$this->_sendServer=$server;
$this->_port=$port;
$this->_isSecurity=$isSecurity;
$this->_userName=empty($username)?"":base64_encode($username);
$this->_password=empty($password)?"":base64_encode($password);
returntrue;
}

/**
*设置发件人
*@accesspublic
*@paramstring$from发件人地址
*@returnboolean
*/
publicfunctionsetFrom($from)
{
$this->_from=$from;
returntrue;
}

/**
*设置收件人,多个收件人,调用多次.
*@accesspublic
*@paramstring$to收件人地址
*@returnboolean
*/
publicfunctionsetReceiver($to)
{
if(isset($this->_to)){
if(is_string($this->_to)){
$this->_to=array($this->_to);
$this->_to[]=$to;
returntrue;
}elseif(is_array($this->_to)){
$this->_to[]=$to;
returntrue;
}else{
returnfalse;
}
}else{
$this->_to=$to;
returntrue;
}
}

/**
*设置抄送,多个抄送,调用多次.
*@accesspublic
*@paramstring$cc抄送地址
*@returnboolean
*/
publicfunctionsetCc($cc)
{
if(isset($this->_cc)){
if(is_string($this->_cc)){
$this->_cc=array($this->_cc);
$this->_cc[]=$cc;
returntrue;
}elseif(is_array($this->_cc)){
$this->_cc[]=$cc;
returntrue;
}else{
returnfalse;
}
}else{
$this->_cc=$cc;
returntrue;
}
}

/**
*设置秘密抄送,多个秘密抄送,调用多次
*@accesspublic
*@paramstring$bcc秘密抄送地址
*@returnboolean
*/
publicfunctionsetBcc($bcc)
{
if(isset($this->_bcc)){
if(is_string($this->_bcc)){
$this->_bcc=array($this->_bcc);
$this->_bcc[]=$bcc;
returntrue;
}elseif(is_array($this->_bcc)){
$this->_bcc[]=$bcc;
returntrue;
}else{
returnfalse;
}
}else{
$this->_bcc=$bcc;
returntrue;
}
}

/**
*设置邮件附件,多个附件,调用多次
*@accesspublic
*@paramstring$file文件地址
*@returnboolean
*/
publicfunctionaddAttachment($file)
{
if(!file_exists($file)){
$this->_errorMessage="file".$file."doesnotexist.";
returnfalse;
}
if(isset($this->_attachment)){
if(is_string($this->_attachment)){
$this->_attachment=array($this->_attachment);
$this->_attachment[]=$file;
returntrue;
}elseif(is_array($this->_attachment)){
$this->_attachment[]=$file;
returntrue;
}else{
returnfalse;
}
}else{
$this->_attachment=$file;
returntrue;
}
}

/**
*设置邮件信息
*@accesspublic
*@paramstring$body邮件主题
*@paramstring$subject邮件主体内容,可以是纯文本,也可是是html文本
*@returnboolean
*/
publicfunctionsetMail($subject,$body)
{
$this->_subject=$subject;
$this->_body=base64_encode($body);
returntrue;
}

/**
*发送邮件
*@accesspublic
*@returnboolean
*/
publicfunctionsend()
{
$command=$this->getCommand();

$this->_isSecurity?$this->socketSecurity():$this->socket();

foreach($commandas$value){
$result=$this->_isSecurity?$this->sendCommandSecurity($value[0],$value[1]):$this->sendCommand($value[0],$value[1]);
if($result){
continue;
}else{
returnfalse;
}
}

//其实这里也没必要关闭,smtp命令:QUIT发出之后,服务器就关闭了连接,本地的socket资源会自动释放
$this->_isSecurity?$this->closeSecutity():$this->close();
returntrue;
}

/**
*返回错误信息
*@returnstring
*/
publicfunctionerror()
{
if(!isset($this->_errorMessage)){
$this->_errorMessage="";
}
return$this->_errorMessage;
}

/**
*返回mail命令
*@accessprotected
*@returnarray
*/
protectedfunctiongetCommand()
{
$separator="----=_Part_".md5($this->_from.time()).uniqid();//分隔符

$command=array(
array("HELOsendmail\r\n",250)
);
if(!empty($this->_userName)){
$command[]=array("AUTHLOGIN\r\n",334);
$command[]=array($this->_userName."\r\n",334);
$command[]=array($this->_password."\r\n",235);
}

//设置发件人
$command[]=array("MAILFROM:<".$this->_from.">\r\n",250);
$header="FROM:<".$this->_from.">\r\n";

//设置收件人
if(is_array($this->_to)){
$count=count($this->_to);
for($i=0;$i<$count;$i++){
$command[]=array("RCPTTO:<".$this->_to[$i].">\r\n",250);
if($i==0){
$header.="TO:<".$this->_to[$i].">";
}elseif($i+1==$count){
$header.=",<".$this->_to[$i].">\r\n";
}else{
$header.=",<".$this->_to[$i].">";
}
}
}else{
$command[]=array("RCPTTO:<".$this->_to.">\r\n",250);
$header.="TO:<".$this->_to.">\r\n";
}

//设置抄送
if(isset($this->_cc)){
if(is_array($this->_cc)){
$count=count($this->_cc);
for($i=0;$i<$count;$i++){
$command[]=array("RCPTTO:<".$this->_cc[$i].">\r\n",250);
if($i==0){
$header.="CC:<".$this->_cc[$i].">";
}elseif($i+1==$count){
$header.=",<".$this->_cc[$i].">\r\n";
}else{
$header.=",<".$this->_cc[$i].">";
}
}
}else{
$command[]=array("RCPTTO:<".$this->_cc.">\r\n",250);
$header.="CC:<".$this->_cc.">\r\n";
}
}

//设置秘密抄送
if(isset($this->_bcc)){
if(is_array($this->_bcc)){
$count=count($this->_bcc);
for($i=0;$i<$count;$i++){
$command[]=array("RCPTTO:<".$this->_bcc[$i].">\r\n",250);
if($i==0){
$header.="BCC:<".$this->_bcc[$i].">";
}elseif($i+1==$count){
$header.=",<".$this->_bcc[$i].">\r\n";
}else{
$header.=",<".$this->_bcc[$i].">";
}
}
}else{
$command[]=array("RCPTTO:<".$this->_bcc.">\r\n",250);
$header.="BCC:<".$this->_bcc.">\r\n";
}
}

//主题
$header.="Subject:".$this->_subject."\r\n";
if(isset($this->_attachment)){
//含有附件的邮件头需要声明成这个
$header.="Content-Type:multipart/mixed;\r\n";
}elseif(false){
//邮件体含有图片资源的需要声明成这个
$header.="Content-Type:multipart/related;\r\n";
}else{
//html或者纯文本的邮件声明成这个
$header.="Content-Type:multipart/alternative;\r\n";
}

//邮件头分隔符
$header.="\t".'boundary="'.$separator.'"';
$header.="\r\nMIME-Version:1.0\r\n";
$header.="\r\n--".$separator."\r\n";
$header.="Content-Type:text/html;charset=utf-8\r\n";
$header.="Content-Transfer-Encoding:base64\r\n\r\n";
$header.=$this->_body."\r\n";
$header.="--".$separator."\r\n";

//加入附件
if(isset($this->_attachment)&&!empty($this->_attachment)){
if(is_array($this->_attachment)){
$count=count($this->_attachment);
for($i=0;$i<$count;$i++){
$header.="\r\n--".$separator."\r\n";
$header.="Content-Type:".$this->getMIMEType($this->_attachment[$i]).';name="'.basename($this->_attachment[$i]).'"'."\r\n";
$header.="Content-Transfer-Encoding:base64\r\n";
$header.='Content-Disposition:attachment;filename="'.basename($this->_attachment[$i]).'"'."\r\n";
$header.="\r\n";
$header.=$this->readFile($this->_attachment[$i]);
$header.="\r\n--".$separator."\r\n";
}
}else{
$header.="\r\n--".$separator."\r\n";
$header.="Content-Type:".$this->getMIMEType($this->_attachment).';name="'.basename($this->_attachment).'"'."\r\n";
$header.="Content-Transfer-Encoding:base64\r\n";
$header.='Content-Disposition:attachment;filename="'.basename($this->_attachment).'"'."\r\n";
$header.="\r\n";
$header.=$this->readFile($this->_attachment);
$header.="\r\n--".$separator."\r\n";
}
}

//结束邮件数据发送
$header.="\r\n.\r\n";

$command[]=array("DATA\r\n",354);
$command[]=array($header,250);
$command[]=array("QUIT\r\n",221);

return$command;
}

/**
*发送命令
*@accessprotected
*@paramstring$command发送到服务器的smtp命令
*@paramint$code期望服务器返回的响应吗
*@returnboolean
*/
protectedfunctionsendCommand($command,$code)
{
//debug('Sendcommand:'.$command.',expectedcode:'.$code);
//发送命令给服务器
try{
if(socket_write($this->_socket,$command,strlen($command))){

//当邮件内容分多次发送时,没有$code,服务器没有返回
if(empty($code)){
returntrue;
}

//读取服务器返回
$data=trim(socket_read($this->_socket,1024));
//debug('response:'.$data);

if($data){
$pattern="/^".$code."/";
if(preg_match($pattern,$data)){
returntrue;
}else{
$this->_errorMessage="Error:".$data."|**|command:";
returnfalse;
}
}else{
$this->_errorMessage="Error:".socket_strerror(socket_last_error());
returnfalse;
}
}else{
$this->_errorMessage="Error:".socket_strerror(socket_last_error());
returnfalse;
}
}catch(Exception$e){
$this->_errorMessage="Error:".$e->getMessage();
}
}

/**
*发送命令
*@accessprotected
*@paramstring$command发送到服务器的smtp命令
*@paramint$code期望服务器返回的响应吗
*@returnboolean
*/
protectedfunctionsendCommandSecurity($command,$code)
{
//debug('Sendcommand:'.$command.',expectedcode:'.$code);
try{
if(fwrite($this->_socket,$command)){
//当邮件内容分多次发送时,没有$code,服务器没有返回
if(empty($code)){
returntrue;
}
//读取服务器返回
$data=trim(fread($this->_socket,1024));
//debug('response:'.$data);

if($data){
$pattern="/^".$code."/";
if(preg_match($pattern,$data)){
returntrue;
}else{
$this->_errorMessage="Error:".$data."|**|command:";
returnfalse;
}
}else{
returnfalse;
}
}else{
$this->_errorMessage="Error:".$command."sendfailed";
returnfalse;
}
}catch(Exception$e){
$this->_errorMessage="Error:".$e->getMessage();
}
}

/**
*读取附件文件内容,返回base64编码后的文件内容
*@accessprotected
*@paramstring$file文件
*@returnmixed
*/
protectedfunctionreadFile($file)
{
if(file_exists($file)){
$file_obj=file_get_contents($file);
returnbase64_encode($file_obj);
}else{
$this->_errorMessage="file".$file."DOSenotexist";
returnfalse;
}
}

/**
*获取附件MIME类型
*@accessprotected
*@paramstring$file文件
*@returnmixed
*/
protectedfunctiongetMIMEType($file)
{
if(file_exists($file)){
$mime=mime_content_type($file);
if(!preg_match("/gif|jpg|png|jpeg/",$mime)){
$mime="application/octet-stream";
}
return$mime;
}else{
returnfalse;
}
}

/**
*建立到服务器的网络连接
*@accessprivate
*@returnboolean
*/
privatefunctionsocket()
{
//创建socket资源
$this->_socket=socket_create(AF_INET,SOCK_STREAM,getprotobyname('tcp'));

if(!$this->_socket){
$this->_errorMessage=socket_strerror(socket_last_error());
returnfalse;
}

socket_set_block($this->_socket);//设置阻塞模式

//连接服务器
if(!socket_connect($this->_socket,$this->_sendServer,$this->_port)){
$this->_errorMessage=socket_strerror(socket_last_error());
returnfalse;
}
$str=socket_read($this->_socket,1024);
if(!strpos($str,"220")){
$this->_errorMessage=$str;
returnfalse;
}

returntrue;
}

/**
*建立到服务器的SSL网络连接
*@accessprivate
*@returnboolean
*/
privatefunctionsocketSecurity()
{
$remoteAddr="tcp://".$this->_sendServer.":".$this->_port;
$this->_socket=stream_socket_client($remoteAddr,$errno,$errstr,30);
if(!$this->_socket){
$this->_errorMessage=$errstr;
returnfalse;
}

//设置加密连接,默认是ssl,如果需要tls连接,可以查看php手册stream_socket_enable_crypto函数的解释
stream_socket_enable_crypto($this->_socket,true,STREAM_CRYPTO_METHOD_SSLv23_CLIENT);

stream_set_blocking($this->_socket,1);//设置阻塞模式
$str=fread($this->_socket,1024);
if(!strpos($str,"220")){
$this->_errorMessage=$str;
returnfalse;
}

returntrue;
}

/**
*关闭socket
*@accessprivate
*@returnboolean
*/
privatefunctionclose()
{
if(isset($this->_socket)&&is_object($this->_socket)){
$this->_socket->close();
returntrue;
}
$this->_errorMessage="Noresourcecantobeclose";
returnfalse;
}

/**
*关闭安全socket
*@accessprivate
*@returnboolean
*/
privatefunctioncloseSecutity()
{
if(isset($this->_socket)&&is_object($this->_socket)){
stream_socket_shutdown($this->_socket,STREAM_SHUT_WR);
returntrue;
}
$this->_errorMessage="Noresourcecantobeclose";
returnfalse;
}
}

关于laravel5.8框架如何引入第三方类库,请参考下文补充内容 laravel8大同小异。

调用方法:

/**
*@name:发送邮件方法
*@author:camellia
*@date:2021-01-19
*@param:$emailstring发送给谁
*@param:$mail_titlestring邮件标题
*@param:$mail_bodystring邮件内容
*@return:$resultbooltrue/false
*/
publicfunctionsend_mail($email,$mail_title,$mail_body)
{
$mail=newSmtpMail();
$mail->setServer(EMAIL_SERVER,SEND_EMAIL,EMAIL_SECERT,465,true);//参数1(qq邮箱使用smtp.qq.com,qq企业邮箱使用smtp.exmail.qq.com),参数2(邮箱登陆账号),参数3(邮箱登陆密码,也有可能是独立密码,就是开启pop3/smtp时的授权码),参数4(默认25,腾云服务器屏蔽25端口,所以用的465),参数5(是否开启ssl,用465就得开启)//$mail->setServer("XXXXX","joffe@XXXXX","XXXXX",465,true);
$mail->setFrom(SEND_EMAIL,"时间里的博客");//发送者邮箱
$mail->setReceiver($email);//接收者邮箱
$mail->addAttachment("");//Attachment附件,不用可注释
$mail->setMail($mail_title,$mail_body);//标题和内容
$result=$mail->send();//可以var_dump一下,发送成功会返回true,失败false
return$result;//*/
}

代码亲测可用。

补充

laravel5.8引入第三方类库的方法详解

有需求需要使用PHPMailer发送邮件。

那么首先需要引入PHPMailer这个第三方的类库。我是这样做的:

1:在app目录下新建Extend目录。如下图所示:

PHP laravel使用自定义邮件类实现发送邮件

将PHPMailer放入Extend目录下。如下图所示

PHP laravel使用自定义邮件类实现发送邮件

2:修改项目根目录下的composer.json文件

"autoload": {
        "psr-4": {
            "App\\": "app/"
        },
        "classmap": [
            "database/seeds",
            "database/factories",
            "app/Extend/PHPMailer/src"
        ]
    },

添加你第三方类库的位置到autoload中

3:执行composer命令,在网站根目录下:

composer dump-autoload

4:调用:

(1):使用命名空间

use PHPMailer\src\PHPMailer;

(2):调用

 //实例化PHPMailer核心类
$mail = new PHPMailer();

如果报错,就在实例化前边加一个转义符\

至此,laravel引入第三方类库成功。

以上就是PHP laravel使用自定义邮件类实现发送邮件的详细内容,更多关于PHP laravel发送邮件的资料请关注我们其它相关文章!

相关文章 大家在看