Как отправить письмо клиенту от имени сотрудника

Scope: crm

Кто может выполнять метод: пользователи с правом на изменение элемента CRM

Выберите инструмент для разработки с AI-агентом:

  • используйте Битрикс24 Вайбкод, чтобы создать приложение для Битрикс24 по описанию задачи без знания языков программирования. Агент напишет код и разместит приложение на сервере без ручной настройки хостинга
  • используйте MCP-сервер, чтобы разрабатывать интеграцию через REST API в своем проекте. Агент будет обращаться к официальной REST-документации

Письмо клиенту можно отправить автоматически через CRM. В поле «От кого» будут указаны имя и адрес электронной почты сотрудника. В карточке контакта добавится событие для исходящего письма.

Чтобы отправить письмо, последовательно выполним три метода:

  1. crm.contact.get — получим данные клиента

  2. user.get— получим данные сотрудника

  3. crm.activity.add — создадим дело типа «Письмо»

1. Получим данные клиента

Используем метод crm.contact.get с идентификатором клиента. Значение идентификатора можно предварительно сохранить в переменной contactID. Например, получим данные контакта с идентификатором 1.

Как использовать примеры в документации

import { B24Hook } from '@bitrix24/b24jssdk'
        
        const $b24 = B24Hook.fromWebhookUrl(process.env.B24_HOOK)
        // B24_HOOK = 'https://your-domain.bitrix24.ru/rest/USER_ID/TOKEN/'
        
        let contactID = 1;
        const response = await $b24.actions.v2.call.make({
            method: 'crm.contact.get',
            params: { id: contactID },
            requestId: 'contact-get'
        })
        let resultContact = response.getData().result
        
$contactID = 1;
        $resultContact = $sb->getCRMScope()->contact()->get($contactID)->contact();
        
from b24pysdk import BitrixWebhook, Client
        
        client = Client(
            BitrixWebhook(
                domain="your-domain.bitrix24.com",
                webhook_token="user_id/webhook_key",
            )
        )
        
        contact_id = 1
        result_contact = client.crm.contact.get(
            bitrix_id=contact_id,
        ).response.result
        

В результате получим данные клиента, включая адрес электронной почты EMAIL и идентификатор ответственного сотрудника ASSIGNED_BY_ID.

{
            "result": {
                "ID": "1",
                "NAME": "Алексей",
                "SECOND_NAME": "Кириллович",
                "LAST_NAME": "Вронский",
                "ASSIGNED_BY_ID": "61",
                "EMAIL": [
                    {
                        "ID": "1328",
                        "VALUE_TYPE": "WORK",
                        "VALUE": "vronsky@example.ru",
                        "TYPE_ID": "EMAIL"
                    }
                ]
            } 
        }
        

2. Получим данные сотрудника

Чтобы получить данные ответственного сотрудника, используем метод user.get с фильтром по идентификатору сотрудника. Идентификатор должен принимать значение из поля ASSIGNED_BY_ID объекта resultContact.

const responseUser = await $b24.actions.v2.call.make({
            method: 'user.get',
            params: {
                filter: {
                    ID: resultContact.ASSIGNED_BY_ID
                }
            },
            requestId: 'user-get'
        })
        let resultUser = responseUser.getData().result
        
$resultUser = $sb->getUserScope()->user()->get(
            [],
            ['ID' => $resultContact->ASSIGNED_BY_ID]
        )->getUsers();
        
result_user = client.user.get(
            filter={
                "ID": result_contact["ASSIGNED_BY_ID"],
            }
        ).response.result
        

Получим данные сотрудника, включая адрес электронной почты EMAIL.

{
            "result": [
                {
                "ID": "61",
                "ACTIVE": true,
                "NAME": "Иван",
                "LAST_NAME": "Петров",
                "EMAIL": "ivanpetrov@example.ru"
                }
            ]
        }
        

3. Создадим дело типа «Письмо»

Подготовим переменные:

  • contactEmail — первый элемент из контакта resultContact,

  • staff — первый элемент из объекта resultUser.

    let contactEmail = resultContact.EMAIL[0];
            let staff = resultUser[0];
        
    $emails = $resultContact->EMAIL;
            $contactEmail = reset($emails);
            $staff = reset($resultUser);
        
contact_email = result_contact["EMAIL"][0]
        staff = result_user[0]
        

