# Email 类

CodeIgniter 强大的 Email 类支持以下功能：

- 多种协议：Mail、Sendmail 和 SMTP

- SMTP 的 TLS 和 SSL 加密

- 多个收件人

- 抄送（CC）和密送（BCC）

- HTML 或纯文本邮件

- 附件

- 自动换行

- 邮件优先级

- BCC 批处理模式，可将大型邮件列表分割为小型 BCC 批次

- 邮件调试工具

## 使用 Email 类

### 发送邮件

发送邮件不仅简单，还可即时配置或在 app/Config/Email.php 文件中设置首选项。

以下是一个发送邮件的基本示例：

    <?php

    $email = service('email');

    $email->setFrom('your@example.com', 'Your Name');
    $email->setTo('someone@example.com');
    $email->setCC('another@another-example.com');
    $email->setBCC('them@their-example.com');

    $email->setSubject('Email Test');
    $email->setMessage('Testing the email class.');

    $email->send();

### 设置邮件首选项

有 22 种不同的首选项可用于定制邮件发送方式。既可手动设置（如本节所述），也可通过配置文件中存储的首选项自动设置（详见 邮件首选项）。

#### 通过传递数组设置邮件首选项

通过向邮件初始化方法传递数组来设置首选项。以下是设置部分首选项的示例：

    <?php

    $config['protocol'] = 'sendmail';
    $config['mailPath'] = '/usr/sbin/sendmail';
    $config['charset']  = 'iso-8859-1';
    $config['wordWrap'] = true;

    $email->initialize($config);

备注

大多数首选项都有默认值，未设置时将自动使用。

#### 在配置文件中设置邮件首选项

如不希望使用上述方法设置首选项，可将其放入配置文件。只需打开 app/Config/Email.php 文件，在 Email 属性中设置配置项，然后保存文件即可自动使用。在配置文件中设置首选项后，无需使用 `$email->initialize()` 方法。

#### SMTP 协议的 SSL 与 TLS

为保护与 SMTP 服务器通信时的用户名、密码和邮件内容，应使用通道加密。两种不同的标准已被广泛部署，排查邮件发送问题时理解其差异非常重要。

大多数 SMTP 服务器允许通过 465 或 587 端口连接发送邮件。（原始 25 端口已很少使用，因为许多 ISP 设置了阻止规则，且通信完全为明文）。

关键区别在于，根据 RFC 8314，465 端口要求通信通道从一开始就使用 TLS 加密。而 587 端口连接允许明文通信，后续通过 `STARTTLS` SMTP 命令升级通道以使用加密。

465 端口的连接升级可能受服务器支持也可能不受支持，若服务器不允许，`STARTTLS` SMTP 命令可能会失败。若将端口设置为 465，应尝试将 `SMTPCrypto` 设置为空字符串（`''`），因为通信从一开始就使用 TLS 加密，无需 `STARTTLS`。

若配置要求连接到 587 端口，很可能应将 `SMTPCrypto` 设置为 `tls`，因为这将在与 SMTP 服务器通信时执行 `STARTTLS` 命令，从明文切换到加密通道。初始通信为明文，随后通过 `STARTTLS` 命令将通道升级为 TLS。

#### 查看首选项

上次成功发送使用的设置可从实例属性 `$archive` 获取。这有助于测试和调试，以确定 `send()` 调用时的实际值。

### 邮件首选项

以下是发送邮件时可设置的所有首选项列表。

