Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Example code not working #17

Open
zookatron opened this issue Oct 24, 2018 · 18 comments
Open

Example code not working #17

zookatron opened this issue Oct 24, 2018 · 18 comments
Assignees
Labels

Comments

@zookatron
Copy link

How to reproduce:

php version

PHP 7.2.9-1+ubuntu16.04.1+deb.sury.org+1 (cli) (built: Aug 19 2018 07:16:12) ( NTS )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.2.0, Copyright (c) 1998-2018 Zend Technologies
    with Zend OPcache v7.2.9-1+ubuntu16.04.1+deb.sury.org+1, Copyright (c) 1999-2018, by Zend Technologies

packages

composer require phpmailer/phpmailer
composer require thefox/smtpd
composer require monolog/monolog

server.php

<?php

// Import PHPMailer classes into the global namespace
// These must be at the top of your script, not inside a function
use TheFox\Smtp\Server;
use TheFox\Smtp\Event;
use Zend\Mail\Message;
use Monolog\Logger;
use Monolog\Handler\StreamHandler;

//Load Composer's autoloader
require 'vendor/autoload.php';

// Generate certificate
$privkey = openssl_pkey_new();
$cert = openssl_csr_new([
    'countryName' => 'UK',
    'stateOrProvinceName' => 'Isle Of Wight',
    'localityName' => 'Cowes',
    'organizationName' => 'Open Sauce Systems',
    'organizationalUnitName' => 'Dev',
    'commonName' => '127.0.0.1',
    'emailAddress' => '[email protected]',
], $privkey);
$cert = openssl_csr_sign($cert, null, $privkey, 365);

// Generate PEM file
$pem = [];
openssl_x509_export($cert, $pem[0]);
openssl_pkey_export($privkey, $pem[1]);
$pem = implode($pem);

// Save PEM file
$pemfile = 'server.pem';
file_put_contents($pemfile, $pem);
$listenOptions = [
    'ssl' => [
        'verify_peer' => false,
        'local_cert' => $pemfile,
        'allow_self_signed' => true,
    ],
];

// Create a Logger with Monolog.
$logger = new Logger('smtp_example');
$logger->pushHandler(new StreamHandler('php://stdout', Logger::DEBUG));

$server = new Server([
    'ip' => '127.0.0.1',
    'port' => 587,
    'logger' => $logger,
]);
if(!$server->listen($listenOptions)) {
    print 'Server could not listen.' . "\n";
    exit(1);
}

$server->addEvent(new Event(Event::TRIGGER_NEW_MAIL, null, function(Event $event, string $from, array $rcpts, Message $mail) {
    // Do Stuff
}));

$server->addEvent(new Event(Event::TRIGGER_AUTH_ATTEMPT, null, function($event, $type, $credentials): bool {
    return true;
}));

$server->loop();

email.php

<?php

// Import PHPMailer classes into the global namespace
// These must be at the top of your script, not inside a function
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;

//Load Composer's autoloader
require 'vendor/autoload.php';

$mail = new PHPMailer(true);                              // Passing `true` enables exceptions
try {
    //Server settings
    $mail->SMTPDebug = 2;                                 // Enable verbose debug output
    $mail->isSMTP();                                      // Set mailer to use SMTP
    $mail->Host = 'localhost';  // Specify main and backup SMTP servers
    $mail->SMTPAuth = false;                               // Enable SMTP authentication
    // $mail->Username = '[email protected]';                 // SMTP username
    // $mail->Password = 'secret';                           // SMTP password
    $mail->SMTPSecure = 'tls';                            // Enable TLS encryption, `ssl` also accepted
    $mail->Port = 587;                                    // TCP port to connect to
    $mail->SMTPOptions = array(
        'ssl' => array(
            'verify_peer' => false,
            'verify_peer_name' => false,
            'allow_self_signed' => true
        )
    );

    //Recipients
    $mail->setFrom('[email protected]', 'Mailer');
    $mail->addAddress('[email protected]', 'Joe User');     // Add a recipient
    $mail->addAddress('[email protected]');               // Name is optional
    $mail->addReplyTo('[email protected]', 'Information');
    $mail->addCC('[email protected]');
    $mail->addBCC('[email protected]');

    //Attachments
    // $mail->addAttachment('/var/tmp/file.tar.gz');         // Add attachments
    // $mail->addAttachment('/tmp/image.jpg', 'new.jpg');    // Optional name

    //Content
    $mail->isHTML(true);                                  // Set email format to HTML
    $mail->Subject = 'Here is the subject';
    $mail->Body    = 'This is the HTML message body <b>in bold!</b>';
    $mail->AltBody = 'This is the body in plain text for non-HTML mail clients';

    $mail->send();
    echo 'Message has been sent';
} catch (Exception $e) {
    echo 'Message could not be sent. Mailer Error: ', $mail->ErrorInfo;
}

