检查SMTP身份验证,而不发送电子邮件,也不使用PHP中的pear

时间:2014-07-18 11:48:26

标签: php email smtp phpmailer swiftmailer

如何在不发送电子邮件和PHP中不使用pear的情况下检查SMTP身份验证。他们可以用主机,端口,用户名和密码检查身份验证吗?

我检查了swiftmailer,它说认证是在发送电子邮件。 http://swiftmailer.org/docs/sending.html#smtp-with-a-username-and-password

同样在phpmailer上。 https://github.com/PHPMailer/PHPMailer/blob/master/examples/smtp.phps

2 个答案:

答案 0 :(得分:2)

不可否认,这不是最干净的解决方案,但它会起作用。下面复制的是expect脚本,它将连接到SMTP服务器,尝试进行身份验证,然后退出会话并断开连接。如果expect脚本的最后一行输出为235 2.7.0 Authentication successful(或响应代码以2xx开头的其他类似响应),则使用提供的凭据进行身份验证成功,否则身份验证失败。您可以使用expect从PHP脚本调用此shell_exec()脚本,并解析输出以测试是否可以使用给定一组凭据的SMTP服务器进行身份验证。

                #!/usr/bin/expect
                set mailserver "smtp.smtpserver.com";         #fqdn of SMTP server
                set credentials "AG1xxxxxxxxxxxxxxxxxxxDNy";  #this string should be "\0username\0password" base64-encoded.

                spawn telnet $mailserver 25
                expect "failed" {
                                send_user "$mailserver: connect failed\n"
                                exit
                        } "2?? *" {
                        } "4?? *"   {
                                exit
                        } "refused" {
                                send_user "$mailserver: connect refused\n"
                                exit
                        } "closed" {
                                send_user "$mailserver: connect closed\n"
                                exit
                        } timeout {
                                send_user "$mailserver: connect to port 25 timeout\n"
                                exit
                        }
                send "HELO foo.com\r"
                expect "2?? *" {
                } "5?? *" {
                        exit
                } "4?? *" {
                        exit
                }

                send "AUTH PLAIN $credentials\r";
                expect "2?? *" {
                } "5?? *" {
                        exit
                } "4?? *" {
                        exit
                }

                send "QUIT\r"
                exit

答案 1 :(得分:0)

使用PHPmailer可以测试连接而无需发送电子邮件。

我添加了该类的函数otuside(但是可以在控制器中使用它而不会出现问题)

    /*
|--------------------------------------------------------------------------
| USE in file
|--------------------------------------------------------------------------
|
| Need add "use" this because:
|  - PHPMailer\PHPMailer\Exception -> catch exceptions of PHPmailer
|  - PHPMailer\PHPMailer\SMTP -> Do the conexión of smtp server
|
 */
use PHPMailer\PHPMailer\Exception;
use PHPMailer\PHPMailer\SMTP;


/**
 * Test connection SMTP
 * @param String $route Host route
 * @param Integer $port Port to connect
 * @param String $userName Email or user name
 * @param String $userPass Password from user
 * @param String $from Mail from 
 * @param String $to Mail to
 * @return Array ['status'=>boolean,'logs'=>array]
 */
function testSMTP($route,$port,$userName = null,$userPass = null,$from=null,$to=null){
    //SMTP needs accurate times, and the PHP time zone MUST be set
    //This should be done in your php.ini, but this is how to do it if you don't have access to that
    date_default_timezone_set('Etc/UTC');
    $logs = [];
    $status_ok = false;

    //Create a new SMTP instance
    $logs = NewLog($logs,"Starting SMTP test");
    $smtp = new SMTP();

    //Enable to show all logs while load page
    //$smtp->do_debug = SMTP::DEBUG_CONNECTION;

    try {
        //Connect to an SMTP server
        $logs = NewLog($logs,"Testing SMTP connection");
        if (!$smtp->connect($route, $port)) {
            throw new Exception('Connect failed');
        }
        //Say hello
        if (!$smtp->hello(gethostname())) {
            throw new Exception('EHLO failed: ' . $smtp->getError()['error']);
        }
        $logs = NewLog($logs,"SMTP connected");
        //Get the list of ESMTP services the server offers
        $e = $smtp->getServerExtList();
        //If server can do TLS encryption, use it
        if (is_array($e) && array_key_exists('STARTTLS', $e)) {
            $tlsok = $smtp->startTLS();
            if (!$tlsok) {
                throw new Exception('Failed to start encryption: ' . $smtp->getError()['error']);
            }
            //Repeat EHLO after STARTTLS
            if (!$smtp->hello(gethostname())) {
                throw new Exception('EHLO (2) failed: ' . $smtp->getError()['error']);
            }
            //Get new capabilities list, which will usually now include AUTH if it didn't before
            $e = $smtp->getServerExtList();
        }
        //If server supports authentication, do it (even if no encryption)
        if(!empty($userName) && !empty($userPass)){
            if (is_array($e) && array_key_exists('AUTH', $e)) {
                if ($smtp->authenticate($userName, $userPass)) {
                    $logs = NewLog($logs,"SMTP user loged");
                } else {
                    throw new Exception('Authentication failed: ' . $smtp->getError()['error']);
                }
            }
        }
        //checkeamos el RCPT TO y MAIL FROM con los metodos de 
        if (!empty($to) && !empty($from)) {
            $logs = NewLog($logs,"Testing SMTP send email");
            if(!$smtp->mail($from)){
                throw new Exception('MAIL FROM: ' . $smtp->getError()['error']);
            }
            if(!$smtp->recipient($to)){
                throw new Exception('RCPT TO: ' . $smtp->getError()['error']);
            }
            $logs = NewLog($logs,"Test SMTP send it's ok");
        }
        $logs = NewLog($logs,"End SMTP test - OK");
        $status_ok = true;
    } catch (Exception $e) {
        $logs = NewLog($logs,'SMTP error: ' . $e->getMessage(), "\n");
    }
    //Whatever happened, close the connection.
    $smtp->quit();

    //return result
    return [
        'logs' => $logs,
        'status' => $status_ok
    ];

}

function NewLog ($listLogs,$log){
    $listLogs[] = "[".date('Y.m.d H:i:s')."] ".$log;
    return $listLogs;
}

您可以在控制器旁边使用此功能,但最好在类中使用它。

相关问题