首选项 | 默认值 | 选项 | 说明
--- | --- | --- | ---
fromEmail |  |  | 要在"from"标头中设置的邮件地址。
fromName |  |  | 要在"from"标头中设置的名称。
userAgent | CodeIgniter |  | "用户代理"。
protocol | mail | `mail`、`sendmail`、 或 `smtp` | 邮件发送协议。
mailPath | /usr/sbin/sendmail |  | Sendmail 的服务器路径。
SMTPHost |  |  | SMTP 服务器主机名。
SMTPAuthMethod | login | `login`、`plain` | SMTP 身份验证方式。（自 4.7.0 版本起可用）
SMTPUser |  |  | SMTP 用户名。
SMTPPass |  |  | SMTP 密码。
SMTPPort | 25 |  | SMTP 端口。（若设置为 `465`，无论 `SMTPCrypto` 设置如何， 都将使用 TLS 连接。）
SMTPTimeout | 5 |  | SMTP 超时时间（秒）。
SMTPKeepAlive | false | `true`/`false` | 启用持久 SMTP 连接。
SMTPCrypto | tls | `tls`、`ssl`、或 空字符串（`''`） | SMTP 加密。设置为 `ssl` 将使用 SSL 创建到服务器的安全通道； 设置为 `tls` 将向服务器发出 `STARTTLS` 命令。465 端口的连接应将此设置为空字符串（`''`）。 另请参阅 SMTP 协议的 SSL 与 TLS。
wordWrap | true | `true`/`false` | 启用自动换行。
wrapChars | 76 |  | 换行的字符数。
mailType | text | `text` 或 `html` | 邮件类型。若发送 HTML 邮件，必须将其作为完整网页发送。 确保没有相对链接或相对图片路径，否则将无法正常工作。
charset | UTF-8 |  | 字符集（`utf-8`、`iso-8859-1` 等）。
validate | true | `true`/`false` | 是否验证邮件地址。
priority | 3 | 1、2、3、4、5 | 邮件优先级。`1` = 最高。`5` = 最低。`3` = 正常。
CRLF | \r\n | `\r\n`、`\n` 或 `\r` | 换行字符。（使用 `\r\n` 以符合 RFC 822）。
newline | \r\n | `\r\n`、`\n` 或 `\r` | 换行字符。（使用 `\r\n` 以符合 RFC 822）。
BCCBatchMode | false | `true`/`false` | 启用 BCC 批处理模式。
BCCBatchSize | 200 |  | 每个 BCC 批次中的邮件数量。
DSN | false | `true`/`false` | 启用服务器通知消息。

### 覆盖自动换行

若启用了自动换行（建议遵循 RFC 822），且邮件中有很长的链接，它可能会被换行，导致收件人无法点击。CodeIgniter 允许在邮件内容的部分区域手动覆盖自动换行，如下所示:

    邮件文本中
    正常换行的部分。

    {unwrap}http://example.com/a_long_link_that_should_not_be_wrapped.html{/unwrap}

    更多将正常
    换行的文本。

将不希望被自动换行的项目放置在：{unwrap} {/unwrap} 之间。

## 类参考