run server & send email:

sudo php server.php
php email.php

server.php output:

[2018-10-23 19:22:54] smtp_example.INFO: start [] []
[2018-10-23 19:22:54] smtp_example.INFO: ip = "127.0.0.1" [] []
[2018-10-23 19:22:54] smtp_example.INFO: port = "587" [] []
[2018-10-23 19:22:54] smtp_example.INFO: hostname = "localhost.localdomain" [] []
[2018-10-23 19:22:54] smtp_example.NOTICE: listen ok [] []
[2018-10-23 19:23:06] smtp_example.DEBUG: client 1 data send: "220 localhost.localdomain SMTP Service Ready" [] []
[2018-10-23 19:23:06] smtp_example.DEBUG: client 1 data send: "250-localhost.localdomain\n250-AUTH PLAIN LOGIN\n250-STARTTLS\n250 HELP" [] []
[2018-10-23 19:23:06] smtp_example.DEBUG: client 1 data send: "220 Ready to start TLS" [] []
[2018-10-23 19:23:06] smtp_example.DEBUG: client 1: collect data [] []
[2018-10-23 19:23:06] smtp_example.DEBUG: client 1: collect data [] []
[2018-10-23 19:23:06] smtp_example.DEBUG: client 1: collect data [] []
[2018-10-23 19:23:06] smtp_example.DEBUG: client 1: collect data [] []
[2018-10-23 19:23:06] smtp_example.DEBUG: client 1: collect data [] []
[2018-10-23 19:23:06] smtp_example.DEBUG: client 1: collect data [] []
[2018-10-23 19:23:06] smtp_example.DEBUG: client 1: collect data [] []
[2018-10-23 19:23:06] smtp_example.DEBUG: client 1: collect data [] []
[2018-10-23 19:23:06] smtp_example.DEBUG: client 1: collect data [] []
[2018-10-23 19:23:06] smtp_example.DEBUG: client 1: collect data [] []
[2018-10-23 19:23:06] smtp_example.DEBUG: client 1: collect data [] []
[2018-10-23 19:23:06] smtp_example.DEBUG: client 1: collect data [] []
... (repeats forever) ...

email.php output:

2018-10-24 00:23:06	SERVER -> CLIENT: 220 localhost.localdomain SMTP Service Ready
2018-10-24 00:23:06	CLIENT -> SERVER: EHLO tim-workstation
2018-10-24 00:23:06	SERVER -> CLIENT: 250-localhost.localdomain
                   	                  250-AUTH PLAIN LOGIN
                   	                  250-STARTTLS
                   	                  250 HELP
2018-10-24 00:23:06	CLIENT -> SERVER: STARTTLS
2018-10-24 00:23:06	SERVER -> CLIENT: 220 Ready to start TLS
2018-10-24 00:23:06	CLIENT -> SERVER: EHLO tim-workstation
2018-10-24 00:23:08	SERVER -> CLIENT:
2018-10-24 00:23:08	SMTP ERROR: EHLO command failed:
2018-10-24 00:23:08	SMTP NOTICE: EOF caught while checking if connected

The server does not appear to be receiving the "EHLO tim-workstation" command that is being sent by PHPMailer and so it just continually spins with no received data. Are you able to reproduce this? Do you know why this might be happening? Your library appears to be using a custom networking library and I'm not familiar enough with the low-level networking functions to debug effectively. If you could point me in the right direction I could probably write up a fix.

@jonevance
Copy link