Чтобы добавить событие и отправить письмо, используем метод crm.activity.add. В него нужно передать данные клиента, сотрудника и параметры дела.

  • SUBJECT — тема письма. Укажем subject email now.

  • DESCRIPTION — текст письма. Например, body email now.

  • DESCRIPTION_TYPE — тип текста. Возможные значения: 1— обычный текст, 2— HTML-разметка, 3— BB-код. Зададим значение 3.

  • COMPLETED — флаг показывает, завершено ли событие. Укажем Y.

  • DIRECTION — направление активности. Передаем 2 — исходящее письмо. Полный список направлений активности можно получить с помощью метода crm.enum.activitydirection.

  • OWNER_ID — идентификатор контакта. Передаем переменную contactID.

  • OWNER_TYPE_IDидентификатор типа объекта CRM. Передаем 3— контакт. Полный список типов объектов можно получить с помощью метода crm.enum.ownertype.

  • TYPE_ID — тип активности. Укажем 4 — письмо. Список типов активности можно получить с помощью метода crm.enum.activitytype.

  • COMMUNICATIONS — контактные данные клиента:

    • VALUE — адрес электронной почты, берем значение VALUE из массива contactEmail,

    • ENTITY_ID — идентификатор клиента, передаем contactID,

    • ENTITY_TYPE_IDидентификатор типа объекта, передаем 3 — контакт.

  • START_TIME и END_TIME — дата и время начала и окончания активности. Укажем длительность 1 час.

  • RESPONSIBLE_ID — идентификатор ответственного, передаем staff.ID.

  • SETTINGS — дополнительные настройки:

    • MESSAGE_FROM — отправитель письма, передаем имя staff.NAME, фамилию staff.LAST_NAME и адрес электронной почты staff.EMAIL сотрудника.
const responseActivity = await $b24.actions.v2.call.make({
            method: 'crm.activity.add',
            params: {
                fields: {
                    "SUBJECT": "subject email now",
                    "DESCRIPTION": "body email now",
                    "DESCRIPTION_TYPE": 3,
                    "COMPLETED": "Y",
                    "DIRECTION": 2,
                    "OWNER_ID": contactID,
                    "OWNER_TYPE_ID": 3,
                    "TYPE_ID": 4,
                    "COMMUNICATIONS": [
                        {
                            'VALUE': contactEmail.VALUE,
                            'ENTITY_ID': contactID,
                            'ENTITY_TYPE_ID': 3
                        }
                    ],
                    "START_TIME": new Date().toISOString(),
                    "END_TIME": new Date(Date.now() + 3600 * 1000).toISOString(),
                    "RESPONSIBLE_ID": staff.ID,
                    'SETTINGS': {
                        'MESSAGE_FROM': `${staff.NAME} ${staff.LAST_NAME} <${staff.EMAIL}>`
                    }
                }
            },
            requestId: 'activity-add'
        });
        
$resultActivity = $sb->getCRMScope()->activity()->add(
            [
                "SUBJECT" => "subject email now",
                "DESCRIPTION" => "body email now",
                "DESCRIPTION_TYPE" => 3,// тип текста (crm.enum.contenttype): обычный, HTML, BB-код
                "COMPLETED" => "Y",// отправить сейчас
                "DIRECTION" => 2,// crm.enum.activitydirection
                "OWNER_ID" => $contactID,
                "OWNER_TYPE_ID" => 3, // crm.enum.ownertype
                "TYPE_ID" => 4, // crm.enum.activitytype
                "COMMUNICATIONS" => [
                    [
                        'VALUE' => $contactEmail->VALUE,
                        'ENTITY_ID' => $contactID,
                        'ENTITY_TYPE_ID' => 3// crm.enum.ownertype
                    ]
                ],
                "START_TIME" => date("Y-m-d H:i:s", time()),
                "END_TIME" => date("Y-m-d H:i:s", time() + 3600),
                "RESPONSIBLE_ID" => $staff->ID,
                'SETTINGS' => [
                    'MESSAGE_FROM' => implode(
                        ' ',
                        [$staff->NAME, $staff->LAST_NAME, '<' . $staff->EMAIL . '>']
                    ),
                ],
            ]
        )->getId();
        
