При разработке и поддержке проектов на платформе 1С-Битрикс критически важно использовать современные стандарты D7 API. В этом руководстве мы детально изучим тему «Как отправить письмо клиенту от имени сотрудника», разберем архитектурные особенности и предоставим готовые к интеграции примеры кода.
Как отправить письмо клиенту от имени сотрудника
> Scope: crm
>
> Кто может выполнять метод: пользователи с правом на изменение элемента CRM
Письмо клиенту можно отправить автоматически через CRM. В поле «От кого» будут указаны имя и адрес электронной почты сотрудника. В карточке контакта добавится событие для исходящего письма.
Чтобы отправить письмо, последовательно выполним три метода:
1. crm.contact.get — получим данные клиента
2. user.get— получим данные сотрудника
3. crm.activity.add — создадим дело типа «Письмо»
1\. Получим данные клиента
Используем метод crm.contact.get с идентификатором клиента. Значение идентификатора можно предварительно сохранить в переменной contactID. Например, получим данные контакта с идентификатором 1.
- JS
let contactID = 1;
BX24.callMethod(
'crm.contact.get',
{ 'id': contactID },
function(result) {
if (result.error()) {
reject(result.error());
} else {
resolve(result.data());
}
}
);- PHP
$contactID = 1;
$resultContact = CRest::call(
'crm.contact.get',
[
'id' => $contactID
]
);В результате получим данные клиента, включая адрес электронной почты 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.
- JS
BX24.callMethod(
'user.get',
{
'filter': {
'ID': resultContact.ASSIGNED_BY_ID
}
},
function(result) {
if (result.error()) {
reject(result.error());
} else {
resolve(result.data());
}
}
);- PHP
{
$resultUser = CRest::call(
'user.get',
[
'filter' => [
'ID' => $resultContact['result']['ASSIGNED_BY_ID']
]
]
);
}Получим данные сотрудника, включая адрес электронной почты EMAIL.
{
"result": [
{
"ID": "61",
"ACTIVE": true,
"NAME": "Иван",
"LAST_NAME": "Петров",
"EMAIL": "ivanpetrov@example.ru"
}
]
}3\. Создадим дело типа «Письмо»
Подготовим переменные:
contactEmail— первый элемент из контактаresultContact,
staff— первый элемент из объектаresultUser.
- JS
let contactEmail = resultContact.EMAIL[0];
let staff = resultUser[0];- PHP
$contactEmail = reset($resultContact['result']['EMAIL']);
$staff = reset($resultUser['result']);Чтобы добавить событие и отправить письмо, используем метод 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сотрудника.
- JS
BX24.callMethod(
'crm.activity.add',
{
'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}>`
}
}
}
); - PHP
$resultActivity = CRest::call(
'crm.activity.add',
[
'fields' => [
"SUBJECT" => "subject email now",
"DESCRIPTION" => "body email now",
"DESCRIPTION_TYPE" => 3,//text,html,bbCode type id in: CRest::call('crm.enum.contenttype');
"COMPLETED" => "Y",//send now
"DIRECTION" => 2,// CRest::call('crm.enum.activitydirection');
"OWNER_ID" => $contactID,
"OWNER_TYPE_ID" => 3, // CRest::call('crm.enum.ownertype');
"TYPE_ID" => 4, // CRest::call('crm.enum.activitytype');
"COMMUNICATIONS" => [
[
'VALUE' => $contactEmail['VALUE'],
'ENTITY_ID' => $contactID,
'ENTITY_TYPE_ID' => 3// CRest::call('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'] . '>']
),
],
]
]
);Если событие создано успешно, метод вернет его идентификатор. Если вы получили ошибку error, изучите описание возможных ошибок в документации метода crm.activity.add.
{
"result": 3165,
}Полный пример кода
Код в примере объединяет все шаги: получает данные клиента и сотрудника, добавляет дело «Письмо» и отправляет письмо клиенту.
- JS
document.addEventListener('DOMContentLoaded', function() {
async function createEmailActivityForContact() {
try {
let contactID = 1;
let resultContact = await new Promise((resolve, reject) => {
BX24.callMethod(
'crm.contact.get',
{ 'id': contactID },
function(result) {
if (result.error()) {
reject(result.error());
} else {
resolve(result.data());
}
}
);
});
if (resultContact && resultContact.ASSIGNED_BY_ID && resultContact.EMAIL) {
let resultUser = await new Promise((resolve, reject) => {
BX24.callMethod(
'user.get',
{
'filter': {
'ID': resultContact.ASSIGNED_BY_ID
}
},
function(result) {
if (result.error()) {
reject(result.error());
} else {
resolve(result.data());
}
}
);
});
if (resultUser.length > 0) {
let contactEmail = resultContact.EMAIL[0];
let staff = resultUser[0];
if (contactEmail.VALUE && staff.EMAIL) {
let resultActivity = await new Promise((resolve, reject) => {
BX24.callMethod(
'crm.activity.add',
{
'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}>`
}
}
},
function(result) {
if (result.error()) {
reject(result.error());
} else {
resolve(result.data());
}
}
);
});
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
<?
$contactID = 1;
$resultContact = CRest::call(
'crm.contact.get',
[
'id' => $contactID
]
);
$resultActivity = [];
if (!empty($resultContact['result']['ASSIGNED_BY_ID']) && !empty($resultContact['result']['EMAIL']))
{
$resultUser = CRest::call(
'user.get',
[
'filter' => [
'ID' => $resultContact['result']['ASSIGNED_BY_ID']
]
]
);
if ($resultUser['result'])
{
$contactEmail = reset($resultContact['result']['EMAIL']);
$staff = reset($resultUser['result']);
if (!empty($contactEmail['VALUE']) && !empty($staff['EMAIL']))
{
$resultActivity = CRest::call(
'crm.activity.add',
[
'fields' => [
"SUBJECT" => "subject email now",
"DESCRIPTION" => "body email now",
"DESCRIPTION_TYPE" => 3,//text,html,bbCode type id in: CRest::call('crm.enum.contenttype');
"COMPLETED" => "Y",//send now
"DIRECTION" => 2,// CRest::call('crm.enum.activitydirection');
"OWNER_ID" => $contactID,
"OWNER_TYPE_ID" => 3, // CRest::call('crm.enum.ownertype');
"TYPE_ID" => 4, // CRest::call('crm.enum.activitytype');
"COMMUNICATIONS" => [
[
'VALUE' => $contactEmail['VALUE'],
'ENTITY_ID' => $contactID,
'ENTITY_TYPE_ID' => 3// CRest::call('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'] . '>']
),
],
]
]
);
}
}
}
if (!empty($resultActivity['result']))
{
echo json_encode(['message' => 'Activity add']);
}
elseif (!empty($resultActivity['error_description']))
{
echo json_encode(['message' => 'Activity not added: ' . $resultActivity['error_description']]);
}
else
{
echo json_encode(['message' => 'Activity not added']);
}
?>💡 Экспертное мнение и рекомендации
Практические рекомендации:
- При написании кастомных компонентов для «Как отправить письмо клиенту от имени сотрудника» всегда разделяйте бизнес-логику и представление (шаблон).
- Используйте отладку SQL-запросов через конструкцию
$wpdb->last_queryили стандартный трекер Битрикса, чтобы контролировать нагрузку.
Похожая задача в бизнесе?
Помогу автоматизировать процессы и внедрить ИИ
Меня зовут Андрей Горошко. Я Full-stack разработчик и эксперт по 1С-Битрикс. Настраиваю CRM Битрикс24, разрабатываю защищенные API и создаю умных ИИ-агентов для автоматизации рутины.
или на почту: gorandvas@yandex.ru