pear/net_smtp

SMTP协议的实现

1.12.1 2024-04-15 19:42 UTC

This package is auto-updated.

Last update: 2024-09-15 20:32:50 UTC


README

用户文档

目录

1   依赖关系

1.1   PEAR_Error

Net_SMTP包使用PEAR_Error类来处理所有错误处理

1.2   Net_Socket

使用Net_Socket包作为所有网络通信的基础。可以通过$socket_options构造参数指定连接选项。

$socket_options = array('ssl' => array('verify_peer_name' => false));
$smtp = new Net_SMTP($host, null, null, false, 0, $socket_options);

注意:PHP 5.6引入了OpenSSL更改。默认启用对等证书验证。虽然不建议,但可以使用$socket_options禁用对等验证(如上所示)。

1.3   Auth_SASL

Auth_SASL包是可选依赖项。如果可用,Net_SMTP包将能够支持DIGEST-MD5_CRAM-MD5_SCRAM-SHA_ SMTP认证方法。否则,只能提供LOGIN_和PLAIN方法。

2   错误处理

Net_SMTP类中的所有公共方法在发生错误时都会返回一个PEAR_Error对象。检查PEAR_Error对象的标准方法是使用PEAR::isError()

if (PEAR::isError($error = $smtp->connect())) {
    die($error->getMessage());
}

3   SMTP认证

Net_SMTP包支持SMTP认证标准(由RFC-2554定义)。Net_SMTP包按照优先级支持以下认证方法

3.1   CRAM-MD5(已弃用)

已弃用 此认证方法不再安全,应避免使用。

在安全性方面,CRAM-MD5认证方法已被DIGEST-MD5_方法取代。它在此提供是为了与可能不支持较新DIGEST-MD5算法的旧SMTP服务器保持兼容。

注意:只有当AUTH_SASL包可用时,才支持CRAM-MD5认证方法。

3.2   DIGEST-MD5(已弃用)

已弃用 此认证方法不再安全,应避免使用。

DIGEST-MD5认证方法使用RSA Data Security Inc.的MD5消息摘要算法。它被认为是一种比PLAIN或LOGIN更安全的SMTP认证方法,但在没有TLS/SSL的情况下仍然容易受到中间人攻击。

注意:仅当AUTH_SASL软件包可用时,才支持DIGEST-MD5认证方法。

3.3   GSSAPI

GSSAPI认证方法使用Kerberos 5协议(RFC-4120)。不使用用户名/密码。需要服务主体gssapi_principal参数和可选的凭据缓存gssapi_cname参数。需要DNS和密钥分发中心(KDC)设置。被认为是SMTP认证最安全的方法。

注意:仅当krb5 PHP扩展可用时,才支持GSSAPI认证方法。

3.4   LOGIN(已弃用)

已弃用 此认证方法不再安全,应避免使用。

LOGIN认证方法使用Base64编码方案对用户的密码进行加密(Base64)。因为解密Base64编码的字符串是微不足道的。

3.5   PLAIN

此认证方法不再安全,应仅用于本地或通过TLS加密连接。

PLAIN认证方法以明文形式发送用户的密码。

3.6   SCRAM

在密码学中,Salted Challenge Response Authentication Mechanism(SCRAM)是一系列现代基于密码的挑战-响应认证机制,为服务器提供认证。

可用的机制包括SCRAM-SHA-1、SCRAM-SHA-224、SCRAM-SHA-256、SCRAM-SHA-384和SCRAM-SHA-512。

注意:仅当AUTH_SASL软件包可用时,才支持SCRAM-SHA认证方法。

3.7   XOAUTH2

XOAUTH2认证方法根据Gmail的SASL XOAUTH2文档发送用户名和OAuth2访问令牌。

4   安全连接

如果PHP中启用了安全套接字传输,则可以与远程SMTP服务器建立安全连接

$smtp = new Net_SMTP('ssl://mail.example.com', 465);

此示例使用ssl://传输连接到mail.example.com的465端口(一个常见的SMTPS端口)。

