不通过fsockopen()发送带有gmail smtp的电子邮件

时间:2013-05-15 18:41:57

标签: php email

当我尝试使用PHPMailer_v5.1发送电子邮件时,它可以正常工作。但是当我尝试自己制作时,我知道结果可能是错误或电子邮件未发送。我的问题是未发送的电子邮件。 这是我的代码:

<?php
$fp = fsockopen("ssl://smtp.gmail.com", 465, $errNo, $errStr, 15);
if(!$fp){
    echo "not connected";
}else{
    fputs($fp, "EHLO"."\r\n");
    fputs($fp, "AUTH LOGIN"."\r\n");
    fputs($fp, base64_encode("author@gmail.com")."\r\n");
    fputs($fp, base64_encode("password")."\r\n");
    fputs($fp, "MAIL FROM:<author@gmail.com>"."\r\n");
    fputs($fp, "RCPT TO:<target@gmail.com>"."\r\n");
    fputs($fp, "DATA"."\r\n");
    fputs($fp, "Subject: This is subject"."\r\n");
    fputs($fp, "This is body message"."\r\n");
    fputs($fp, "."."\r\n");
    fputs($fp, "QUIT"."\r\n");
    fclose($fp);
}
?>
抱歉,我的英语不好。

1 个答案:

答案 0 :(得分:1)

我认为这里的问题是你将SMTP视为一条单行道,只是在没有检查响应的情况下完成命令。

在连接之后你应该做的第一件事是阅读服务器横幅,然后在每个命令之后你应该阅读服务器的响应。在服务器横幅上等待非常重要,因为在忙碌的MTA中,您可能需要等待一分钟才能真正启动事务。这是我用于测试的邮件的EHLO函数的注释版本:

private function do_ehlo() {
    // most MTAs expect a domain/host name, and the picky ones want the hostname specified here
    // to match the reverse lookup of the IP address.
    $ehlo = sprintf("EHLO %s\r\n", $this->connection_info['domain']);
    $this->log($ehlo, 'out');
    fwrite($this->sock, $ehlo, strlen($ehlo));

    // SMTP responses can span multiple lines, they will look like
    // ###-First line
    // ###-Second line
    // ### Last line
    //
    // Where ### is the 3-digit status code, and every line but the last has a dash between the
    // code and the text.
    while( $get = fgets($this->sock, 1024) ) {
        $this->log($get, 'in');
        if( ! preg_match('/^([0-9]{3})([ -])(.*)$/', $get, $matches) || $matches[1] != '250' ) {
            Throw new Exception('Abnormal EHLO repsonse received: ' . $get);
        }
        // The advertised capabilities of the server in the EHLO response will include the types
        // of AUTH mechanisms that are supported, which is important, because LOGIN is just
        // gussied-up plaintext, and plaintext is bad.
        $this->capabilities[] = trim($matches[3]);
        // stop trying to read from the socket if a space is detected, indicating either a 
        // single-line response, or the last line of a multi-line response.
        if( $matches[2] == ' ' ) { break; }
    }
}

IIRC GMail对于遵守规则特别挑剔,他们可能会因为没有在EHLO中指定正确的名称而立即将你踢到路边,甚至只是因为错过了您MAIL FROMRCPT TO命令中的冒号。如果你想真正挑剔,你也没有在消息数据中设置Date标题,我认为这也是严格服务器的一个重要因素,请使用:sprintf('Date: %s', date(DATE_RFC2822));

最后,如果您想编写自己的邮件,请先阅读RF2822RFC821RFC2821。只要确保你手边有浓咖啡,​​否则你很快就会睡着了。

TL; DR: PHPmailer更容易。