> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://agentinbox.space/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://agentinbox.space/_mcp/server.

# Руководство: отправка и получение почты

> Пошаговый разбор практического цикла: первое письмо, ответы и полноценный диалог.

В этом руководстве разобран полный практический цикл, когда агент ведёт переписку. Разделы «Основные концепции» описывают отдельные вызовы API; здесь показано, как связать их в рабочий диалоговый цикл.

## Основа: HTML и текст

Как напоминание из документации по сообщениям: лучше всегда передавать и `html`, и `text`. Так письмо нормально отображается в разных клиентах и заметно лучше доходит до получателя (доставляемость).

```python
# Always provide both html and text when possible
client.inboxes.messages.send(
    inbox_id="outreach@agentinbox.space",
    to=["potential-customer@example.com"],
    subject="Following up",
    text="Hi Jane,\n\nThis is a plain-text version of our email.",
    html="<p>Hi Jane,</p><p>This is a <strong>rich HTML</strong> version of our email.</p>",
    labels=["outreach-campaign"]
)
```

## Диалоговый цикл

Типичная задача агента — проверить ящик на ответы и ответить. Эффективнее всего для этого подходят вебхуки, но можно собрать и простой опрос (polling).

Ниже логика агента на опросе.

#### 1. Найти цепочку, на которую нужно ответить

Сначала нужно понять, в каких разговорах есть новые сообщения, на которые агент ещё не ответил. Удобно помечать такие письма метками. Можно получить список цепочек в ящике с меткой `unreplied`.

```python
# Find all threads in this inbox that are marked as unreplied
threadsRes = client.threads.list(
    labels = ["unreplied"]
)
if threadsRes.count == 0:
    print("No threads need a reply.")
else:
    # Let's work on the first unreplied thread
    thread_to_reply_to = threadsRes.thread[0]
```

```typescript
// Find all threads in this inbox that are marked as unreplied
const threadRes = await client.threads.list(
    {
        labels: [
            "huh"
        ]
    }
)

if (threadRes.count === 0) {
    console.log("No threads need a reply.");
} else {
    // Let's work on the first unreplied thread
    const threadToReplyTo = threadRes.threads[0];
}
```

#### 2. Взять ID последнего сообщения в цепочке

Чтобы ответить в переписке, нужно ответить на *самое последнее сообщение* в цепочке. По ID цепочки можно получить объект с полным списком сообщений; ID нужного — у последнего сообщения в списке.

```python
# Get the full thread object to access its messages
thread_details = client.threads.get(thread_to_reply_to.thread_id)

# The last message in the list is the one we want to reply to
last_message = thread_details.messages[-1]
message_id_to_reply_to = last_message.message_id
```

```typescript
// Get the full thread object to access its messages
const threadDetails = await client.threads.get('thread_id');

// The last message in the array is the one we want to reply to
const lastMessage = threadDetails.messages[threadDetails.messages.length - 1];
const messageIdToReplyTo = lastMessage.message_id;
```

> **Tip**
>
> Используйте `last_message.extracted_text` (или `extracted_html`), если нужен
> только новый текст ответа без цитируемой истории.

#### 3. Отправить ответ и обновить метки

Когда есть `message_id`, можно отправить ответ агента. Хорошая практика — сразу обновить метки у исходного сообщения: снять `unreplied` и добавить `replied`, чтобы агент не ответил дважды на одно письмо.

```python
# Send the reply
client.inboxes.messages.reply(
    inbox_id="info@patternautomation.com",
    message_id=message_id_to_reply_to,
    text="This is our agent's helpful reply!"
)

# Update the labels on the original message
client.inboxes.messages.update(
    inbox_id="info@patternautomation.com",
    message_id=message_id_to_reply_to,
    add_labels=["replied"],
    remove_labels=["unreplied"]
)
```

```typescript
// Send the reply
await client.inboxes.messages.reply("info@patternautomation.com", messageIdToReplyTo, {
    text: "This is our agent's helpful reply!",
});

// Update the labels on the original message
await client.inboxes.messages.update("info@patternautomation.com", messageIdToReplyTo, {
    addLabels: ["replied"],
    removeLabels: ["unreplied"],
});
```

**`CLI`**

```bash title="CLI"
# send the reply
agentinbox inboxes:messages reply \
  --inbox-id info@patternautomation.com \
  --message-id <message_id> \
  --text "This is our agent's helpful reply!"

# update the labels on the original message
agentinbox inboxes:messages update \
  --inbox-id info@patternautomation.com \
  --message-id <message_id> \
  --add-label replied \
  --remove-label unreplied
```

> **Обработка в реальном времени через вебхуки**
>
> В продакшене опрос неэффективен. Надёжнее обрабатывать входящие ответы через вебхуки: Agent Inbox сразу уведомит агента о новом сообщении, и ответ можно строить в реальном времени.
>
> [**Как настроить вебхуки →**](/overview)

## Отложенная отправка

Вместо мгновенной отправки можно запланировать письмо на будущее — удобно для рабочих часов или равномерного аутрича.

Создайте черновик с полем `send_at` — дальше Agent Inbox отправит письмо в указанное время.

**`Python`**

```python title="Python"
from datetime import datetime, timedelta

# Schedule for tomorrow at 9 AM UTC
send_time = (datetime.utcnow() + timedelta(days=1)).replace(hour=9, minute=0, second=0)

client.inboxes.drafts.create(
    inbox_id="outreach@agentinbox.space",
    to=["prospect@example.com"],
    subject="Quick question about your workflow",
    text="Hi, I noticed you're using...",
    html="<p>Hi, I noticed you're using...</p>",
    send_at=send_time.isoformat() + "Z"
)
```

**`TypeScript`**

```typescript title="TypeScript"
// Schedule for tomorrow at 9 AM UTC
const sendTime = new Date();
sendTime.setUTCDate(sendTime.getUTCDate() + 1);
sendTime.setUTCHours(9, 0, 0, 0);

await client.inboxes.drafts.create(
    "outreach@agentinbox.space",
    {
        to: ["prospect@example.com"],
        subject: "Quick question about your workflow",
        text: "Hi, I noticed you're using...",
        html: "<p>Hi, I noticed you're using...</p>",
        sendAt: sendTime.toISOString()
    }
);
```

> **Info**
>
> Подробнее об отложенной отправке — отмена, перенос, список запланированных черновиков и условные напоминания — на странице [**Черновики**](/drafts).