from datetime import datetime, timedelta
        
        contact_email = result_contact["EMAIL"][0]
        staff = result_user[0]
        now = datetime.now()
        
        result_activity = client.crm.activity.add(
            fields={
                "SUBJECT": "subject email now",
                "DESCRIPTION": "body email now",
                "DESCRIPTION_TYPE": 3,
                "COMPLETED": "Y",
                "DIRECTION": 2,
                "OWNER_ID": contact_id,
                "OWNER_TYPE_ID": 3,
                "TYPE_ID": 4,
                "COMMUNICATIONS": [
                    {
                        "VALUE": contact_email["VALUE"],
                        "ENTITY_ID": contact_id,
                        "ENTITY_TYPE_ID": 3,
                    }
                ],
                "START_TIME": now.isoformat(timespec="seconds"),
                "END_TIME": (now + timedelta(hours=1)).isoformat(timespec="seconds"),
                "RESPONSIBLE_ID": staff["ID"],
                "SETTINGS": {
                    "MESSAGE_FROM": f"{staff['NAME']} {staff['LAST_NAME']} <{staff['EMAIL']}>"
                },
            }
        ).response.result
        

Если событие создано успешно, метод вернет его идентификатор. Если вы получили ошибку error, изучите описание возможных ошибок в документации метода crm.activity.add.

{
            "result": 3165,
        }
        

Полный пример кода

Код в примере объединяет все шаги: получает данные клиента и сотрудника, добавляет дело «Письмо» и отправляет письмо клиенту.

import { B24Hook } from '@bitrix24/b24jssdk'
        
        const $b24 = B24Hook.fromWebhookUrl(process.env.B24_HOOK)
        // B24_HOOK = 'https://your-domain.bitrix24.ru/rest/USER_ID/TOKEN/'
        
        async function createEmailActivityForContact() {
            try {
                let contactID = 1;
        
                const responseContact = await $b24.actions.v2.call.make({
                    method: 'crm.contact.get',
                    params: { id: contactID },
                    requestId: 'contact-get'
                });
                let resultContact = responseContact.getData().result;
        
                if (resultContact && resultContact.ASSIGNED_BY_ID && resultContact.EMAIL) {
                    const responseUser = await $b24.actions.v2.call.make({
                        method: 'user.get',
                        params: { filter: { ID: resultContact.ASSIGNED_BY_ID } },
                        requestId: 'user-get'
                    });
                    let resultUser = responseUser.getData().result;
        
                    if (resultUser.length > 0) {
                        let contactEmail = resultContact.EMAIL[0];
                        let staff = resultUser[0];
        
                        if (contactEmail.VALUE && staff.EMAIL) {
                            const responseActivity = await $b24.actions.v2.call.make({
                                method: 'crm.activity.add',
                                params: {
                                    fields: {
                                        "SUBJECT": "subject email now",
                                        "DESCRIPTION": "body email now",
                                        "DESCRIPTION_TYPE": 3,
                                        "COMPLETED": "Y",
                                        "DIRECTION": 2,
                                        "OWNER_ID": contactID,
                                        "OWNER_TYPE_ID": 3,
                                        "TYPE_ID": 4,
                                        "COMMUNICATIONS": [
                                            {
                                                'VALUE': contactEmail.VALUE,
                                                'ENTITY_ID': contactID,
                                                'ENTITY_TYPE_ID': 3
                                            }
                                        ],
                                        "START_TIME": new Date().toISOString(),
                                        "END_TIME": new Date(Date.now() + 3600 * 1000).toISOString(),
                                        "RESPONSIBLE_ID": staff.ID,
                                        'SETTINGS': {
                                            'MESSAGE_FROM': `${staff.NAME} ${staff.LAST_NAME} <${staff.EMAIL}>`
                                        }
                                    }
                                },
                                requestId: 'activity-add'
                            });
                            let resultActivity = responseActivity.getData().result;
        
                            if (resultActivity) {
                                console.log(JSON.stringify({ 'message': 'Activity added' }));
                            } else {
                                console.log(JSON.stringify({ 'message': 'Activity not added' }));
                            }
                        }
                    }
                }
            } catch (error) {
                console.error(error);
                console.log(JSON.stringify({ 'message': 'Activity not added: ' + error.message }));
            }
        }
        
        createEmailActivityForContact();
        
