php函数mail()报Could not instantiate mail function.错误解决
网上有很多朋友用phpmailer组件发送邮件提示:Could not instantiate mail function.错误,解决方案少之用少,原因是服务器没有安装sendmail组件,使用yum进行安装:
yum install sendmail
/etc/init.d/sendmail start
注意:如果sendmail启动缓慢,请将hostname加入到/etc/hosts里面
配置/usr/local/php/etc/php.ini,填写sendmail绝对路径:
vim /usr/local/php/etc/php.ini
sendmail_path = /usr/sbin/sendmail -t -i
:wq!
/etc/init.d/php-fpm restart
PHPMailer是一个非常棒的开源邮件类,使用也非常简单,但是对于虚拟主机来说,往往要受到各种限制。刚才我在虚拟主机上使用 PHPMailer就遇到一个“SMTP Error: Could not connect to SMTP host”错误。下面介绍两种解决办法:
这个错误说明虚拟主机不支持PHPMailer默认调用的fsockopen函数,找到class.smtp.php文件,搜索fsockopen,就找到了这样一段代码:
// connect to the smtp server
$this->smtp_conn = @fsockopen($host,// the host of the server
$port,// the port to use
$errno, // error number if any
$errstr, // error message if any
$tval); // give up after ? secs
方法1:将fsockopen函数替换成pfsockopen函数
因为pfsockopen的参数与fsockopen基本一致,所以只需要将@fsockopen替换成@pfsockopen就可以了。
方法2:使用stream_socket_client函数
一般fsockopen()被禁,pfsockopen也有可能被禁,所以这里介绍另一个函数stream_socket_client()。
stream_socket_client的参数与fsockopen有所不同,所以代码要修改为:
$this->smtp_conn = stream_socket_client(“tcp://”.$host.”:”.$port, $errno, $errstr, $tval);
补充:
解决办法:很多网站列出的解决办法说是因为smtp大小写的问题,虽然问题的本质不在这里,但确实也需要改这个地方,至于为什么,看下面的操作。
在 class.phpmailer.php 中,将:
function IsSMTP(){$this->Mailer='smtp';}
改成:
function IsSMTP(){$this->Mailer = 'SMTP';}
这个地方的修改不是使用了smtp来发送邮件,而是使用了另外一种方式发送邮件,检查 class.phpmailer.php 文件里面有下面这么一段:
switch($this->Mailer){
case 'sendmail':
return $this->SendmailSend($header, $body);
case 'smtp'://由于SMTP和smtp不相等 所以选择的是下面MailSend发送邮件 并不是使用smtp发送邮件
return $this->SmtpSend($header, $body);
default:
return $this->MailSend($header, $body);
}
(2)Linux主机禁用了fsockopen()函数
国内有很多空间服务商出于安全考虑会禁用服务器的fsockopen函数。
解决方法:
用pfsockopen() 函数代替 fsockopen() ,如果 pfsockopen 函数也被禁用的话,还可换其他可以操作Socket函数来代替, 如stream_socket_client()
在 class.smtp.php 中将 @fsockopen 改成 @pfsockopen
把
$this->smtp_conn = @fsockopen($host, // the host of the server
改成:
$this->smtp_conn = @pfsockopen($host, // the host of the server
$port, // the port to use
$errno, // error number if any
$errstr, // error message if any
$tval); // give up after ? secs
(3)防火墙安全设置规则,如果以上两种方案都不凑效,那估计是防火墙的规则问题了,可以让服务器管理员去掉所有的防火墙规则,然后测试一下,看是否是这个原因。
使用mail方法发信时,如果标题或发件人含有中文就会造成乱码,而正文不会。解决办法如下
先用函数base64_encode() ? 使用 MIME base64 对数据进行编码
标题字符串前加编码类型例如: =?UTF-8?B?
标题字符串后加:?=
邮件header说明Content-type ? 防止邮件正文也乱码
首先在报文头加入声明
//如果你的网站是GBK,下面将utf-8改为gbk
$headers = 'MIME-Version: 1.0' . "\r\n";
$headers .= 'Content-type: text/html; charset=utf-8' . "\r\n";
然后在需要使用中文的地方将中文进行如下转移
//如果你的网站是GBK,下面将utf-8改为gb2312
//例如标题
$subject = "新密码通知信";
$subject = "=?UTF-8?B?".base64_encode($subject)."?=";
//例如发件人
$headers .= 'From: =?UTF-8?B?'.base64_encode("某某网站").'?=<service@apieye.com>' . "\r\n";
1.首先是下载PHPMailer
2.解压
从中取出class.phpmailer.php 和 class.smtp.php 放到你的项目的文件夹,因为我们等下会引用到它们.
3.创建发送邮件的函数,其中你需要配置smtp服务器
function postmail($to,$subject = '',$body = ''){
//Author:smsyun WebSite: http://www.111cn.net
//$to 表示收件人地址 $subject 表示邮件标题 $body表示邮件正文
//error_reporting(E_ALL);
error_reporting(E_STRICT);
date_default_timezone_set('Asia/Shanghai');//设定时区东八区
require_once('class.phpmailer.php');
include('class.smtp.php');
$mail = new PHPMailer(); //new一个PHPMailer对象出来
$body = eregi_replace("[\]",'',$body); //对邮件内容进行必要的过滤
$mail->CharSet ="utf-8";//设定邮件编码,默认ISO-8859-1,如果发中文此项必须设置,否则乱码
$mail->IsSMTP(); // 设定使用SMTP服务
$mail->SMTPDebug = 1; // 启用SMTP调试功能
// 1 = errors and messages
// 2 = messages only
$mail->SMTPAuth = true; // 启用 SMTP 验证功能
$mail->SMTPSecure = "ssl"; // 安全协议,可以注释掉
$mail->Host = 'stmp.163.com'; // SMTP 服务器
$mail->Port = 25; // SMTP服务器的端口号
$mail->Username = 'smsyun'; // SMTP服务器用户名,PS:我乱打的
$mail->Password = 'password'; // SMTP服务器密码
$mail->SetFrom('xxx@xxx.xxx', 'who');
$mail->AddReplyTo('xxx@xxx.xxx','who');
$mail->Subject = $subject;
$mail->AltBody = 'To view the message, please use an HTML compatible email viewer!'; // optional, comment out and test
$mail->MsgHTML($body);
$address = $to;
$mail->AddAddress($address, '');
//$mail->AddAttachment("images/phpmailer.gif"); // attachment
//$mail->AddAttachment("images/phpmailer_mini.gif"); // attachment
if(!$mail->Send()) {
echo 'Mailer Error: ' . $mail->ErrorInfo;
} else {
// echo "Message sent!恭喜,邮件发送成功!";
}
}
4. 使用函数
postmail('admin@163.com','测试标题','测试内容');
如果发不出邮件我们可以检测一下是不是邮箱没用开启stmp与pop3功能了,这个可以到163邮箱中去开启了,还有一个如果是新注册的163邮箱是不能发送哦,注册久了才可以使用。
本文教程我们来讲解使用亚马逊云AMAZON SES发邮件的详细步骤,前面是用文字描述,后面那篇附带了每个步骤的图片。使用SES发邮件
(1) 使用SES(Simple Email Service)发邮件的时候,我们需要添加一个发件者邮箱(verify email sender),SES使用这个发件者邮箱作为发件者,添加完认证发信者之后,需要登录发信者邮箱点击确认连接。
SNS(简单消息服务)还有个类似的功能,叫topic,类似邮件组,将多个verified receivers添加到一个topic,然后在CloudWatch或者其他的服务调用,来发群邮件。这次先不讨论SNS。
可以使用下面这小段代码来添加verified sender
import boto.ses
conn = boto.ses.connect_to_region('us-east-1')
conn.verify_email_address('sender@address.com')
对了,截止我写这些时,SES只支持三个地区,Virginia,Ireland,Oregon(分别对应us-east-1, eu-west-1, us-west-2)
(2) 接来下我们收集SMTP credential相关信息
在SMTP Settings里面我们可以看到SMTP相关信息,例如Virginia地区的:
Server Name: email-smtp.us-east-1.amazonaws.com
Port: 25, 465 or 587
Use Transport Layer Security (TLS): Yes
Authentication: Your SMTP credentials - see below.
然后在下面创建SMTP credential点击创建,他就自动创建了一个IAM角色并授权,并产生一组了类似AccessKey的信息,不过名字变成Username和password,形如:
IAM User Name,Smtp Username,Smtp Password
"ses-smtp-user.xxxx",AKIxxx,Aqbxxxxxxxxxxxxxxxxxx
(3) 这样使用SMTP发邮件的信息收集全了。可使用ConfigObj来加载配置文件中的Credential,并用smtplib来创建发邮件的对象
import smtplib
from configobj import ConfigObj
cfg = ConfigObj(config_path)
cfg_dict = cfg.dict()
host = cfg_dict["server"]
from_addr = cfg_dict["from_addr"]
username = cfg_dict["username"]
password = cfg_dict["password"]
server = smtplib.SMTP(host)
server.starttls()
server.login(username, password)
server.sendmail(from_addr, receivers, BODY)
server.quit()
配置文件形如:
server = email-smtp.us-east-1.amazonaws.com
from_addr = sender@domain.com
username = AKIxxx
password = Aqbxxxxxxxxxxxxxxxxxx
使用亚马逊云AMAZON SES发邮件图解步骤
普通企业发邮件很少,一般使用Gmail、163.com、Hotmail.com、QQ邮箱之类的邮箱直接发送就可以了。
但是如果您的客户比较多,日发送量超过500封以上,这就成了一个大问题,因为上面所说邮箱每日发送量都是有限额的,多了就发不出去了。
亚马逊云(aws)是世界上最早的也是最成熟的云平台,它上面提供了一个叫做SES的邮件服务,专门为满足上面所说的情况,每日发送几万封也是没问题得。
注册亚马逊云帐号,搜亚马逊云可找到。
注册帐号的时候需要一个手机、普通信用卡
安装一个普通邮件客户端软件,比如foxmail、outlook
方法/步骤
首先是注册亚马逊云帐号,并登陆AWS管理控制台,选择SES进入。
进入以后,会看到这个蓝色的按钮。
默认注册亚马逊云帐户是不开通SES邮件服务的,需要单独申请。
点击蓝色按钮进入申请页面。
在申请页面前两项是默认的,第三项Region是选择区域,选第一个就行。
Pre-Production Checklist:这个选项中3项全选中。
Use Case Description:这个描述您用SES邮件服务干什么,要写成英文的。
申请完成后,返回SES邮件服务界面,一般亚马逊24小时内会审批完成,就能看到结果。看这张图中的Sending Quota这一条,如果变成了1万,说明亚马逊审核通过,这时候就可以发邮件了。
选中SMTP Setting,点击Create My Smtp这个蓝色的按钮,再点Create按钮,务必记住这个用户名和密码。
安装一个客户端软件,如outlook、foxmail。
根据图片上画出的位置记下对应的SMTP发邮件设置信息,在您的客户端软件里面添上就可以了。
点Email Address,进入验证发邮件地址页面,添加上自己的发信邮箱,验证的时候亚马逊会给您发一封验证信,确认一下就可以。
这时候就可以用您的邮件客户端软件开始发邮件了,一天发上千封是没问题的。
但是这里面有一些注意事项:
1、一个发信邮箱一天最好别发超过5000封,否则以后再发就会进垃圾收件箱。
2、最好不要一次性发出,因为收信邮局有频率限制,连续发太多,实际很多并没有发到。
也可以找一些专业用亚马逊ses发邮件的工具,这些软件一般可以定时发送,设置发送频率,设置发送任务,自动生成邮件黑名单,查询反弹邮件,还有的可以根据不同的客户发送不同的内容等等。
邮件黑名单:空邮件地址和用户退订(用户点这是一封垃圾邮件)
反弹邮件:收到服务器异步返回的信息,有可能是1-2个小时以后才返回,实际由于各种原因并没有发送到,比如发送频率太快,邮件内容不符合要求等。
当然这类工具很多,搜一下就能找到,多对比一下,就能找到自己满意的。
祝大家使用顺利。
注意事项
注册亚马逊云帐号只能是一个信用卡一个电话一个账户,不能重复注册。
申请开通SES邮件服务,需要把申请原因描述的比较清楚,不能一笔带过。
相关文章
Ecshop提示Only variables should be passed by reference in错误
在安装好ecshop软件之后我们打开首页时提示Only variables should be passed by reference in错误了,碰到这个问题是什么原因呢?下面我们就一起来看看解决办法吧。...2016-11-25- 409错误是什么?http 409错误怎么解决呢?不少站长在遇到这个错误代码之后都一筹莫展,本次一聚教程网为大家带来了详细的说明,快来看看吧。 409错误是什么: HTTP 40...2017-01-22
- 414错误是HTTP协议状态码中的一种,很多都还不知道414错误是什么,以及不知道怎么解决414错误,那么就来看看小编带来的介绍吧。 414错误是什么: HTTP 414错误,(Requ...2017-01-22
- http 405错误是什么?http 405错误怎么解决?相信很多站长都在找这两个问题的答案,本次小编为大家带来了详细的教程,快来看看吧。 405错误是什么: HTTP 405错误是H...2017-01-22
- eval函数在php中是一个函数并不是系统组件函数,我们在php.ini中的disable_functions是无法禁止它的,因这他不是一个php_function哦。 eval()针对php安全来说具有很...2016-11-25
- 在php中eval是一个函数并且不能直接禁用了,但eval函数又相当的危险了经常会出现一些问题了,今天我们就一起来看看eval函数对数组的操作 例子, <?php $data="array...2016-11-25
- 401是HTTP状态码的一种,属于“请示错误”,表示请求可能出错,已妨碍了服务器对请求的处理。具体的401错误是指:未授权,请求要求进行身份验证。登录后,服务器可能会返回对页面...2017-01-22
Python astype(np.float)函数使用方法解析
这篇文章主要介绍了Python astype(np.float)函数使用方法解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下...2020-06-08- http 402错误是什么?402错误较为少见,一般不轻易出现,下面小编就来告诉大家402错误是什么吧。 HTTP 402错误是HTTP状态码的一种,表示“要求付费”; 所求的...2017-01-22
- 411错误是HTTP协议状态码的一种,很多人都还不知道411错误是什么,本次一聚教程网将为大家进行解答,并且告诉大家411错误怎么解决。 411错误是什么: HTTP 411错误,(Lengt...2017-01-22
- 403错误是网站访问过程中,常见的错误提示。资源不可用,服务器理解客户的请求,但拒绝处理它。通常由于服务器上文件或目录的权限设置导致,比如IIS或者apache设置了访问权限...2017-01-22
- Apache status 503 的原因大致有如下几种情况 : 1、 CPU 负载过高,服务器响应不过来,返回503 2、 系统连接数超限,超过MaxVhostClients的上限,返回503 3、 单IP连接数超限,超过M...2016-01-28
- 403错误是HTTP状态码的一种,属于“请示错误”,表示服务器拒绝请求。如果在搜索引擎尝试抓取您网站上的有效网页时显示此状态代码,那么,这可能是您的服务器或主机拒绝搜索...2017-01-22
- 这篇文章主要介绍了Python中的imread()函数用法说明,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-03-16
- 412错误是什么?412错误怎么解决?本次一聚教程网将为大家带来详细的介绍,帮助大家全面了解412错误的意思以及解决412错误的方法。 412错误是什么: HTTP 412错误,(Precond...2017-01-22
- 相信很多站长都遇到过这样一个问题,访问页面时出现408错误,下面一聚教程网将为大家介绍408错误出现的原因以及408错误的解决办法。 HTTP 408错误出现原因: HTT...2017-01-22
- 本文主要介绍了C# 中取绝对值的函数。具有很好的参考价值。下面跟着小编一起来看下吧...2020-06-25
- HTTP 406错误是HTTP协议状态码的一种,表示无法使用请求的内容特性来响应请求的网页。一般是指客户端浏览器不接受所请求页面的 MIME 类型。 而MIME类型是在把输出...2017-01-22
- 下面小编就为大家带来一篇C#学习笔记- 随机函数Random()的用法详解。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧...2020-06-25
- 407错误是什么?407错误怎么解决?不少站长都遇到过407错误,下面小编将告诉大家如何处理407错误。 407错误是什么: HTTP 407错误是HTTP协议状态码的一种,表示需要代...2017-01-22