How to Send an E-mail to a Client on Behalf of an Employee
Scope:
crmWho can execute the method: users with permission to modify a CRM entity
If you are developing integrations for Bitrix24 using AI tools (Codex, Claude Code, Cursor), connect to the MCP server so that the assistant can utilize the official REST documentation.
You can automatically send an e-mail to a client through the CRM. The "From" field will display the name and e-mail address of the employee. An event for the outgoing e-mail will be added to the contact card.
To send the e-mail, we will sequentially execute three methods:
-
crm.contact.get — retrieve client data
-
user.get — retrieve employee data
-
crm.activity.add — create a deal of type "E-mail"
1. Retrieve Client Data
We will use the crm.contact.get method with the client ID. The ID value can be stored in the variable contactID. For example, we will retrieve the contact data with the ID 1.
How to Use Examples in Documentation
let contactID = 1;
BX24.callMethod(
'crm.contact.get',
{ 'id': contactID },
function(result) {
if (result.error()) {
reject(result.error());
} else {
resolve(result.data());
}
}
);
$contactID = 1;
$resultContact = CRest::call(
'crm.contact.get',
[
'id' => $contactID
]
);
As a result, we will obtain client data, including the e-mail address EMAIL and the ID of the responsible employee ASSIGNED_BY_ID.
{
"result": {
"ID": "1",
"NAME": "Alex",
"SECOND_NAME": "Kirillovich",
"LAST_NAME": "Vronsky",
"ASSIGNED_BY_ID": "61",
"EMAIL": [
{
"ID": "1328",
"VALUE_TYPE": "WORK",
"VALUE": "vronsky@example.com",
"TYPE_ID": "EMAIL"
}
]
}
}
2. Retrieve Employee Data
To get the data of the responsible employee, we will use the user.get method with a filter by employee ID. The ID should take the value from the ASSIGNED_BY_ID field of the resultContact object.
BX24.callMethod(
'user.get',
{
'filter': {
'ID': resultContact.ASSIGNED_BY_ID
}
},
function(result) {
if (result.error()) {
reject(result.error());
} else {
resolve(result.data());
}
}
);
{
$resultUser = CRest::call(
'user.get',
[
'filter' => [
'ID' => $resultContact['result']['ASSIGNED_BY_ID']
]
]
);
}
We will obtain employee data, including the e-mail address EMAIL.
{
"result": [
{
"ID": "61",
"ACTIVE": true,
"NAME": "Ivan",
"LAST_NAME": "Petrov",
"EMAIL": "ivanpetrov@example.com"
}
]
}
3. Create a Deal of Type "E-mail"
We will prepare the variables:
-
contactEmail— the first element from the contactresultContact, -
staff— the first element from theresultUserobject.
let contactEmail = resultContact.EMAIL[0];
let staff = resultUser[0];
$contactEmail = reset($resultContact['result']['EMAIL']);
$staff = reset($resultUser['result']);
To add the event and send the e-mail, we will use the crm.activity.add method. We need to pass the client data, employee data, and deal parameters.
-
SUBJECT— the subject of the e-mail. We will specifysubject email now. -
DESCRIPTION— the body of the e-mail. For example,body email now. -
DESCRIPTION_TYPE— the text type. Possible values:1— plain text,2— HTML markup,3— BB-code. We will set the value to3. -
COMPLETED— a flag indicating whether the event is completed. We will specifyY. -
DIRECTION— the direction of the activity. We will pass2— outgoing e-mail. A complete list of activity directions can be obtained using the crm.enum.activitydirection method. -
OWNER_ID— the contact ID. We will pass the variablecontactID. -
OWNER_TYPE_ID— the identifier of the CRM object type. We will pass3— contact. A complete list of object types can be obtained using the crm.enum.ownertype method. -
TYPE_ID— the activity type. We will specify4— e-mail. A list of activity types can be obtained using the crm.enum.activitytype method. -
COMMUNICATIONS— the client's contact details:-
VALUE— the e-mail address, we will take theVALUEfrom thecontactEmailarray, -
ENTITY_ID— the client ID, we will passcontactID, -
ENTITY_TYPE_ID— the identifier of the object type, we will pass3— contact.
-
-
START_TIMEandEND_TIME— the start and end date and time of the activity. We will specify a duration of 1 hour. -
RESPONSIBLE_ID— the ID of the responsible person, we will passstaff.ID. -
SETTINGS— additional settings:MESSAGE_FROM— the sender of the e-mail, we will pass the namestaff.NAME, last namestaff.LAST_NAME, and e-mail addressstaff.EMAILof the employee.
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}>`
}
}
}
);
$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 the event is created successfully, the method will return its ID. If you receive an error, refer to the documentation for the crm.activity.add method to understand possible errors.
{
"result": 3165,
}
Complete Code Example
The code in this example combines all steps: it retrieves client and employee data, adds the "E-mail" deal, and sends the e-mail to the client.
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 added']);
}
elseif (!empty($resultActivity['error_description']))
{
echo json_encode(['message' => 'Activity not added: ' . $resultActivity['error_description']]);
}
else
{
echo json_encode(['message' => 'Activity not added']);
}
?>