PHP 邮件功能在 Centos 服务器上不起作用
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/8341678/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
PHP mail function not working on Centos server
提问by Astha
I am using centos Server and have to send the mail to the user so i copied running code of mine from one server and used it in here, but it is not sending mails.
我正在使用 centos 服务器并且必须将邮件发送给用户,所以我从一台服务器复制了我的运行代码并在这里使用它,但它没有发送邮件。
Code is :
代码是:
$to = $email; //writing mail to the user
$subject = "Hii";
$message = "<table>
<tr><td> Hello ".$email.",</td></tr>
<tr><td> Some Text </td></tr>
<tr><td> Some Text </td></tr>
<tr><td> Some Text </td></tr>
<tr><td> Some Text </td></tr>
</table>" ;
$from = "[email protected]";
// To send HTML mail, the Content-type header must be set
$headers = 'MIME-Version: 1.0' . "\r\n";
$headers .= 'Content-type: text/html; charset=iso-8859-1' . "\r\n";
// Additional headers
$headers .= 'From: Team <[email protected]>' . "\r\n";
if(mail($to,$subject,$message,$headers))
{
echo "0";// mail sent Successfully.
}
else
{
echo "1";
}
It always print 1. Same code running fine on other project. Please guide me what i can do to enable it here too? Any help will be highly appreciated!
它总是打印 1. 相同的代码在其他项目上运行良好。请指导我如何在这里启用它?任何帮助将不胜感激!
回答by Astha
After installing sendmail* and running the following commands:
安装 sendmail* 并运行以下命令后:
[root@sendmail ~]# yum install sendmail*
[root@sendmail mail]# yum install dovecot
[root@sendmail mail]# cd /etc/mail/
[root@sendmail mail]# vi local-host-names
# local-host-names - include all aliases for your machine here.
example.com
[root@sendmail mail]# vi /etc/dovecot.conf
protocols = imap pop3 //uncomment
[root@sendmail mail]# m4 sendmail.mc > sendmail.cf
[root@sendmail mail]# make
[root@sendmail mail]# /etc/init.d/sendmail start
[root@sendmail mail]# /etc/init.d/saslauthd start
[root@sendmail mail]# /etc/init.d/dovecot start
[root@sendmail mail]# chkconfig sendmail on
[root@sendmail mail]# chkconfig dovecot on
[root@sendmail mail]# chkconfig saslauthd on
I still had the same issue. I checked my /var/log/maillog
and saw an error:
我仍然有同样的问题。我检查了我的/var/log/maillog
并看到一个错误:
My unqualified host name (domain) unknown; sleeping for retry
After more searching, I changed /etc/hosts
from:
经过更多的搜索,我/etc/hosts
从:
127.0.0.1 localhost localhost.localdomain domain
ip.ip.ip.ip domain localhost
to:
到:
127.0.0.1 localhost.localdomain localhost domain
ip.ip.ip.ip localhost domain
and now the mail function is now working fine.
现在邮件功能现在工作正常。
回答by Timo K?hk?nen
I had the same problem. I have a development server at home and prod server at external server house and incoming mails go to other server. PHP:s mail()
works nicely in server house, but not at home.
我有同样的问题。我在家里有一个开发服务器,在外部服务器上有一个生产服务器,传入的邮件会转到其他服务器。PHP:smail()
在服务器上工作得很好,但在家里不行。
I tested a bit and got it to work at home in the same manner as in server house. The difference between methods in server house and home is the configuration of sendmail. Server house I had only to install sendmail and it was fine, but at home I had to install also sendmail-cf and use it to add outgoing mail server address.
我测试了一下,让它在家里以与在服务器内部相同的方式工作。server house 和 home 的方法区别在于sendmail 的配置。服务器房子我只需要安装sendmail就可以了,但是在家里我还必须安装sendmail-cf并使用它来添加外发邮件服务器地址。
Let's assume you have Centos, Apache and PHP at home server and you want to send emails using PHP:s mail() function.
假设您在家庭服务器上有 Centos、Apache 和 PHP,并且您想使用 PHP:s mail() 函数发送电子邮件。
1) Set hostname on home server into two places: /etc/sysconfig/network and /proc/sys/kernel/hostname this way:
1) 以这种方式将家庭服务器上的主机名设置为两个位置:/etc/sysconfig/network 和 /proc/sys/kernel/hostname:
# nano /etc/sysconfig/network NETWORKING=yes HOSTNAME=mydns157.dlinkddns.com # nano /proc/sys/kernel/hostname HOSTNAME=mydns157.dlinkddns.com
2) Install sendmail and sendmail-cf:
2)安装sendmail和sendmail-cf:
# yum install sendmail sendmail-cf
3) Add the following row into /etc/mail/sendmail.mc, where you have your ISP:s outgoing mail server:
3) 将以下行添加到 /etc/mail/sendmail.mc 中,您有 ISP:s 的外发邮件服务器:
define(`SMART_HOST',`mail.myisp.com')dnl
4) Update sendmail.cf:
4)更新sendmail.cf:
# /etc/mail/make
5) Restart sendmail and apache:
5)重启sendmail和apache:
# service sendmail restart # service httpd restart
6) Boot to update hostname:
6) 开机更新主机名:
# reboot
That's it. Now the following works:
就是这样。现在以下工作:
# php -r'mail("[email protected]", "Subject", "Body", null, "[email protected]");'
You can skip -f:
您可以跳过 -f:
# php -r'mail("[email protected]", "Subject", "Body");'
in which case the sender's name become automatically user@hostname, eg. [email protected].
在这种情况下,发件人的姓名自动变为 user@hostname,例如。[email protected]。
Some notes of hostname
主机名的一些注意事项
The selection of hostname is critical. The default in Centos6 is localhost.localdomain
, but mail()
is not working with it if you skip your own sender address (eg. '[email protected]'
) when calling mail(). If you are sure, that you always call mail() using your real address as sender address, the hostname can be whatever, but if you have existing calls to mail() that lacks the sender address (I have hundreds of this like calls for testing purposes), then you must have a real domain as a hostname, because your server's hostname is used as a sender-address-domain in these cases. Real in the sense that domain must have at least DNS A-record (for some reason my ISP doesn't require NS-record for sender address, only A-record, but test and check with your ISP). The downside of using non-email-domain as a sender address is that replys and delivery notifications will go to bit's heaven, but if you drop sender address in your code, it usually means that you test and debug something and don't need reply functionality. The domain can be eg. the one you get from dynamic dns server eg. mydns157.dlinkddns.com
, which can point to your home router (but not have to). You can get DNS record in PHP using dns_get_record("mydns157.dlinkddns.com")
, which returns an array like this:
主机名的选择至关重要。Centos6 中的默认值是localhost.localdomain
,但mail()
如果您跳过自己的发件人地址(例如'[email protected]'
) 调用 mail() 时。如果你确定你总是使用你的真实地址作为发件人地址来调用 mail(),主机名可以是任何,但是如果你有对缺少发件人地址的 mail() 的现有调用(我有数百个这样的调用测试目的),那么你必须有一个真实的域作为主机名,因为在这些情况下你的服务器的主机名被用作发件人地址域。真正意义上的域必须至少具有 DNS A 记录(出于某种原因,我的 ISP 不需要发件人地址的 NS 记录,只需要 A 记录,但请与您的 ISP 进行测试和检查)。使用非电子邮件域作为发件人地址的缺点是回复和发送通知将进入天堂,但是如果您在代码中删除发件人地址,通常意味着您测试和调试某些内容并且不需要回复功能。域可以是例如。您从动态 dns 服务器获得的那个,例如。mydns157.dlinkddns.com
,它可以指向您的家庭路由器(但不是必须)。您可以使用 PHP 获取 DNS 记录dns_get_record("mydns157.dlinkddns.com")
,它返回一个如下所示的数组:
[host] => mydns157.dlinkddns.com [type] => A [ip] => 92.152.214.137 [class] => IN [ttl] => 7
If type
in above DNS-record is NS
, then the domain acts as an email domain, which is OK for hostname of own server, but the effect is a little different. If you set as hostname an existing email domain eg. myexistingemaildomain.com
, and send a message to [email protected]
eg for debugging purposes, sendmail thinks that the message has to be delivered to mail-folder of user me
on this server. If me
user doesn't exist, the sending fails and if the user exists, then the message goes to /var/mail/me
. This can be what you want, but (like me) you may want that all messages are delivered outside instead of server folders.
如果type
上面的 DNS-record 是NS
,那么这个域就充当了一个 email 域,这对于自己服务器的主机名来说是可以的,但效果有点不同。如果您将现有电子邮件域设置为主机名,例如。myexistingemaildomain.com
,并发送消息到[email protected]
例如用于调试目的,sendmail 认为消息必须传递me
到此服务器上用户的邮件文件夹。如果me
用户不存在,则发送失败,如果用户存在,则消息转到/var/mail/me
。这可能是您想要的,但是(像我一样)您可能希望所有邮件都传递到外部而不是服务器文件夹。
Your hostname (in DNS record) doesn't need to point to your server's actual external IP to make mail() work in lack-of-sender-address cases, but there is no harm of it. The main thing is that hostname has a valid A-record and that the domain belongs to you. If the domain doesn't belong to you, then there may born a security hole. If you set as hostname some existing email domain eg. microsoft.com
(for whatever reason) and send a message to someone without adding your own sender address when calling mail() (eg. '[email protected]'
), the sender address will be automatically [email protected]
. If you are logged as root, the sender address will be [email protected]
. Replys and notifications of failed deliveries go then to [email protected]
and this may not be your intention.
您的主机名(在 DNS 记录中)不需要指向您服务器的实际外部 IP 来使 mail() 在缺少发件人地址的情况下工作,但这没有坏处。最重要的是主机名具有有效的 A 记录并且域属于您。如果域不属于您,那么可能会产生安全漏洞。如果您将一些现有的电子邮件域设置为主机名,例如。microsoft.com
(无论出于何种原因)并在调用 mail() 时向某人发送消息而不添加您自己的发件人地址(例如'[email protected]'
),发件人地址将自动为[email protected]
. 如果您以 root 身份登录,则发件人地址将为[email protected]
。交付失败的回复和通知将发送至[email protected]
,这可能不是您的意图。
回答by preOtep
I know this has been answered but I had a similiar problem. In case anyone else....
我知道这已得到解答,但我遇到了类似的问题。万一别人....
/var/log/maillog showed me a Postfix permission issue.
/var/log/maillog 显示了一个 Postfix 权限问题。
sendmail: fatal: chdir /var/spool/postfix: Permission denied
Tracking down error I found solution to be SELinux policy on CentOS (I'm using version 6).
跟踪错误我发现解决方案是 CentOS 上的 SELinux 策略(我使用的是版本 6)。
Quick answer: setsebool httpd_can_sendmail 1
快速回答: setsebool httpd_can_sendmail 1
You can use -P to make the change permanent; I just needed for password reset e-mail so not needed for my case.
您可以使用 -P 使更改永久化;我只需要密码重置电子邮件,所以我的情况不需要。
Credit: http://www.spidersoft.com.au/2011/posftix-permission-denied-problem/?ModPagespeed=noscript
信用:http: //www.spidersoft.com.au/2011/posftix-permission-denied-problem/?ModPagespeed= noscript
EDIT: I would have commented but I don't have enough reputation yet.
编辑:我会发表评论,但我还没有足够的声誉。
回答by Phil LaNasa
I just had this issue, two things.
我刚刚遇到了这个问题,有两件事。
My emails were going to spam, definitely check that. Probably because my server didn't have proper PTR and SPF records.
我的电子邮件是垃圾邮件,一定要检查一下。可能是因为我的服务器没有正确的 PTR 和 SPF 记录。
But also, I found it a lot easier to test sendmail with this:
而且,我发现用这个测试 sendmail 容易得多:
sendmail -s '[email protected]'
Subject:Testing!
hey there, how ya doin?
CTRL+D
回答by Eamorr
I'd recommend using SwiftMailer to simply a lot of this.
我建议使用 SwiftMailer 来解决很多问题。
require_once('../lib/swiftMailer/lib/swift_required.php');
function sendEmail(){
//Sendmail
$transport = Swift_SendmailTransport::newInstance('/usr/sbin/sendmail -bs');
//Create the Mailer using your created Transport
$mailer = Swift_Mailer::newInstance($transport);
$body="Dear $fname,\n\nYour job application was successful. \n\nYours,\n\nEamorr\n\n\n\n\n\n\n";
//Create a message
$message = Swift_Message::newInstance('Subject goes here')
->setFrom(array($email => "[email protected]"))
->setTo(array($email => "$fname $lname"))
->setBody($body);
//Send the message
$result = $mailer->send($message);
}
回答by Sonal Khunt
回答by Ratul Doley
Always check your maillog in /var/log/maillog to know the cause of the problem.
I had a similar issue once after having properly configured postfix. I got an error saying fatal: setrlimit: Permission denied
. Workaround is check if the httpd can send mail is enabled or not by getsebool httpd_can_sendmail
command. If httpd can send mail is off then enable it by the command: setsebool -P httpd_can_sendmail 1
. Hope this helps.
始终检查 /var/log/maillog 中的邮件日志以了解问题的原因。在正确配置了 postfix 后,我曾经遇到过类似的问题。我有一个错误说fatal: setrlimit: Permission denied
。解决方法是通过getsebool httpd_can_sendmail
命令检查是否启用了 httpd 可以发送邮件。如果 httpd 可以发送邮件关闭,则通过以下命令启用它:setsebool -P httpd_can_sendmail 1
。希望这可以帮助。