Having the same problem, and I've narrowed it down a bit. If I turn off TLS on the sending side, the server works as expected. Not sure where to go from here to debug further, though...

@TheFox TheFox self-assigned this Feb 19, 2019
@TheFox TheFox added the bug label Feb 19, 2019
@TheFox
Copy link
Owner

TheFox commented Feb 19, 2019

Hi, I'm sorry for this. I have to debug the code line-by-line. Maybe rewriting the example from scratch with a better approach.

Creating the certificate in the example code is not a good idea. This script should not focus on creating an SSL certificate, rather on handling the SMTP server.

@jonevance
Copy link

Nothing to be sorry for! Bugs are part of the process (assuming it even is a bug). If it helps, the stream_socket_enable_crypto call at StreamSocket.php:170 does not return an error or warning, but once it has been called the stream_socket_recvfrom call at line 135 starts returning FALSE. Of course this should be returning a string, but even worse is that the dataRecv method of the Client class does not know what to do with a FALSE response, so it keeps looping and looping.

@jonevance
Copy link

More info, in case it may help: I removed the self-signed certificate and purchased a real one. The problem still exists, so I don't believe the self-signing is the issue (but of course I may have screwed up the certificate somehow). If there's anything else I can do to help track this down, please let me know.

@TheFox
Copy link
Owner

TheFox commented Feb 21, 2019

Technically there is no different between a self-signed certificate and a purchased real one.

@jonevance
Copy link

Indeed; I interpreted the second line of your original response to indicate you thought the certificate creation in the example code may be a problem, so I tried to verify that it is not. If I misinterpreted your comment, I apologize.

@TheFox
Copy link
Owner

TheFox commented Feb 21, 2019

Ah, I see. This was a miscommunication.

I meant that the example script and this project should not focus on creating certificates at all. Only take the path to an existing certificate. I'll remove the example in the next version and create an extra examples directory with different example files.

@jonevance
Copy link

Gotcha. Note, though, that this issue definitely seems to be irrespective of the example code. Any attempt I've made to use the SMTP server with TLS is failing in the manner described above.

@jonevance
Copy link

Testing with OpenSSL command line doesn't give me any hints, but perhaps you will understand the attached log better.

openssl.log

@jonevance
Copy link

Progress, maybe. At least some information, if not a fix. Replace stream_socket_recvfrom and stream_socket_sendto with fread and fwrite, respectively, and it works.

@TheFox
Copy link
Owner

TheFox commented Feb 22, 2019

@jonevance @zookatron Are you on master, or a specific version?

@jonevance
Copy link

0.3

@TheFox
Copy link
Owner

TheFox commented Feb 22, 2019

That's really old. We are already at 0.7.

@jonevance
Copy link

jonevance commented Feb 22, 2019

Sorry about that. Your README.md instructs to install via:
composer.phar require "thefox/smtpd=~0.3"

I've upgraded to 0.7 and the problem persists, and is still "fixable" by swapping the recv and send with fread and fwrite.

@zookatron
Copy link
Author

Hi all,

@TheFox I've tried several different versions of the library and they all appear to have the same bug for me, including version 0.7.

@jonevance Your "replace stream_socket_recvfrom and stream_socket_sendto with fread and fwrite" fix is working perfectly for me, thanks, that is a huge help! @TheFox Any chance we could get this fix merged into master? Would it help to create a PR?

@jonevance
Copy link

Prefer to have the stream functions work, of course, but I've tried everything; the problem really seems to be in the underlying system.

@joseleperez
Copy link

@TheFox Same happens here with the current master.

[2019-04-10 15:22:33] smtp_example.DEBUG: client 1: collect data [] []
[2019-04-10 15:22:33] smtp_example.DEBUG: client 1: collect data [] []
[2019-04-10 15:22:33] smtp_example.DEBUG: client 1: collect data [] []
[2019-04-10 15:22:33] smtp_example.DEBUG: client 1: collect data [] []
$ php -v
PHP 7.2.14 (cli) (built: Jan 31 2019 00:51:06) ( NTS )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.2.0, Copyright (c) 1998-2018 Zend Technologies

@groovenectar
Copy link

I ran into the same issue and can confirm that TheFox/network#1 from @aaronschmied fixes it

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

5 participants