首页 > 编程技术 > php

php函数mail()报Could not instantiate mail function.错误解决

发布时间:2016-11-25 17:00

在php发函数时,函数mail()提示Could not instantiate mail function.错误,用phpmailer组件发送也提示这个错误,现在我把解决问题整理出来。


网上有很多朋友用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发邮件时提示SMTP Error: Could not connect to SMTP host错误是smtp服务器的问题我们一起来看看关于SMTP Error: Could not connect to SMTP host问题的解决办法,具体的细节如下所示.

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函数是php自由的一个邮件发送函数了,但有人在使用mail发邮件时出与标题也内容乱码问题了,那么此问题如何处理呢

使用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";

PHPMailer发送邮件配置非常的简单,只要下载一个PHPMailer插件,然后我们再注册一个163邮箱就可以实现php发邮件了,具体例子如下。


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进入。


怎样使用亚马逊云AMAZON SES发邮件。



进入以后,会看到这个蓝色的按钮。

默认注册亚马逊云帐户是不开通SES邮件服务的,需要单独申请。

点击蓝色按钮进入申请页面。


怎样使用亚马逊云AMAZON SES发邮件。



在申请页面前两项是默认的,第三项Region是选择区域,选第一个就行。

Pre-Production Checklist:这个选项中3项全选中。

Use Case Description:这个描述您用SES邮件服务干什么,要写成英文的。


怎样使用亚马逊云AMAZON SES发邮件。



申请完成后,返回SES邮件服务界面,一般亚马逊24小时内会审批完成,就能看到结果。看这张图中的Sending Quota这一条,如果变成了1万,说明亚马逊审核通过,这时候就可以发邮件了。


怎样使用亚马逊云AMAZON SES发邮件。



选中SMTP Setting,点击Create My Smtp这个蓝色的按钮,再点Create按钮,务必记住这个用户名和密码。


怎样使用亚马逊云AMAZON SES发邮件。




怎样使用亚马逊云AMAZON SES发邮件。



安装一个客户端软件,如outlook、foxmail。

根据图片上画出的位置记下对应的SMTP发邮件设置信息,在您的客户端软件里面添上就可以了。


怎样使用亚马逊云AMAZON SES发邮件。



点Email Address,进入验证发邮件地址页面,添加上自己的发信邮箱,验证的时候亚马逊会给您发一封验证信,确认一下就可以。


怎样使用亚马逊云AMAZON SES发邮件。



这时候就可以用您的邮件客户端软件开始发邮件了,一天发上千封是没问题的。

但是这里面有一些注意事项:

1、一个发信邮箱一天最好别发超过5000封,否则以后再发就会进垃圾收件箱。

2、最好不要一次性发出,因为收信邮局有频率限制,连续发太多,实际很多并没有发到。

也可以找一些专业用亚马逊ses发邮件的工具,这些软件一般可以定时发送,设置发送频率,设置发送任务,自动生成邮件黑名单,查询反弹邮件,还有的可以根据不同的客户发送不同的内容等等。

邮件黑名单:空邮件地址和用户退订(用户点这是一封垃圾邮件)

反弹邮件:收到服务器异步返回的信息,有可能是1-2个小时以后才返回,实际由于各种原因并没有发送到,比如发送频率太快,邮件内容不符合要求等。

当然这类工具很多,搜一下就能找到,多对比一下,就能找到自己满意的。

祝大家使用顺利。

注意事项

注册亚马逊云帐号只能是一个信用卡一个电话一个账户,不能重复注册。

申请开通SES邮件服务,需要把申请原因描述的比较清楚,不能一笔带过。

标签:[!--infotagslink--]

您可能感兴趣的文章: