php:apache Docker 容器中的 PEAR 邮件

PEAR Mail in php:apache Docker container

我有两台服务器。带有 Dovecot 的 Postfix 邮件服务器,否则可以正常工作。我可以使用 Gmail 客户端通过它发送邮件(所以,是的,那里安装了一个有效的证书)。另一台服务器是我的应用程序服务器,它有 php:7.4-apache 图像 运行。我已经在 container/image 中安装了 PEAR Mail 库,并且我正在尝试通过邮件服务器从应用程序发送邮件,但是 PEAR Mail 客户端在发送 STARTTLS 后一直挂起。问题:

我做错了什么?

邮件服务器上的邮件日志仅显示:

Jun  1 17:36:46 Mimosa postfix/submission/smtpd[19141]: connect from unknown[10.0.0.14]
Jun  1 17:36:46 Mimosa postfix/submission/smtpd[19141]: lost connection after STARTTLS from unknown[10.0.0.14]
Jun  1 17:36:46 Mimosa postfix/submission/smtpd[19141]: disconnect from unknown[10.0.0.14]

客户端的调试输出是这样的:

[ehlo] Recv: 250-PIPELINING DEBUG: Recv: 250-SIZE 10240000 DEBUG: Recv: 250-VRFY DEBUG: 
Recv: 250-ETRN DEBUG: Recv: 250-STARTTLS DEBUG: Recv: 250-ENHANCEDSTATUSCODES DEBUG: 
Recv: 250-8BITMIME DEBUG: Recv: 250 DSN DEBUG: Send: STARTTLS DEBUG: 
Recv: 220 2.0.0 Ready to start TLS DEBUG: Send: RSET DEBUG: Send: QUIT

这是客户端使用的代码:

<html><body>
<?php

var_dump(extension_loaded('openssl'));
//echo phpinfo();

include('/usr/local/lib/php/Mail.php');
$recipients = 'myemail@gmail.com'; //CHANGE
$headers['From']= 'noreply@mydomain.com'; //CHANGE
$headers['To']= 'myemail@gmail.com'; //CHANGE
$headers['Subject'] = 'Test message';
$body = 'Test message'; // Define SMTP Parameters
$params['host'] = '10.0.0.6';
$params['port'] = '587';
$params['auth'] = 'PLAIN';
$params['username'] = 'noreply'; //CHANGE
$params['password'] = 'password'; //CHANGE
$params['debug'] = 'true'; 

$mail_object =& Mail::factory('smtp', $params);

foreach ($params as $p){
 echo "$p<br />";
}

// Send the message
$mail_object->send($recipients, $headers, $body);

?>
</body></html>

我也试过下面的代码,本质上是一样的:

<?php

error_reporting(E_ALL ^ E_NOTICE ^ E_DEPRECATED ^ E_STRICT);

require_once "/usr/local/lib/php/Mail.php";

$host = "10.0.0.6";
$username = "noreply";
$password = "password";
$port = "587";
$to = "myemail@gmail.com";
$email_from = "noreply@mydomain.com";
$email_subject = "Testing Pear" ;
$email_body = "Sent using Pear install Mail" ;
$email_address = "noreply@domain.com";

$headers = array ('From' => $email_from, 'To' => $to, 'Subject' => $email_subject, 'Reply-To' => $email_address);
$smtp = Mail::factory('smtp', array ('host' => $host, 'port' => $port, 'auth' => true, 'username' => $username, 'password' => $password));
$mail = $smtp->send($to, $headers, $email_body);


if (PEAR::isError($mail)) {
echo("<p>" . $mail->getMessage() . "</p>");
var_dump($mail);
} else {
echo("<p>Message successfully sent!</p>");
}
?>

并收到以下错误:

" authentication failure [SMTP: STARTTLS failed (code: 220, response: 2.0.0 Ready to start TLS)]"

我已经尝试了端口 25 和 587,结果相同,但只有 587 应该可以。我已经尝试将 auth 参数设置为 true、false 和 plain。注释掉 auth 参数被需要 STARTTLS 的邮件服务器拒绝。

在 Mail.php

中更改此行
function auth($uid, $pwd, $method = '', $tls = true, $authz = '')

to false,当然是行不通的,因为服务器需要一个STARTTLS。在两端禁用 TLS,可能会使它起作用,但这并不能解决 TLS 的问题。

请不要告诉我只使用 PHPmailer。

谢谢。

因为这里的问题是 TLS 不工作,任何建议你应该编辑 Mail.php

WRONG    function auth($uid, $pwd, $method = '', $tls = ??, $authz = '') (Don't do this)

关闭 TLS 是荒谬的。

这里的问题是邮件服务器上的证书是针对特定名称的,而不是 LAN IP 地址。我已尝试使用 SAN 为 LAN IP 地址添加第二个证书,但没有成功。如果您使用的是反向代理,就像我是 (HAproxy),那么它也无法使用 FQDN,而不是 LAN IP 地址,如果您的容器正在使用外部服务器 (8.8.8.8) 解析 DNS,尽管问题可能会有 NAT/PAT,而不是。

我找到的解决方案是在 LAN 上设置转发 DNS 服务器,并为与证书相同的域和主机设置正向查找区域。不管怎样,$host 的值需要与邮件服务器证书上的名称相匹配,并且您需要某种 DNS 来解析一个地址,以便您访问该服务器。