# Gửi email

`POST /emails` gửi một email tới tối đa 50 người nhận. `POST /emails/batch` gửi tối đa 100 email khác nhau trong một lần gọi. Trang này đi qua từng trường, response, hẹn giờ, idempotency, các giới hạn, và cách theo dõi một email qua các trạng thái và sự kiện.

## Trước khi bắt đầu

- Một tên miền đã xác minh. Xem [Tên miền](https://hatang.dev/vi/docs/guides/email/domains.md).
- API key có phạm vi `email:send`. Xem [Xác thực](https://hatang.dev/vi/docs/guides/getting-started/authentication.md).
- Request gửi tới `https://api.hatang.dev` với header `Authorization: Bearer ht_...` và `Content-Type: application/json`.

## Gửi một email

**cURL**

```bash
curl -X POST https://api.hatang.dev/emails \
  -H "Authorization: Bearer $HATANG_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: order-1024-confirmation" \
  -d '{
    "from": "Shop <orders@shop.vn>",
    "to": ["lan@example.vn"],
    "cc": ["ketoan@shop.vn"],
    "reply_to": "hotro@shop.vn",
    "subject": "Đơn #1024 đã được xác nhận",
    "html": "<p>Chào Lan, đơn <strong>#1024</strong> của bạn đã được xác nhận.</p>",
    "text": "Chào Lan, đơn #1024 của bạn đã được xác nhận.",
    "tags": [{ "name": "category", "value": "order_confirmation" }],
    "headers": { "X-Order-Id": "1024" }
  }'
```

**Node.js**

```ts
import { Hatang } from "@hatang/sdk";

const hatang = new Hatang(process.env.HATANG_API_KEY, { baseUrl: "https://api.hatang.dev" });

const { data, error } = await hatang.emails.send(
  {
    from: "Shop <orders@shop.vn>",
    to: ["lan@example.vn"],
    cc: ["ketoan@shop.vn"],
    reply_to: "hotro@shop.vn",
    subject: "Đơn #1024 đã được xác nhận",
    html: "<p>Chào Lan, đơn <strong>#1024</strong> của bạn đã được xác nhận.</p>",
    text: "Chào Lan, đơn #1024 của bạn đã được xác nhận.",
    tags: [{ name: "category", value: "order_confirmation" }],
    headers: { "X-Order-Id": "1024" },
  },
  { idempotencyKey: "order-1024-confirmation" },
);
if (error) throw new Error(`${error.name}: ${error.message}`);
console.log(data.id);
```

**Python**

```python
from hatang import Hatang

hatang = Hatang()  # đọc HATANG_API_KEY
email = hatang.emails.send(
    {
        "from": "Shop <orders@shop.vn>",
        "to": ["lan@example.vn"],
        "cc": ["ketoan@shop.vn"],
        "reply_to": "hotro@shop.vn",
        "subject": "Đơn #1024 đã được xác nhận",
        "html": "<p>Chào Lan, đơn <strong>#1024</strong> của bạn đã được xác nhận.</p>",
        "text": "Chào Lan, đơn #1024 của bạn đã được xác nhận.",
        "tags": [{"name": "category", "value": "order_confirmation"}],
        "headers": {"X-Order-Id": "1024"},
    },
    idempotency_key="order-1024-confirmation",
)
print(email["id"])  # gọi lỗi thì ném hatang.HatangError
```

**PHP**

```php
<?php
$client = new GuzzleHttp\Client(['base_uri' => 'https://api.hatang.dev']);

$res = $client->post('/emails', [
    'headers' => [
        'Authorization' => 'Bearer ' . getenv('HATANG_API_KEY'),
        'Idempotency-Key' => 'order-1024-confirmation',
    ],
    'json' => [
        'from' => 'Shop <orders@shop.vn>',
        'to' => ['lan@example.vn'],
        'cc' => ['ketoan@shop.vn'],
        'reply_to' => 'hotro@shop.vn',
        'subject' => 'Đơn #1024 đã được xác nhận',
        'html' => '<p>Chào Lan, đơn <strong>#1024</strong> của bạn đã được xác nhận.</p>',
        'text' => 'Chào Lan, đơn #1024 của bạn đã được xác nhận.',
        'tags' => [['name' => 'category', 'value' => 'order_confirmation']],
        'headers' => ['X-Order-Id' => '1024'],
    ],
]);
echo json_decode($res->getBody(), true)['id'];
```

**Go**

```go
body := strings.NewReader(`{
  "from": "Shop <orders@shop.vn>",
  "to": ["lan@example.vn"],
  "subject": "Đơn #1024 đã được xác nhận",
  "html": "<p>Đơn <strong>#1024</strong> của bạn đã được xác nhận.</p>"
}`)
req, _ := http.NewRequest("POST", "https://api.hatang.dev/emails", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("HATANG_API_KEY"))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Idempotency-Key", "order-1024-confirmation")
res, err := http.DefaultClient.Do(req)
```

Response là `200` kèm id của email mới (một UUID):

```json
{ "id": "0199e6c1-7a2b-7f00-9c1e-3f6a2b1d9e10" }
```

`200` nghĩa là Hạ Tầng đã nhận email và đưa vào hàng đợi. Việc giao thư diễn ra sau đó; theo dõi bằng [trạng thái và sự kiện](#statuses-and-events).

## Các trường của request

| Trường | Kiểu | Mô tả |
|---|---|---|
| `from` | string | Người gửi, `hello@shop.vn` hoặc `Shop <hello@shop.vn>`. Tên miền phải đã xác minh. Chỉ được bỏ trống khi `template` đã có sẵn. |
| `to` | string hoặc mảng | Người nhận. |
| `cc` | string hoặc mảng | Người nhận đồng gửi. |
| `bcc` | string hoặc mảng | Người nhận ẩn. Không bao giờ xuất hiện trong header thư. |
| `reply_to` | string hoặc mảng | Địa chỉ Reply-To, tối đa 50. |
| `subject` | string | Tối đa 998 ký tự. Bắt buộc, trừ khi `template` đã có sẵn. |
| `html` | string | Nội dung HTML, tối đa 10.000.000 ký tự. |
| `text` | string | Nội dung văn bản thuần, tối đa 10.000.000 ký tự. |
| `template` | object | `{ "id": "tpl_… hoặc alias", "variables": { … } }` gửi một template đã publish thay cho `html`/`text`. Xem [Templates](https://hatang.dev/vi/docs/guides/email/templates.md). |
| `headers` | object | Header thêm, ví dụ `{ "X-Order-Id": "1024" }`. |
| `tags` | mảng | Tối đa 50 cặp `{ "name", "value" }`, được gửi kèm trong webhook. |
| `attachments` | mảng | Tối đa 50 tệp. Xem [Tệp đính kèm](#attachments). |
| `scheduled_at` | string | Gửi sau. Xem [Hẹn giờ gửi](#schedule-an-email). |
| `topic_id` | string | Bỏ qua người nhận đã rời topic này. Xem [Contacts, segments và topics](https://hatang.dev/vi/docs/guides/email/audiences.md). |

Phải có `html`, `text` hoặc `template`. Request có `template` thì không được có thêm `html` hay `text`.

> **Tip: Gửi cả HTML lẫn văn bản thuần**
>
> Hạ Tầng chỉ tự tạo phần văn bản thuần từ HTML khi gửi bằng template. Khi gửi trực tiếp, hãy truyền cả `html` và `text`: một số ứng dụng email và bộ lọc spam có xem phần văn bản.

### Người nhận

- Địa chỉ viết dạng thường (`lan@example.vn`) hoặc kèm tên hiển thị (`Lan <lan@example.vn>`).
- `to`, `cc` và `bcc` cộng lại tối đa **50** địa chỉ. Muốn gửi cho nhiều người hơn, gửi mỗi người một email (bằng `/emails/batch`) hoặc dùng [chiến dịch email](https://hatang.dev/vi/docs/guides/email/broadcasts.md).
- Mỗi người nhận được giao và theo dõi riêng. Người nhận nằm trong [danh sách chặn](https://hatang.dev/vi/docs/guides/email/suppressions-and-bounces.md) bị bỏ qua và được báo là bị trả lại.

### Header

Dùng `headers` cho các header riêng như `X-Order-Id` hay `List-Unsubscribe`. Hạ Tầng bỏ các header do chính nó đặt: `From`, `To`, `Cc`, `Bcc`, `Subject`, `Date`, `Message-ID`, `Content-Type`, `Content-Transfer-Encoding`, `MIME-Version`, `Return-Path`, `Received`, `DKIM-Signature` và `Authentication-Results`. Mọi thư còn có header `X-Entity-Ref-ID` chứa id của email.

### Tag

Tag dùng để đánh dấu email cho hệ thống của bạn. `name` và `value` mỗi trường dài 1 tới 256 ký tự, chỉ gồm chữ cái ASCII, số, `_` và `-`. Trong webhook, tag có dạng object, ví dụ `"tags": { "category": "order_confirmation" }`.

### Tệp đính kèm {#attachments}

Gửi nội dung mỗi tệp dạng base64 trong `content`:

```json
{
  "attachments": [
    { "filename": "hoa-don-1024.pdf", "content": "JVBERi0xLjcKJc…", "content_type": "application/pdf" },
    { "filename": "logo.png", "content": "iVBORw0KGgo…", "content_type": "image/png", "content_id": "logo" }
  ]
}
```

| Trường | Mô tả |
|---|---|
| `filename` | Tên tệp người nhận thấy, tối đa 255 ký tự. |
| `content` | Tệp dạng chuỗi base64. SDK Node.js nhận cả `Buffer` hoặc `Uint8Array` và tự mã hoá. |
| `content_type` | Kiểu MIME. Không bắt buộc. |
| `content_id` | Đặt để hiển thị tệp ngay trong nội dung: trong HTML viết `<img src="cid:logo">`. |

> **Caution: Chưa hỗ trợ `path`**
>
> Tệp đính kèm theo URL (`path`) bị từ chối với lỗi `422 invalid_attachment`. Hãy tự tải tệp về rồi gửi bằng `content`.

Toàn bộ email, gồm nội dung và tệp đính kèm sau khi giải mã, phải dưới **40 MB**.

### React Email

SDK Node.js nhận một phần tử `react` và render ra `html` và `text` trước khi gửi request (bản thân API chỉ nhận `html` và `text`). Cài thêm `@react-email/render` và `react` cạnh SDK:

```tsx
import { Hatang } from "@hatang/sdk";
import { WelcomeEmail } from "./emails/welcome";

const hatang = new Hatang(process.env.HATANG_API_KEY, { baseUrl: "https://api.hatang.dev" });

await hatang.emails.send({
  from: "Shop <hello@shop.vn>",
  to: "lan@example.vn",
  subject: "Chào mừng bạn đến với Shop",
  react: <WelcomeEmail name="Lan" />,
});
```

## Hẹn giờ gửi {#schedule-an-email}

Đặt `scheduled_at` là một thời điểm ISO 8601 có múi giờ, hoặc một cụm như `in 1 hour`, `in 30 minutes`, `in 2 days`. Thời điểm ISO tối đa 30 ngày tới.

```json
{ "from": "Shop <hello@shop.vn>", "to": ["lan@example.vn"], "subject": "Ngày mai hết hạn dùng thử", "html": "<p>…</p>", "scheduled_at": "2026-10-20T09:00:00+07:00" }
```

Email có trạng thái `scheduled`. Trước khi gửi, bạn có thể dời giờ hoặc huỷ:

**cURL**

```bash
# Dời giờ
curl -X PATCH https://api.hatang.dev/emails/$EMAIL_ID \
  -H "Authorization: Bearer $HATANG_API_KEY" -H "Content-Type: application/json" \
  -d '{ "scheduled_at": "in 3 hours" }'

# Huỷ
curl -X POST https://api.hatang.dev/emails/$EMAIL_ID/cancel -H "Authorization: Bearer $HATANG_API_KEY"
```

**Node.js**

```ts
await hatang.emails.update({ id: emailId, scheduledAt: "in 3 hours" });
await hatang.emails.cancel(emailId);
```

**Python**

```python
hatang.emails.update(email_id, scheduled_at="in 3 hours")
hatang.emails.cancel(email_id)
```

**PHP**

```php
$headers = ['Authorization' => 'Bearer ' . getenv('HATANG_API_KEY')];
$client->patch("/emails/$emailId", ['headers' => $headers, 'json' => ['scheduled_at' => 'in 3 hours']]);
$client->post("/emails/$emailId/cancel", ['headers' => $headers]);
```

Cả hai trả về `{ "object": "email", "id": "…" }`. Dời giờ hoặc huỷ một email không còn ở trạng thái `scheduled` sẽ nhận lỗi `422`. Email đã huỷ có trạng thái `canceled`.

## Gửi theo lô

`POST /emails/batch` nhận một mảng từ 1 tới 100 email. Mỗi phần tử có các trường giống `POST /emails`, trừ `attachments` và `scheduled_at` không được dùng.

**cURL**

```bash
curl -X POST https://api.hatang.dev/emails/batch \
  -H "Authorization: Bearer $HATANG_API_KEY" \
  -H "Content-Type: application/json" \
  -d '[
    { "from": "Shop <hello@shop.vn>", "to": ["lan@example.vn"], "subject": "Chào Lan", "html": "<p>Chào Lan</p>" },
    { "from": "Shop <hello@shop.vn>", "to": ["minh@example.vn"], "subject": "Chào Minh", "html": "<p>Chào Minh</p>" }
  ]'
```

**Node.js**

```ts
const { data, error } = await hatang.batch.send([
  { from: "Shop <hello@shop.vn>", to: ["lan@example.vn"], subject: "Chào Lan", html: "<p>Chào Lan</p>" },
  { from: "Shop <hello@shop.vn>", to: ["minh@example.vn"], subject: "Chào Minh", html: "<p>Chào Minh</p>" },
]);
```

**Python**

```python
result = hatang.batch.send([
    {"from": "Shop <hello@shop.vn>", "to": ["lan@example.vn"], "subject": "Chào Lan", "html": "<p>Chào Lan</p>"},
    {"from": "Shop <hello@shop.vn>", "to": ["minh@example.vn"], "subject": "Chào Minh", "html": "<p>Chào Minh</p>"},
])
```

**PHP**

```php
$res = $client->post('/emails/batch', [
    'headers' => ['Authorization' => 'Bearer ' . getenv('HATANG_API_KEY')],
    'json' => [
        ['from' => 'Shop <hello@shop.vn>', 'to' => ['lan@example.vn'], 'subject' => 'Chào Lan', 'html' => '<p>Chào Lan</p>'],
        ['from' => 'Shop <hello@shop.vn>', 'to' => ['minh@example.vn'], 'subject' => 'Chào Minh', 'html' => '<p>Chào Minh</p>'],
    ],
]);
```

```json
{ "data": [{ "id": "0199e6c1-7a2b-7f00-9c1e-3f6a2b1d9e10" }, { "id": "0199e6c1-7a2c-7c41-8f0e-61f1b2a3c4d5" }] }
```

Các id theo đúng thứ tự các phần tử.

> **Caution: Gửi theo lô không phải "tất cả hoặc không gì cả"**
>
> Hạ Tầng kiểm tra cấu trúc của mọi phần tử trước khi gửi. Những kiểm tra cần tới tài khoản của bạn (tên miền của `from`, template, hạn mức ngày) chạy lần lượt từng phần tử trong lúc gửi, nên nếu phần tử thứ 5 lỗi thì phần tử 1 tới 4 đã được gửi và lệnh gọi trả về lỗi. Trước một lô lớn, hãy chắc chắn mọi tên miền `from` đã xác minh và hạn mức còn đủ. Endpoint batch không hỗ trợ `Idempotency-Key`.

## Idempotency {#idempotency}

Lỗi mạng là chuyện thường. Để gọi lại `POST /emails` an toàn, gửi kèm header `Idempotency-Key` (trong SDK Node.js là tuỳ chọn `idempotencyKey`). Dùng một key định danh thư trong hệ thống của bạn, ví dụ `order-1024-confirmation`.

| Tình huống | Kết quả |
|---|---|
| Request đầu tiên với key | Email được tạo và gửi. |
| Cùng key, cùng nội dung | `200` kèm id của email đầu tiên. Không gửi lại và không trừ hạn mức. |
| Cùng key, nội dung khác | `400 invalid_idempotent_request` |
| Cùng key khi request đầu còn đang chạy | `409 concurrent_idempotent_requests`. Đợi một chút rồi thử lại. |

Key thuộc về doanh nghiệp của bạn: hai doanh nghiệp khác nhau dùng cùng một key không xung đột.

## Giới hạn

| Giới hạn | Giá trị |
|---|---|
| Người nhận mỗi email | 50, tính chung `to`, `cc` và `bcc` |
| Địa chỉ `reply_to` | 50 |
| Tiêu đề | 998 ký tự |
| `html`, `text` | Mỗi trường 10.000.000 ký tự |
| Tệp đính kèm | 50 tệp mỗi email |
| Kích thước email | 40 MB, gồm nội dung và tệp đính kèm |
| Tag | 50 tag mỗi email, mỗi tên hoặc giá trị tối đa 256 ký tự |
| Gửi theo lô | 100 email mỗi lần gọi |
| Hẹn giờ | Tối đa 30 ngày tới |
| Tốc độ gọi | 10 request mỗi giây cho mỗi doanh nghiệp. Response có header `ratelimit-limit`, `ratelimit-remaining` và `ratelimit-reset`; lỗi `429` có thêm `retry-after`. |
| Hạn mức ngày | Mỗi email (mỗi phần tử của lô, mỗi email của chiến dịch) tính là một. Đặt lại lúc nửa đêm UTC. `GET /usage` cho biết còn bao nhiêu. |

## Lỗi

Lỗi ở mọi nơi có cùng một dạng:

```json
{ "statusCode": 403, "name": "validation_error", "message": "The shop.vn domain is not verified. Please, add and verify your domain first." }
```

| Mã | `name` | Khi nào |
|---|---|---|
| 422 | `validation_error` | Thiếu hoặc sai trường, ví dụ không có `html`/`text`/`template`, quá 50 người nhận, hoặc `scheduled_at` quá 30 ngày. |
| 403 | `validation_error` | Tên miền của `from` chưa được thêm vào doanh nghiệp hoặc chưa xác minh. |
| 401 | `restricted_api_key` | API key bị giới hạn vào tên miền gửi khác. |
| 422 | `invalid_attachment` | Tệp đính kèm dùng `path`. |
| 403 | `application_error` | Doanh nghiệp đang tạm dừng gửi (**Cài đặt email**). |
| 429 | `rate_limit_exceeded` | Quá 10 request mỗi giây. |
| 429 | `daily_quota_exceeded` | Đã dùng hết hạn mức ngày. |
| 400 | `invalid_idempotent_request` | Idempotency key đã được dùng với nội dung khác. |
| 409 | `concurrent_idempotent_requests` | Một request khác cùng idempotency key đang chạy. |

Danh sách đầy đủ ở [Lỗi](https://hatang.dev/vi/docs/reference/errors.md).

## Xem và liệt kê email

`GET /emails/{id}` trả về một email:

```json
{
  "object": "email",
  "id": "0199e6c1-7a2b-7f00-9c1e-3f6a2b1d9e10",
  "to": ["lan@example.vn"],
  "from": "Shop <orders@shop.vn>",
  "created_at": "2026-10-14T09:12:03.000Z",
  "subject": "Đơn #1024 đã được xác nhận",
  "html": "<p>Chào Lan, …</p>",
  "text": "Chào Lan, …",
  "bcc": null,
  "cc": ["ketoan@shop.vn"],
  "reply_to": ["hotro@shop.vn"],
  "last_event": "delivered",
  "status": "delivered",
  "scheduled_at": null,
  "tags": [{ "name": "category", "value": "order_confirmation" }],
  "headers": { "X-Order-Id": "1024" }
}
```

`GET /emails` liệt kê email, mới nhất trước:

| Tham số query | Mô tả |
|---|---|
| `limit` | 1 tới 100, mặc định 20. |
| `after`, `before` | Con trỏ phân trang: truyền id của email cuối (hoặc đầu) của trang đang có. |
| `status` | Một hoặc nhiều trạng thái cách nhau bởi dấu phẩy, ví dụ `bounced,complained`. |
| `source` | `api`, `smtp`, `broadcast`, `chat` hoặc `system`. |
| `q` | Tìm theo tiêu đề, người gửi, địa chỉ `to`, hoặc đúng id email. |

`GET /emails/{id}/events` trả về mọi sự kiện của email và trạng thái của từng người nhận, kèm phản hồi SMTP gần nhất:

```json
{
  "object": "list",
  "data": [
    { "id": "evt_…", "type": "email.sent", "created_at": "2026-10-14T09:12:03.000Z", "data": { "source": "api" } },
    { "id": "evt_…", "type": "email.delivered", "created_at": "2026-10-14T09:12:05.000Z", "data": { "address": "lan@example.vn", "code": 250 } }
  ],
  "recipients": [
    { "address": "lan@example.vn", "kind": "to", "status": "delivered", "attempts": 1, "last_smtp_code": 250, "last_smtp_response": "250 Ok", "next_attempt_at": null }
  ]
}
```

## Trạng thái và sự kiện {#statuses-and-events}

`status` của email tổng hợp từ các người nhận:

| Trạng thái | Ý nghĩa |
|---|---|
| `scheduled` | Đang chờ tới `scheduled_at`. |
| `queued` | Đã nhận, đang chờ chuyển cho máy chủ thư. |
| `sent` | Đã chuyển đi; còn ít nhất một người nhận chưa có kết quả cuối. |
| `delivered` | Mọi người nhận được gửi tới đều đã nhận được thư. Khi một số người nhận bị trả lại còn số khác đã nhận, trạng thái cũng là `delivered`; xem chi tiết ở từng người nhận. |
| `delivery_delayed` | Đang thử giao lại cho ít nhất một người nhận. |
| `bounced` | Không giao được cho người nhận nào, kể cả khi mọi người nhận đều nằm trong danh sách chặn. |
| `complained` | Một người nhận đánh dấu email là spam. |
| `canceled` | Email hẹn giờ đã bị huỷ. |
| `failed` | Hạ Tầng không gửi được email. |

Mỗi người nhận có trạng thái riêng trong `GET /emails/{id}/events`: `pending`, `sent`, `delivered`, `delayed`, `bounced`, `suppressed` hoặc `canceled`.

Các sự kiện webhook sau theo dõi một email. Đăng ký ở mục **Webhooks** trong dashboard hoặc bằng `POST /webhooks`; xem [Webhook](https://hatang.dev/vi/docs/guides/getting-started/webhooks.md).

| Sự kiện | Khi nào |
|---|---|
| `email.sent` | Hạ Tầng đã nhận email. |
| `email.delivered` | Máy chủ thư của người nhận đã nhận thư. |
| `email.delivery_delayed` | Đang thử giao lại. Gửi ở lần chậm đầu tiên, sau đó tối đa mỗi giờ một lần cho mỗi người nhận. |
| `email.bounced` | Một người nhận bị trả lại, hoặc bị bỏ qua vì địa chỉ nằm trong danh sách chặn (`bounce.subType` là `Suppressed`). |
| `email.complained` | Một người nhận báo email là spam. |
| `email.opened` | Một người nhận mở email. Cần bật theo dõi mở; tối đa mỗi giờ một lần cho mỗi người nhận. |
| `email.clicked` | Một người nhận nhấp vào link. Cần bật theo dõi nhấp. |
| `email.failed` | Không gửi được email. |

Webhook bị trả lại có kèm lý do:

```json
{
  "type": "email.bounced",
  "created_at": "2026-10-14T09:12:07.000Z",
  "data": {
    "email_id": "0199e6c1-7a2b-7f00-9c1e-3f6a2b1d9e10",
    "from": "Shop <orders@shop.vn>",
    "to": ["lan@example.vn"],
    "subject": "Đơn #1024 đã được xác nhận",
    "created_at": "2026-10-14T09:12:03.000Z",
    "tags": { "category": "order_confirmation" },
    "bounce": { "type": "Permanent", "subType": "NoEmail", "message": "550 5.1.1 The email account that you tried to reach does not exist." }
  }
}
```

## Bước tiếp theo

- [Templates](https://hatang.dev/vi/docs/guides/email/templates.md): gửi bằng id template kèm biến.
- [SMTP relay](https://hatang.dev/vi/docs/guides/email/smtp.md): gửi từ ứng dụng chỉ biết SMTP.
- [Danh sách chặn và thư trả lại](https://hatang.dev/vi/docs/guides/email/suppressions-and-bounces.md): điều gì xảy ra sau khi thư bị trả lại.
- [Tham chiếu REST API](https://hatang.dev/vi/docs/reference/api.md)

Source: https://hatang.dev/vi/docs/guides/email/sending