<?php
        // composer require bitrix24/b24phpsdk:"^3.0"
        require_once 'vendor/autoload.php';
        
        use Bitrix24\SDK\Services\ServiceBuilderFactory;
        use Symfony\Component\EventDispatcher\EventDispatcher;
        use Psr\Log\NullLogger;
        
        $sb = (new ServiceBuilderFactory(new EventDispatcher(), new NullLogger()))
            ->initFromWebhook('https://your-domain.bitrix24.ru/rest/USER_ID/TOKEN/');
        
        $contactID = 1;
        try {
            $resultContact = $sb->getCRMScope()->contact()->get($contactID)->contact();
            $resultActivity = null;
            if (!empty($resultContact->ASSIGNED_BY_ID) && !empty($resultContact->EMAIL))
            {
                $resultUser = $sb->getUserScope()->user()->get(
                    [],
                    ['ID' => $resultContact->ASSIGNED_BY_ID]
                )->getUsers();
                if ($resultUser)
                {
                    $emails = $resultContact->EMAIL;
                    $contactEmail = reset($emails);
                    $staff = reset($resultUser);
                    if (!empty($contactEmail->VALUE) && !empty($staff->EMAIL))
                    {
                        $resultActivity = $sb->getCRMScope()->activity()->add(
                            [
                                "SUBJECT" => "subject email now",
                                "DESCRIPTION" => "body email now",
                                "DESCRIPTION_TYPE" => 3,// тип текста (crm.enum.contenttype): обычный, HTML, BB-код
                                "COMPLETED" => "Y",// отправить сейчас
                                "DIRECTION" => 2,// crm.enum.activitydirection
                                "OWNER_ID" => $contactID,
                                "OWNER_TYPE_ID" => 3, // crm.enum.ownertype
                                "TYPE_ID" => 4, // crm.enum.activitytype
                                "COMMUNICATIONS" => [
                                    [
                                        'VALUE' => $contactEmail->VALUE,
                                        'ENTITY_ID' => $contactID,
                                        'ENTITY_TYPE_ID' => 3// crm.enum.ownertype
                                    ]
                                ],
                                "START_TIME" => date("Y-m-d H:i:s", time()),
                                "END_TIME" => date("Y-m-d H:i:s", time() + 3600),
                                "RESPONSIBLE_ID" => $staff->ID,
                                'SETTINGS' => [
                                    'MESSAGE_FROM' => implode(
                                        ' ',
                                        [$staff->NAME, $staff->LAST_NAME, '<' . $staff->EMAIL . '>']
                                    ),
                                ],
                            ]
                        )->getId();
                    }
                }
            }
            if (!empty($resultActivity))
            {
                echo json_encode(['message' => 'Activity add']);
            }
            else
            {
                echo json_encode(['message' => 'Activity not added']);
            }
        } catch (\Throwable $e) {
            echo json_encode(['message' => 'Activity not added: ' . $e->getMessage()]);
        }
        
from datetime import datetime, timedelta
        
        from b24pysdk import BitrixWebhook, Client
        from b24pysdk.errors import BitrixAPIError
        
        client = Client(
            BitrixWebhook(
                domain="your-domain.bitrix24.com",
                webhook_token="user_id/webhook_key",
            )
        )
        
        contact_id = 1
        
        try:
            contact = client.crm.contact.get(bitrix_id=contact_id).response.result
            result_activity = None
        
            if contact.get("ASSIGNED_BY_ID") and contact.get("EMAIL"):
                result_user = client.user.get(
                    filter={"ID": contact["ASSIGNED_BY_ID"]},
                ).response.result
        
                if result_user:
                    contact_email = contact["EMAIL"][0]
                    staff = result_user[0]
        
                    if contact_email.get("VALUE") and staff.get("EMAIL"):
                        now = datetime.now()
                        result_activity = client.crm.activity.add(
                            fields={
                                "SUBJECT": "subject email now",
                                "DESCRIPTION": "body email now",
                                "DESCRIPTION_TYPE": 3,
                                "COMPLETED": "Y",
                                "DIRECTION": 2,
                                "OWNER_ID": contact_id,
                                "OWNER_TYPE_ID": 3,
                                "TYPE_ID": 4,
                                "COMMUNICATIONS": [
                                    {
                                        "VALUE": contact_email["VALUE"],
                                        "ENTITY_ID": contact_id,
                                        "ENTITY_TYPE_ID": 3,
                                    }
                                ],
                                "START_TIME": now.isoformat(timespec="seconds"),
                                "END_TIME": (now + timedelta(hours=1)).isoformat(timespec="seconds"),
                                "RESPONSIBLE_ID": staff["ID"],
                                "SETTINGS": {
                                    "MESSAGE_FROM": f"{staff['NAME']} {staff['LAST_NAME']} <{staff['EMAIL']}>"
                                },
                            }
                        ).response.result
        
            if result_activity:
                print({"message": "Activity add"})
            else:
                print({"message": "Activity not added"})
        except BitrixAPIError as error:
            print({"message": f"Activity not added: {error}"})