class CodeIgniter\Email\Email
  setFrom($from[, $name = ''[, $returnPath = null]])
    参数:

      - $from (`string`) -- "From" 邮件地址

      - $name (`string`) -- "From" 显示名称

      - $returnPath (`string`) -- 用于重定向未送达邮件的可选邮件地址

    返回:

      CodeIgniter\Email\Email 实例（方法链式调用）

    返回类型:

      `CodeIgniter\Email\Email`

    设置发件人的邮件地址和名称：

        <?php

        $email->setFrom('you@example.com', 'Your Name');

    还可设置 Return-Path 以帮助重定向未送达的邮件：

        <?php

        $email->setFrom('you@example.com', 'Your Name', 'returned_emails@example.com');

    备注

    若将协议配置为 'smtp'，则无法使用 Return-Path。

  setReplyTo($replyto[, $name = ''])
    参数:

      - $replyto (`string`) -- 回复邮件地址

      - $name (`string`) -- 回复邮件地址的显示名称

    返回:

      CodeIgniter\Email\Email 实例（方法链式调用）

    返回类型:

      `CodeIgniter\Email\Email`

    设置回复地址。若未提供信息，则使用 setFrom 方法中的信息。示例：

        <?php

        $email->setReplyTo('you@example.com', 'Your Name');

  setTo($to)
    参数:

      - $to (`mixed`) -- 逗号分隔的字符串或邮件地址数组

    返回:

      CodeIgniter\Email\Email 实例（方法链调用）

    返回类型:

      `CodeIgniter\Email\Email`

    设置收件人的邮件地址。可以是单个邮件、逗号分隔列表或数组：

        <?php

        $email->setTo('someone@example.com');

        <?php

        $email->setTo('one@example.com, two@example.com, three@example.com');

        <?php

        $email->setTo(['one@example.com', 'two@example.com', 'three@example.com']);

  setCC($cc)
    参数:

      - $cc (`mixed`) -- 逗号分隔的字符串或邮件地址数组

    返回:

      CodeIgniter\Email\Email 实例（方法链调用）

    返回类型:

      `CodeIgniter\Email\Email`

    设置抄送（CC）邮件地址。与 "to" 相同，可以是单个邮件、逗号分隔列表或数组。

  setBCC($bcc[, $limit = ''])
    参数:

      - $bcc (`mixed`) -- 逗号分隔的字符串或邮件地址数组

      - $limit (`int`) -- 每批次发送的最大邮件数量

    返回:

      CodeIgniter\Email\Email 实例（方法链调用）

    返回类型:

      `CodeIgniter\Email\Email`

    设置密送（BCC）邮件地址。与 `setTo()` 方法相同，可以是单个邮件、逗号分隔列表或数组。

    若设置了 `$limit`，将启用"批处理模式"，邮件将分批发送，每批不超过指定的 `$limit`。

  setSubject($subject)
    参数:

      - $subject (`string`) -- 邮件主题

    返回:

      CodeIgniter\Email\Email 实例（方法链调用）

    返回类型:

      `CodeIgniter\Email\Email`

    设置邮件主题：

        <?php

        $email->setSubject('This is my subject');

  setMessage($body)
    参数:

      - $body (`string`) -- 邮件消息正文

    返回:

      CodeIgniter\Email\Email 实例（方法链调用）

    返回类型:

      `CodeIgniter\Email\Email`

    设置邮件消息正文：

        <?php

        $email->setMessage('This is my message');

  setAltMessage($str)
    参数:

      - $str (`string`) -- 备选邮件消息正文

    返回:

      CodeIgniter\Email\Email 实例（方法链调用）

    返回类型:

      `CodeIgniter\Email\Email`

    设置备选邮件消息正文：

        <?php

        $email->setAltMessage('This is the alternative message');

    这是可选的消息字符串，用于发送 HTML 格式邮件时指定无 HTML 格式的备选消息，添加到标头字符串中供不接受 HTML 邮件的人使用。若未设置自己的消息，CodeIgniter 将从 HTML 邮件中提取消息并去除标签。

  setHeader($header, $value)
    参数:

      - $header (`string`) -- 标头名称

      - $value (`string`) -- 标头值

    返回:

      CodeIgniter\Email\Email 实例（方法链调用）

    返回类型:

      `CodeIgniter\Email\Email`

    向邮件追加额外标头：

        <?php

        $email->setHeader('Header1', 'Value1');
        $email->setHeader('Header2', 'Value2');

  clear($clearAttachments = false)
    参数:

      - $clearAttachments (`bool`) -- 是否清除附件

    返回:

      CodeIgniter\Email\Email 实例（方法链调用）

    返回类型:

      `CodeIgniter\Email\Email`

    将所有邮件变量初始化为空状态。此方法用于在循环中运行邮件发送方法时，允许在每个周期之间重置数据。

        <?php

        foreach ($list as $name => $address) {
            $email->clear();

            $email->setTo($address);
            $email->setFrom('your@example.com');
            $email->setSubject('Here is your info ' . $name);
            $email->setMessage('Hi ' . $name . ' Here is the info you requested.');
            $email->send();
        }

    若将参数设置为 true，附件也将被清除：

        <?php

        $email->clear(true);

  send($autoClear = true)
    参数:

      - $autoClear (`bool`) -- 是否自动清除消息数据

    返回:

      成功返回 true，失败返回 false

    返回类型:

      `bool`

    邮件发送方法。根据成功或失败返回布尔值 true 或 false，可用于条件判断：

        <?php

        if (! $email->send()) {
            // Generate error
        }

    若请求成功，此方法将自动清除所有参数。要阻止此行为，请传递 false：

        <?php

        if ($email->send(false)) {
            // Parameters won't be cleared
        }

    备注

    为使用 `printDebugger()` 方法，需要避免清除邮件参数。

    备注

    若启用 `BCCBatchMode`，且收件人数量超过 `BCCBatchSize`，此方法将始终返回布尔值 `true`。

  attach($filename[, $disposition = ''[, $newname = null[, $mime = '']]])
    参数:

      - $filename (`string`) -- 文件名

      - $disposition (`string`) -- 附件的 'disposition'。大多数邮件客户端会无视此处使用的 MIME 规范自行决定。https://www.iana.org/assignments/cont-disp/cont-disp.xhtml

      - $newname (`string`) -- 邮件中使用的自定义文件名

      - $mime (`string`) -- 使用的 MIME 类型（对缓冲数据有用）

    返回:

      CodeIgniter\Email\Email 实例（方法链调用）

    返回类型:

      `CodeIgniter\Email\Email`

    用于发送附件。将文件路径/名称放在第一个参数中。要附加多个附件，多次使用此方法。例如：

        <?php

        $email->attach('/path/to/photo1.jpg');
        $email->attach('/path/to/photo2.jpg');
        $email->attach('/path/to/photo3.jpg');

    要使用默认的 disposition（附件），将第二个参数留空，否则使用自定义 disposition：

        <?php

        $email->attach('image.jpg', 'inline');

    也可使用 URL：

        <?php

        $email->attach('http://example.com/filename.pdf');

    若想使用自定义文件名，可使用第三个参数：

        <?php

        $email->attach('filename.pdf', 'attachment', 'report.pdf');

    若需要使用缓冲字符串而非真实的物理文件，可将第一个参数用作缓冲，第三个参数用作文件名，第四个参数用作 MIME 类型：

        <?php

        $email->attach($buffer, 'attachment', 'report.pdf', 'application/pdf');

  setAttachmentCID($filename)
    参数:

      - $filename (`string`) -- 现有附件文件名

    返回:

      附件的 Content-ID，若未找到则返回 false

    返回类型:

      `string`

    设置并返回附件的 Content-ID，用于将内联（图片）附件嵌入 HTML。第一个参数必须是已附加的文件名。

        <?php

        $filename = '/img/photo1.jpg';
        $email->attach($filename);

        foreach ($list as $address) {
            $email->setTo($address);
            $cid = $email->setAttachmentCID($filename);
            $email->setMessage('<img src="cid:' . $cid . '" alt="photo1">');
            $email->send();
        }

    备注

    每封邮件的 Content-ID 必须重新创建以确保唯一性。

  printDebugger($include = ['headers', 'subject', 'body'])
    参数:

      - $include (`array`) -- 要打印的消息部分

    返回:

      格式化的调试数据

    返回类型:

      `string`

    返回包含任何服务器消息、邮件标头和邮件消息的字符串。对调试很有用。

    可选择指定应打印消息的哪些部分。有效选项为：headers、subject、body。

    示例：

        <?php

        // You need to pass false while sending in order for the email data
        // to not be cleared - if that happens, printDebugger() would have
        // nothing to output.
        $email->send(false);

        // Will only print the email headers, excluding the message subject and body
        $email->printDebugger(['headers']);

    备注

    默认情况下，将打印所有原始数据。