Search code examples
phpdockeremailpeardovecot

PEAR Mail in php:apache Docker container


I have two servers. A Postfix mail server with Dovecot that, otherwise, works fine. I can send mail through it using Gmail client (So, yes there is a valid certificate installed there). The other server is my app server, which has the php:7.4-apache image running. I've installed the PEAR Mail library into that container/image, and I'm trying to send mail from the app through the mail server, but the PEAR Mail client keeps hanging up after it sends STARTTLS. Questions:

What am I doing wrong?

Maillog on the mail server says only this:

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]

Debug output from the client says this:

[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

This is the code being used on the client:

<html><body>
<?php

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

include('/usr/local/lib/php/Mail.php');
$recipients = '[email protected]'; //CHANGE
$headers['From']= '[email protected]'; //CHANGE
$headers['To']= '[email protected]'; //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>

I've also tried the following code, which is essentially the same thing:

<?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 = "[email protected]";
$email_from = "[email protected]";
$email_subject = "Testing Pear" ;
$email_body = "Sent using Pear install Mail" ;
$email_address = "[email protected]";

$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>");
}
?>

And received the following error:

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

I've tried both ports 25 and 587 with the same result, though only 587 should work. I've tried the auth parameter as true, false, and plain. Commenting out the auth parameter is rejected by the mail server which requires STARTTLS.

Changing this line in Mail.php

function auth($uid, $pwd, $method = '', $tls = true, $authz = '')

to false, of course, does not work because the server requires a STARTTLS. Disabling TLS on both ends, might make it functional, but that doesn't solve the problem with TLS.

Please, don't tell me to just use PHPmailer.

Thank you.


Solution

  • Since the very problem here is TLS not working, any suggestion that you should edit Mail.php

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

    to turn off TLS is nonsensical.

    The issue here is that the certificate on the mail server is for a particular name, not a LAN IP address. I've tried to add a second certificate for the LAN IP address with a SAN, but that did not work. If you are using a reverse proxy, like I am (HAproxy), then it also fails to use the FQDN, instead of the LAN IP address, if your container is resolving DNS with an external server (8.8.8.8), though the problem there might be NAT/PAT, instead.

    The solution I found is to setup a forwarding DNS server on the LAN, with a forward lookup zone for the same domain & hosts as the certificate. One way or another, the value for $host needs to match the name on the mail server's certificate, and you need some kind of DNS to resolve to an address that will get you to that server.