> ## Documentation Index
> Fetch the complete documentation index at: https://docs.dodopayments.com/llms.txt
> Use this file to discover all available pages before exploring further.

# 客户邮件日志

> 查看 Dodo Payments 代表您向客户发送的每封事务性邮件，检查邮件是否送达，阅读发送时的邮件原文，并再次发送邮件。

<CardGroup cols={2}>
  <Card title="List Customer Emails" icon="list" href="/api-reference/customers/list-customer-emails">
    阅读客户已发送的邮件及其送达结果。
  </Card>

  <Card title="Get Email Content" icon="envelope-open" href="/api-reference/customers/get-customer-email-body">
    阅读一封邮件发送时的原文。
  </Card>
</CardGroup>

## 概览

Dodo Payments 代表您向客户发送事务性邮件：收据、退款通知、订阅通知、催收和恢复邮件、权益授予邮件，以及 Customer Portal 登录链接。

客户记录中的 **Sent Emails** 标签页会记录每封邮件。对于每封邮件，您可以看到发送的内容、邮件送达到了哪一步，以及失败时未送达的原因。您可以打开客户收到的邮件，也可以再次发送。

<Frame>
  <img src="https://mintcdn.com/dodopayments/9G2eOufWVa-OvQvG/images/email-logs/sent-emails-tab.png?fit=max&auto=format&n=9G2eOufWVa-OvQvG&q=85&s=6c7fa235800cee5c32eb286312f2a52b" alt="客户的已发送的邮件标签页，列出每封邮件及其送达状态" style={{ maxHeight: '500px', width: 'auto' }} width="2310" height="996" data-path="images/email-logs/sent-emails-tab.png" />
</Frame>

<Info>
  邮件会保留 **180 天**。送达状态来自邮件服务提供商，通常会在每次送达事件发生后的几秒内更新。
</Info>

## 查看客户的邮件

<Steps>
  <Step title="Open the Customer">
    在控制面板中转到 **Sales → Customers**，然后选择客户。
  </Step>

  <Step title="Open the Sent Emails Tab">
    该标签页会列出过去 180 天内发送给此客户的每封邮件，最新的邮件排在最前面。
  </Step>

  <Step title="Read a Row">
    每一行显示主题，主题下方显示发件人和收件人地址。其他列显示 **Category**、**Date & Time**、**Delivery Status** 以及您可以执行的 **Actions**。
  </Step>
</Steps>

类别包括 **Payments**、**Refunds**、**Subscriptions**、**Dunning & Recovery**、**Entitlements** 或 **Auth**。Customer Portal 登录邮件属于 **Auth**。

## Delivery Status

每封邮件都有五种状态之一。API 返回状态值，控制面板显示其标签：

| Status | Dashboard label | Meaning |
| - | - | - |
| `sent` | **Sent** | Dodo Payments 已将邮件交给服务提供商。邮件正在发送途中，或者接收服务器尚未响应。 |
| `delivered` | **Delivered** | 接收邮件服务器已接受该邮件。 |
| `failed` | **Failed** | 邮件未送达。系统会显示失败原因。 |
| `complained` | **Marked as spam** | 收件人将邮件标记为垃圾邮件。 |
| `blocked` | **Not sent** | 未发送任何邮件，因为本周的测试模式额度已用完。 |

### Failure Reasons

邮件未送达时，该行会显示原因，以便您了解是否需要采取措施。将鼠标指针移到该行的状态上即可查看原因。API 会在 `failure_reason` 中返回相同的原因，并在 `failure_code` 中返回稳定代码：

