- 我有一台 VPS 服务器
- 我在该 VPS 服务器上运行着一个 Postfix 邮件服务器(我按照教程通过命令行安装了它)
- 我在该 VPS 服务器上运行着一个 SMTP 服务器
- 我也有邮件服务器所需的记录,例如(MX 记录、SPF 记录、PTR 记录、DMARC 记录、A 记录),我通过 mxtoolbox 检查器检查了它们,结果全部正确
但不幸的是,无论我使用什么方式,我仍然无法发送或接收邮件:
- usermin(端口:20000)
- 甚至从我的网站使用 PHPMailer 库
我的 Postfix 配置文件是:
# See /usr/share/postfix/main.cf.dist for a commented, more complete version
# Debian specific: Specifying a file name will cause the first
# line of that file to be used as the name. The Debian default
# is /etc/mailname.
#myorigin = /etc/mailname
smtpd_banner = $myhostname ESMTP $mail_name (Ubuntu)
biff = no
# appending .domain is the MUA's job.
append_dot_mydomain = no
# Uncomment the next line to generate "delayed mail" warnings
#delay_warning_time = 4h
readme_directory = no
# See http://www.postfix.org/COMPATIBILITY_README.html -- default to 2 on
# fresh installs.
compatibility_level = 2
# TLS parameters
smtpd_tls_cert_file = /etc/ssl/certs/ssl-cert-snakeoil.pem
smtpd_tls_key_file = /etc/ssl/private/ssl-cert-snakeoil.key
smtpd_use_tls=yes
smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache
smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache
# See /usr/share/doc/postfix/TLS_README.gz in the postfix-doc package for
# information on enabling SSL in the smtp client.
smtpd_relay_restrictions = permit_mynetworks permit_sasl_authenticated defer_unauth_destination
myhostname = mainserver.mskillsa.com
alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases
myorigin = /etc/mailname
mydestination = $myhostname, mskillsa.com, mainserver.mskillsa.com, localhost.mskillsa.com, localhost
mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128
mailbox_command = procmail -a "$EXTENSION"
mailbox_size_limit = 0
recipient_delimiter = +
inet_interfaces = all
inet_protocols = all
smtp_sasl_auth_enable = yes
我的域名是:mskillsa.com
我的主机名是:mainserver.mskillsa.com
我的电子邮件地址是 :[电子邮件保护]
一些记录检查器告诉我,我没有 DKIM 记录,我尝试使用第三方 DKIM 记录生成器,并且我使用它,但仍然有同样的 DKIM 记录问题 !!!
我的PHPMailer代码:
<?php
// Include required phpmailer files
require "includes/PHPMailer.php";
require "includes/SMTP.php";
require "includes/Exception.php";
// Define name spaces
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\SMTP;
use PHPMailer\PHPMailer\Exception;
// Create instance of phpmailer
$mail = new PHPMailer();
// Set mailer to use SMTP
$mail->isSMTP();
// Define SMTP host
$mail->Host = "mail.mskillsa.com";
// enable SMTP authentication
$mail->SMTPAuth = "true";
// Set type of encryption (ssl/tls)
$mail->SMTPSecure = "ssl";
// Set port to connect SMTP
$mail->Port = "465";
// Set username
$mail->Username = "[email protected]";
// Set password
$mail->Password = "password";
// Set email Subject
$mail->Subject = "Hello Info Testing";
// Set sender email
$mail->setFrom("[email protected]");
// Email Body
$mail->Body = "Hello testing...";
// Add recipient
$mail->addAddress('[email protected]');
// Finally Send Email
if ($mail->send()) {
echo "Sent";
} else {
echo "Not Sent";
}
// Closing SMTP Connection
$mail->smtpClose();
我收到以下错误:
2022-08-08 15:42:54 CLIENT -> SERVER: EHLO mskillsa.com
2022-08-08 15:42:54 CLIENT -> SERVER: STARTTLS
SMTP Error: Could not connect to SMTP host. Connection failed. stream_socket_enable_crypto(): Peer certificate CN=`localhost.localdomain' did not match expected CN=`mainserver.mskillsa.com'
2022-08-08 15:42:54 CLIENT -> SERVER: QUIT
2022-08-08 15:42:54
SMTP connect() failed. https://github.com/PHPMailer/PHPMailer/wiki/Troubleshooting
Not Sent
我的master.cf文件:
#
# Postfix master process configuration file. For details on the format
# of the file, see the master(5) manual page (command: "man 5 master" or
# on-line: http://www.postfix.org/master.5.html).
#
# Do not forget to execute "postfix reload" after editing this file.
#
# ==========================================================================
# service type private unpriv chroot wakeup maxproc command + args
# (yes) (yes) (no) (never) (100)
# ==========================================================================
smtp inet n - y - - smtpd
#smtp inet n - y - 1 postscreen
#smtpd pass - - y - - smtpd
#dnsblog unix - - y - 0 dnsblog
#tlsproxy unix - - y - 0 tlsproxy
#submission inet n - y - - smtpd
# -o syslog_name=postfix/submission
# -o smtpd_tls_security_level=encrypt
# -o smtpd_sasl_auth_enable=yes
# -o smtpd_tls_auth_only=yes
# -o smtpd_reject_unlisted_recipient=no
# -o smtpd_client_restrictions=$mua_client_restrictions
# -o smtpd_helo_restrictions=$mua_helo_restrictions
# -o smtpd_sender_restrictions=$mua_sender_restrictions
# -o smtpd_recipient_restrictions=
# -o smtpd_relay_restrictions=permit_sasl_authenticated,reject
# -o milter_macro_daemon_name=ORIGINATING
#smtps inet n - y - - smtpd
# -o syslog_name=postfix/smtps
# -o smtpd_tls_wrappermode=yes
# -o smtpd_sasl_auth_enable=yes
# -o smtpd_reject_unlisted_recipient=no
# -o smtpd_client_restrictions=$mua_client_restrictions
# -o smtpd_helo_restrictions=$mua_helo_restrictions
# -o smtpd_sender_restrictions=$mua_sender_restrictions
# -o smtpd_recipient_restrictions=
# -o smtpd_relay_restrictions=permit_sasl_authenticated,reject
# -o milter_macro_daemon_name=ORIGINATING
#628 inet n - y - - qmqpd
pickup unix n - y 60 1 pickup
cleanup unix n - y - 0 cleanup
qmgr unix n - n 300 1 qmgr
#qmgr unix n - n 300 1 oqmgr
tlsmgr unix - - y 1000? 1 tlsmgr
rewrite unix - - y - - trivial-rewrite
bounce unix - - y - 0 bounce
defer unix - - y - 0 bounce
trace unix - - y - 0 bounce
verify unix - - y - 1 verify
flush unix n - y 1000? 0 flush
proxymap unix - - n - - proxymap
proxywrite unix - - n - 1 proxymap
smtp unix - - y - - smtp
relay unix - - y - - smtp
-o syslog_name=postfix/$service_name
# -o smtp_helo_timeout=5 -o smtp_connect_timeout=5
showq unix n - y - - showq
error unix - - y - - error
retry unix - - y - - error
discard unix - - y - - discard
local unix - n n - - local
virtual unix - n n - - virtual
lmtp unix - - y - - lmtp
anvil unix - - y - 1 anvil
scache unix - - y - 1 scache
#
# ====================================================================
# Interfaces to non-Postfix software. Be sure to examine the manual
# pages of the non-Postfix software to find out what options it wants.
#
# Many of the following services use the Postfix pipe(8) delivery
# agent. See the pipe(8) man page for information about ${recipient}
# and other message envelope options.
# ====================================================================
#
# maildrop. See the Postfix MAILDROP_README file for details.
# Also specify in main.cf: maildrop_destination_recipient_limit=1
#
maildrop unix - n n - - pipe
flags=DRhu user=vmail argv=/usr/bin/maildrop -d ${recipient}
#
# ====================================================================
#
# Recent Cyrus versions can use the existing "lmtp" master.cf entry.
#
# Specify in cyrus.conf:
# lmtp cmd="lmtpd -a" listen="localhost:lmtp" proto=tcp4
#
# Specify in main.cf one or more of the following:
# mailbox_transport = lmtp:inet:localhost
# virtual_transport = lmtp:inet:localhost
#
# ====================================================================
#
# Cyrus 2.1.5 (Amos Gouaux)
# Also specify in main.cf: cyrus_destination_recipient_limit=1
#
#cyrus unix - n n - - pipe
# user=cyrus argv=/cyrus/bin/deliver -e -r ${sender} -m ${extension} ${user}
#
# ====================================================================
# Old example of delivery via Cyrus.
#
#old-cyrus unix - n n - - pipe
# flags=R user=cyrus argv=/cyrus/bin/deliver -e -m ${extension} ${user}
#
# ====================================================================
#
# See the Postfix UUCP_README file for configuration details.
#
uucp unix - n n - - pipe
flags=Fqhu user=uucp argv=uux -r -n -z -a$sender - $nexthop!rmail ($recipient)
#
# Other external delivery methods.
#
ifmail unix - n n - - pipe
flags=F user=ftn argv=/usr/lib/ifmail/ifmail -r $nexthop ($recipient)
bsmtp unix - n n - - pipe
flags=Fq. user=bsmtp argv=/usr/lib/bsmtp/bsmtp -t$nexthop -f$sender $recipient
scalemail-backend unix - n n - 2 pipe
flags=R user=scalemail argv=/usr/lib/scalemail/bin/scalemail-store ${nexthop} ${user} ${extension}
mailman unix - n n - - pipe
flags=FR user=list argv=/usr/lib/mailman/bin/postfix-to-mailman.py
${nexthop} ${user}
答案1
使用 PHPmailer 时事情变得过于复杂。
由于你的 SMTP 服务器位于本地主机,因此你可以做的最简单的事情是不使用 $mail->isSMTP()
并且不设置$mail->Host
、$mail->SMTPAuth
、$mail->SMTPSecure
、$mail->Port
和$mail->Username
的任何值。同样$mail->Password
省略。因此你只剩下$mail->smtpClose()
$mail = new PHPMailer();
$mail->Subject = "Hello Info Testing";
$mail->setFrom("[email protected]");
$mail->Body = "Hello testing...";
$mail->addAddress('[email protected]');
if ($mail->send()) {
echo "Sent";
} else {
echo "Not Sent";
}
就像第一个例子一样本教程(“如何使用 PHPmailer 发送您的第一封电子邮件”)。
通过这种方法,PHPmailer 将使用与 PHP 内部函数完全相同的邮件发送方法mail()
,即使用 将邮件直接提交到本地邮件服务器sendmail
。在我看来,这是在运行本地 SMTP 服务器的机器上发送邮件的最合适方法。如果此方法以前对您有效(mail
从命令行和 PHPmail()
函数),那么它在这里也应该有效。
但是,如果您坚持使用 SMTP,那么有几种方法可以实现,但每种方法都需要对您的参数进行一些更正。
首先,您尝试使用安全连接到本地服务器 ( $mail->SMTPSecure = "ssl"
)。如果您连接到本地主机,这绝对不会带来任何安全优势,这是导致问题的主要原因,因为您发布的错误对话框显示 PHPmailer 证书验证失败。因此,首先尝试完全摆脱加密。替换
$mail->Host = "mail.mskillsa.com";
经过
$mail->Host = "localhost";
或者
$mail->Host = "127.0.0.1";
并删除该行$mail->SMTPSecure = "ssl"
。您可能还需要添加以下内容:
$mail->SMTPAutoTLS = false;
如果 PHPmailer 发现服务器支持加密,则阻止它自动使用加密。
由于您的 Postfix 服务器信任 localhost(这绝对正确)- localhost 地址包含在 中mynetworks=
。因此,您只需连接到标准 SMTP 端口 25。您还应该摆脱身份验证,因为您当前的 Postfix 配置确实不是支持身份验证,至少在端口 25 上支持(您没有发布您的master.cf
,其中可能定义了端口 465 上的提交服务的配置,因此我不确定那里是否支持身份验证,但从您发布的对话框(编辑之前的上一个版本)中,我看到服务器没有宣传 AUTH)。因此,删除$mail->SMTPAuth
、$mail->Username
和$mail->Password
行,然后设置
$mail->Port = 25;
因此下一个可行的选择应该是:
$mail = new PHPMailer();
$mail->isSMTP();
$mail->Host = "localhost";
$mail->SMTPAutoTLS = false;
$mail->Port = 25;
$mail->Subject = "Hello Info Testing";
$mail->setFrom("[email protected]");
$mail->Body = "Hello testing...";
$mail->addAddress('[email protected]');
if ($mail->send()) {
echo "Sent";
} else {
echo "Not Sent";
}
$mail->smtpClose();
最后,如果您真的想使用加密认证提交(尽管我想再次强调,连接到本地 SMTP 服务器时它没有意义),您还需要修复一些 Postfix 配置。
正如我所说,您的 Postfix 配置未启用身份验证。您可能希望使用以下行启用它smtp_sasl_auth_enable = yes
,但这会为 Postfix 启用身份验证作为客户端连接到另一台服务器并向其发送邮件,而不是 Postfix 中的 SMTP 服务器。您通常不希望出现这种情况。如果没有附带参数smtp_sasl_password_maps
(定义 Postfix 应该用来向远程服务器进行身份验证的凭据),此参数根本不起作用。因此,请从 中删除此行main.cf
。
Postfix 中开启身份验证的参数服务器是smtpd_sasl_auth_enable = yes
(请注意名称中的“d”),但是你不应该把它放在你的main.cf
因为在配置邮件服务器时启用端口 25 上的身份验证并不是一个好习惯。相反,您应该仅在提交服务的端口 465 上启用身份验证,该端口在 中定义master.cf
。您还没有发布您的master.cf
,所以我无法告诉您如何更正它。
假设您已经修复了您的master.cf
,您的 PHPmailer 参数中仍有一些问题需要修复。PHPmailer 证书验证失败,因为您有一个自签名在您的服务器和 PHPmailer 上进行证书验证默认情况下需要证书颁发机构的“官方”证书并尝试验证它。因此,除了 PHPmailer 代码中已有的内容外,您还需要添加以下内容:
/* Disable some SSL checks. */
$mail->SMTPOptions = array(
'ssl' => array(
'verify_peer' => false,
'verify_peer_name' => false,
'allow_self_signed' => true
)
);
我从教程我已经链接了,请参阅“如何使用自定义 SMTP 服务器”下的第二个示例。这是第三个变体,应该适合您。
更新:现在您发布了master.cf
内容,我发现您根本没有启用提交服务。因此,我想知道最初连接到端口 465(如您的 PHPmailer 代码中指定)对您来说是如何工作的。您是否在端口 465 上运行了其他软件?因为根据您的说明master.cf
,Postfix 仅监听端口 25。
无论如何,为了使经过身份验证的提交工作,您需要取消注释以下行master.cf
并重新启动 Postfix:
#smtps inet n - y - - smtpd
# -o syslog_name=postfix/smtps
# -o smtpd_tls_wrappermode=yes
# -o smtpd_sasl_auth_enable=yes
# -o smtpd_reject_unlisted_recipient=no
# -o smtpd_client_restrictions=$mua_client_restrictions
# -o smtpd_helo_restrictions=$mua_helo_restrictions
# -o smtpd_sender_restrictions=$mua_sender_restrictions
# -o smtpd_recipient_restrictions=
# -o smtpd_relay_restrictions=permit_sasl_authenticated,reject
# -o milter_macro_daemon_name=ORIGINATING
但是,您还需要定义一些验证器来检查用户凭证。这是 Postfix 外部的一些程序,例如 Dovecot。您需要在两个地方配置身份验证。首先,您需要将以下内容添加到您的 Postfixmain.cf
文件中:
smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth
然后,您需要在 Dovecot 中为 Postfix 配置身份验证服务。有一个Dovecot 网站上的教程怎么做。