无法使用 PHP shell_exec() 执行 telnet 命令

Posted

技术标签:

【中文标题】无法使用 PHP shell_exec() 执行 telnet 命令【英文标题】:Cannot execute telnet commands using PHP shell_exec() 【发布时间】:2016-03-01 08:36:43 【问题描述】:

我正在尝试使用 telnet 和 php 进行邮件验证。整个过程在终端中都很好,但是当我使用 php shell_exec() 时,它只能运行到 Telnet 连接命令。连接 telnet 后,其余特定于 telnet 的命令将不再起作用。

还有其他我们需要使用 php 执行 telnet 的方式吗?

更新:我正在尝试复制 this 教程。

这是我的代码

public function mailtest(Request $request)
        //Taking input email
        $email = $request->input("email");
        $divide = explode("@", $email);
        //Find out the Domain
        $server = $divide[1];
        $response = shell_exec("nslookup -q=mx $server");
        //Response of the nslookup
        print_r($response);
        $mailServerList = explode(PHP_EOL, $response);
        $line = $mailServerList[4];

        $serverArr = preg_split('/\s+/', $line);
        $n = sizeof($serverArr);
        $mailServer = $serverArr[$n-1];
        //Printing out the mail server out of the nslookup response
        print_r($mailServer);
        //Executing Telnet command
        $telnet = shell_exec("telnet $mailServer 25");
        print_r("telnet response ".$telnet);

        //Telnet Helo
        $helo = shell_exec("Helo testing.com");
        print_r("Helo response ".$helo);
        //Telnet mail from 
        $from = shell_exec('mail from: testing@gmail.com');
        print_r("MAil from response ".$from);
        //Telnet RCPT to
        $finalResponse = shell_exec("rcpt to: $email");
        print_r("Mail to response ".$finalResponse);
    

这是回复

Server:     10.0.80.11
Address:    10.0.80.11#53

Non-authoritative answer:
gmail.com   mail exchanger = 5 gmail-smtp-in.l.google.com.
gmail.com   mail exchanger = 10 alt1.gmail-smtp-in.l.google.com.
gmail.com   mail exchanger = 40 alt4.gmail-smtp-in.l.google.com.
gmail.com   mail exchanger = 30 alt3.gmail-smtp-in.l.google.com.
gmail.com   mail exchanger = 20 alt2.gmail-smtp-in.l.google.com.

Authoritative answers can be found from:
gmail-smtp-in.l.google.com  internet address = 173.194.64.27
gmail-smtp-in.l.google.com  has AAAA address 2607:f8b0:4003:c02::1a
alt1.gmail-smtp-in.l.google.com internet address = 173.194.219.27
alt1.gmail-smtp-in.l.google.com has AAAA address 2607:f8b0:4002:c03::1b
alt4.gmail-smtp-in.l.google.com internet address = 64.233.190.26
alt4.gmail-smtp-in.l.google.com has AAAA address 2800:3f0:4003:c01::1b
alt3.gmail-smtp-in.l.google.com internet address = 74.125.141.26
alt3.gmail-smtp-in.l.google.com has AAAA address 2607:f8b0:400c:c06::1a
alt2.gmail-smtp-in.l.google.com internet address = 173.194.205.27
alt2.gmail-smtp-in.l.google.com has AAAA address 2607:f8b0:400d:c02::1b

gmail-smtp-in.l.google.com.telnet response Trying 2607:f8b0:4003:c02::1a...
Connected to gmail-smtp-in.l.google.com.
Escape character is '^]'.
Helo response 
MAil from response No message, no subject; hope that's ok
Mail to response 

【问题讨论】:

作为替代尝试 php 的 imap 扩展和 imap_* 函数 @AlexAndrei 抱歉,它到底是做什么的? 该扩展提供了允许您通过IMAP 协议进行操作的功能,请参阅此处php.net/manual/en/book.imap.php @AlexAndrei 抱歉,我对此不太了解,但是,您能告诉我它是否有助于电子邮件验证吗?还是执行 Telnet 命令? 【参考方案1】:

shell_exec 不适合这种情况(参见 Ulrich 的解释)。

fsockopen 应该可以解决问题。

$fp = @fsockopen('yourMailServer.com', 9001);      

if ($fp)  
    fwrite($fp, "username\n");
    fwrite($fp, "password\n");

    while ($line = fread($fp, 2048))     
       // do things with $line    
        
 else     
    //return error    

【讨论】:

基本上我想做一个telnet myMailServer.com 25来启动连接,然后以Helo hi开始,依此类推,如Tutorial所示。我尝试使用fsockopen,但它似乎不起作用。你能检查一次教程,看看我应该如何使用fsockopen 或你认为可以达到目的的任何方式吗? 对于教程中的每个绿线,您应该调用一个 fwrite 命令。对于每条蓝线,您应该阅读(并采取行动)while 循环中的 $line 参数。 所以一旦@fsockopen('yourMailServer.com', 25);成功,我就从telnet yourMailServer.com 25开始?还是fsockopen 命令有同样的作用? fsockopen 替换了 telnet。它打开一个套接字。【参考方案2】:

在参考了@Lavi 的回答后,这就是我设法解决这种情况的方法。 fputs 成功了,而不是 fwrite

$connect = @fsockopen($mailServer, 25);
if($connect)
    fputs ($connect , "HELO $mailServer\r\n");
    $out = fgets ($connect, 1024);
    $details .= $out."\n";

    fputs ($connect , "MAIL FROM: <$fromemail>\r\n");
    //$from = fgets ($connect, 1024);
    fputs ($connect , "RCPT TO: <$toemail>\r\n");
    //$to = fgets ($connect, 1024);
    fputs ($connect , "QUIT");
    fclose($connect);

【讨论】:

这工作得很好,但我不得不改变 fget 的位置,因为需要其中 4 个才能获得所有正在输出的信息 对无效电子邮件也有效 ::(【参考方案3】:

shell_exec() 启动一个新进程。它首先启动一个 shell,然后将给定的字符串作为命令执行。您不能使用多个 shell_exec() 命令与同一个 shell 进行交互,例如远程控制终端。

在您的情况下,我会尝试在现有代码的基础上进行构建。例如,有一堆现有的PHP SMTP libraries。我很确定其中至少有一个能够做你想做的事,或者至少向你展示一种可以实现缺失功能的方法。

如果您真的坚持推出自己的东西,请查看现有答案,例如interacting with command line program 或 PHP 的 expect module。除非绝对需要,否则我会避免这样做,因为它效率低下。此外,出于安全原因,网络服务器通常被配置为不允许启动新进程,因此如果您的代码在从命令行运行但不在网络服务器内部运行时有效,请记住这一区别。

【讨论】:

以上是关于无法使用 PHP shell_exec() 执行 telnet 命令的主要内容,如果未能解决你的问题,请参考以下文章

LINUX+NGINX下的PHP shell_exec()函数执行linux命令 2019-08-08

PHP协程:并发 shell_exec

php执行外部命令函数:exec()passthru()system()shell_exec()对比

PHP执行系统外部命令函数:exec()passthru()system()shell_exec()

PHP 中的 shell_exec()

phpPHP执行系统外部命令函数:exec()passthru()system()shell_exec()