默认情况下,通过auth()方法的$tls参数启用TLS/SSL以进行认证连接,但也可以使用starttls()方法手动发送STARTTLS命令。

5   发送数据

使用data()方法发送消息数据。数据可以作为单个字符串或作为打开的文件资源提供。

如果提供字符串,则它将通过数据引号系统传递,并作为一个块发送到套接字连接。这些操作都是基于内存的,因此发送大消息可能会导致内存使用量很高。

如果提供打开的文件资源,则data()方法将逐行从文件中读取消息数据。每个数据块将被引号包围并发送到套接字连接,从而降低数据发送操作的总内存开销。

可以通过将可选的第二个参数传递给data()来从消息体数据中单独指定标题数据。这对于使用打开的文件资源提供消息数据特别有用,因为它允许在运行时动态构建标题字段(如Subject:)。

$smtp->data($fp, "Subject: My Subject");

6   数据引用

默认情况下,所有外发字符串数据都按照SMTP标准进行引号处理。这意味着所有原生的Unix(\n)和Mac(\r)换行符都被转换为互联网标准CRLF(\r\n)换行符。此外,因为SMTP协议使用单个前导点(.)来表示消息数据的结束,所以原始数据字符串中的单个前导点将被“加倍”(例如,"..")。

当涉及大量数据时,这些字符串转换可能会很昂贵。例如,Net_SMTP包不了解MIME部分(它只将MIME消息视为一个大的字符字符串),因此在搜索可能需要转义的字符时,无法跳过非文本附件。

因此,您可以扩展Net_SMTP类以实现自己的自定义转义例程。只需基于Net_SMTP类创建一个新的类,并重新实现quotedata()方法

require 'Net_SMTP.php';

class Net_SMTP_custom extends Net_SMTP
{
    function quotedata($data)
    {
        /* Perform custom data quoting */
    }
}

请注意,$data参数将通过引用传递给quotedata()函数。这意味着您可以直接操作$data。这也避免了将大$data字符串复制到和从quotedata()方法中带来的开销。

7   服务器响应

Net_SMTP包保留服务器最后的响应以供进一步检查。getResponse()方法返回一个包含服务器响应代码作为整数和响应参数作为字符串的2-元组(两个元素的数组)。

在成功连接后,通过getGreeting()方法可以获得服务器的问候字符串。

8   调试

Net_SMTP包包含内置的调试输出例程(默认情况下已禁用)。调试输出必须通过setDebug()方法显式启用

$smtp->setDebug(true);

默认情况下,调试消息将发送到标准输出流。如果您需要更多对输出的控制,您可以可选地安装自己的调试处理程序。

function debugHandler($smtp, $message)
{
    echo "[$smtp->host] $message\n";
}

$smtp->setDebug(true, "debugHandler");

9   示例

9.1   基本用法

以下脚本演示了如何使用Net_SMTP包发送简单的电子邮件消息

require 'Net/SMTP.php';

$host = 'mail.example.com';
$from = '[email protected]';
$rcpt = array('[email protected]', '[email protected]');
$subj = "Subject: Test Message\n";
$body = "Body Line 1\nBody Line 2";

/* Create a new Net_SMTP object. */
if (! ($smtp = new Net_SMTP($host))) {
    die("Unable to instantiate Net_SMTP object\n");
}

/* Connect to the SMTP server. */
if (PEAR::isError($e = $smtp->connect())) {
    die($e->getMessage() . "\n");
}

/* Send the 'MAIL FROM:' SMTP command. */
if (PEAR::isError($smtp->mailFrom($from))) {
    die("Unable to set sender to <$from>\n");
}

/* Address the message to each of the recipients. */
foreach ($rcpt as $to) {
    if (PEAR::isError($res = $smtp->rcptTo($to))) {
        die("Unable to add recipient <$to>: " . $res->getMessage() . "\n");
    }
}

/* Set the body of the message. */
if (PEAR::isError($smtp->data($subj . "\r\n" . $body))) {
    die("Unable to send data\n");
}

/* Disconnect from the SMTP server. */
$smtp->disconnect();