| Reason | `failure_code` | What it means | What to do |
| - | - | - | - |
| Mailbox does not exist | `mailbox_not_found` | 该地址不存在。 | 更正客户的电子邮件地址。 |
| Address rejected by the mail server | `address_rejected` | 接收服务器拒绝了该地址。 | 使用其他地址。 |
| Address blocked after earlier failures | `address_suppressed` | 服务提供商在此前发生硬退信或投诉后，抑制了该地址。 | 使用其他地址。 |
| Mailbox is full | `mailbox_full` | 收件人的邮箱已没有可用空间。 | 稍后再次发送。 |
| Temporary delivery failure | `temporary_failure` | 接收服务器出现暂时性问题。 | 稍后再次发送。 |
| Message rejected as too large | `message_too_large` | 接收服务器拒绝了该邮件大小。 | 联系支持团队。 |
| Recipient marked the email as spam | `marked_as_spam` | 收件人举报了该邮件。 | 不要再次发送。 |
| Email could not be sent | `send_failed` | 服务提供商拒绝发送，或该失败不符合其他代码。 | 再次发送。 |
| Not sent: the test-mode email allowance for this week is spent | `test_mode_quota_spent` | 本周的 [test-mode allowance](#test-mode) 已用完。 | 等待额度重置。 |

其中五种原因在重新发送时需要使用其他地址，因为使用相同地址会再次失败：邮箱不存在、地址被邮件服务器拒绝、地址在此前失败后被阻止、邮件大小过大而被拒绝，以及收件人将邮件标记为垃圾邮件。

## Reading an Email

要阅读邮件，请在其所在行选择 **Resend**，或者在失败的行中选择 **Retry**。打开的面板会在 **Email Preview** 下显示已存储的副本，与发送时完全一致。您编写的恢复和催收邮件会带有 **Written by you** 标签。

<Frame>
  <img src="https://mintcdn.com/dodopayments/9G2eOufWVa-OvQvG/images/email-logs/email-preview.png?fit=max&auto=format&n=9G2eOufWVa-OvQvG&q=85&s=b0d00b4b6fe62c6ace0b8a2b4419619b" alt="The stored email content, shown as the customer received it" style={{ maxHeight: '500px', width: 'auto' }} width="824" height="1148" data-path="images/email-logs/email-preview.png" />
</Frame>

有些邮件没有可供显示的内容：

* **Customer Portal login emails.** 这些邮件包含实时登录链接，因此不会显示内容。
* **Blocked emails.** 这些邮件从未到达服务提供商，因此不存在副本。
* **Emails that could not be handed to the provider.** 未存储副本。
* **Emails older than 180 days.** 服务提供商会在此时清除邮件内容。

## Sending an Email Again

要再次发送邮件，请在其所在行选择 **Resend**，或者在失败的行中选择 **Retry**，然后在面板中确认。按钮会显示该邮件还可以重发多少次。Dodo Payments 会根据原始事件重新构建邮件，而不是使用已存储的副本，因此收据会显示付款的当前状态。邮件会保留原始事件的日期。

<Frame>
  <img src="https://mintcdn.com/dodopayments/9G2eOufWVa-OvQvG/images/email-logs/resend-email.png?fit=max&auto=format&n=9G2eOufWVa-OvQvG&q=85&s=8751c05df35b14f116c8d487eaae7b70" alt="The resend control on an email row, with the option to send to a different address" style={{ maxHeight: '500px', width: 'auto' }} width="896" height="2104" data-path="images/email-logs/resend-email.png" />
</Frame>

面板中的 **To** 字段包含原始地址。要将邮件发送到其他地址，请修改该字段。发生永久性失败后，**To** 字段会为空，您必须输入其他地址，因为原始地址会再次失败。

<Warning>
  重发是一封新邮件。客户会收到另一份副本，重发邮件也会在标签页中作为独立行显示。
</Warning>

### Limits

以下限制适用于每次重发：

* 每封邮件最多可以再次发送 **三次**。
* 向同一地址重发同一封邮件时，两次尝试之间需要等待：首次重发需在最近一次发送后等待五分钟，第二次等待十分钟，第三次等待十五分钟。
* 向任何地址重发时，都必须等到该地址上次收到您发送的邮件五分钟后才能发送。
* 未到达服务提供商的发送不会计入三次限制，但仍会增加等待时间。
* 只能在控制面板中使用 Resend。API 仅支持读取。

### When Resend Is Not Available

在以下情况下，控制面板不会提供重发选项，或会拒绝重发：

| Case | Reason |
| - | - |
| 收件人将邮件标记为垃圾邮件 | 收件人要求停止接收这些邮件。 |
| 地址已被抑制 | Provider 接受向该地址发送邮件后又将其丢弃。请输入其他地址。 |
| 同一封邮件的后续发送已发出 | 此行是历史记录，标记为 **已在后续尝试中发送**。再次发送会导致收件人收到第二份副本。 |
| 客户已被阻止 | [被阻止的客户](/features/customer-blocklist) 不会再收到您发送的任何邮件。 |
| 三次重新发送机会已用完 | 限制按邮件计算。 |
| 原始数据已丢失 | Dodo Payments 无法重建该邮件。 |
| 您团队的角色是 **Viewer** | Viewer 不会在该行看到重新发送操作。 |
| 测试模式下 **Test Mode Emails** 已关闭 | 您的企业已关闭测试模式客户邮件。请参阅 [Test Mode](#test-mode)。 |

<Note>
  Customer Portal 登录邮件始终会发送到请求该邮件的地址，每次重发都会创建新的登录链接。
</Note>

## Test Mode

测试模式会发送真实邮件，因此设有额度：**每个企业每周 100 封邮件**。重新发送也会消耗同一额度。每封测试模式邮件都会发送给真实收件人，主题开头包含 `[TEST MODE]`。

要停止测试模式客户邮件，请在 **Settings → Communication → Email** 中关闭 **Test Mode Emails**（请参阅 [Test Mode Emails](/features/communication-preferences#test-mode-emails)）。关闭期间，测试模式不会发送任何客户邮件、不会向该标签页添加任何行、不会消耗额度，并且 dashboard 会拒绝重新发送。Live mode 邮件不受影响。

额度用完后，该周内测试模式不会再发送任何邮件。该周第一封被拒绝的邮件会记录为一个 `blocked` 行，其内容为“未发送：本周的测试模式邮件额度已用完”。同一周内后续被拒绝的邮件不会添加任何行。额度会在每周开始时（星期一）重置。Live mode 没有此限制。

<Info>
  Customer Portal 登录邮件在测试模式下永远不会发送，也不会消耗额度。
</Info>

## 通过 API 读取邮件

您也可以使用 API key 获取列表和内容，从而在自己的支持工具中显示投递状态。列表默认每页返回 10 封邮件。设置 `page_size` 可返回最多 100 封邮件，并设置 `page_number` 进行分页，起始值为 0。

<CodeGroup>
  ```bash cURL theme={null}
  curl "https://live.dodopayments.com/customers/cus_123/emails?page_size=10" \
    -H "Authorization: Bearer $DODO_PAYMENTS_API_KEY"
  ```

  ```typescript Node.js expandable theme={null}
  const customerId = 'cus_123'; // the customer whose emails you want to read
  const res = await fetch(
    `https://live.dodopayments.com/customers/${customerId}/emails?page_size=10`,
    { headers: { Authorization: `Bearer ${process.env.DODO_PAYMENTS_API_KEY}` } },
  );
  const { items, total_count } = await res.json();
  ```

  ```python Python expandable theme={null}
  import os, requests

  customer_id = "cus_123"  # the customer whose emails you want to read
  res = requests.get(
      f"https://live.dodopayments.com/customers/{customer_id}/emails",
      params={"page_size": 10},
      headers={"Authorization": f"Bearer {os.environ['DODO_PAYMENTS_API_KEY']}"},
  )
  items = res.json()["items"]
  ```
</CodeGroup>

TypeScript 和 Python SDK 将两个 endpoint 分别封装为 `client.customers.emails.list()` 和 `client.customers.emails.retrieveBody()`（Python 中为 `retrieve_body()`）。

每个项目都包含其 `email_log_id`，您需要将其传递给内容 endpoint；同时还包含其 `status`。如果发送失败，项目还会包含 `failure_code` 和 `failure_reason`，并包含 `has_preview`，用于表示是否存在已存储的内容。当邮件没有可显示的内容时，内容 endpoint 会返回 `422`。每个项目还包含一个 `policies` 对象，用于说明您可以对该行执行哪些操作：

| Field | Meaning |
| - | - |
| `resend_allowed` | 邮件已发送或已投递，您可以再次发送。 |
| `retry_allowed` | 发送失败，您可以再次尝试。 |
| `resends_remaining` | 该邮件剩余的重新发送次数。 |
| `requires_different_address` | 使用相同地址仍会失败，因此您必须提供其他地址。 |
| `superseded` | 同一封邮件的后续发送替代了此行。 |

请读取 `policies`，而不要自行推导是否符合条件。服务器会应用上述规则。

<CardGroup cols={2}>
  <Card title="Customer Management" icon="user-group" href="/features/customers">
    管理客户、购买历史记录和自助服务访问权限。
  </Card>

  <Card title="Communication Preferences" icon="bell" href="/features/communication-preferences">
    选择由 Dodo Payments 代表您发送哪些邮件。
  </Card>
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.