I built a custom module with logic hooks to send SMS messages from Suitecrm. It uses an external service. Hope someone can find the code helpful. Iām fairly new to Suitecrm so might not be the most well written code, but it works!! Lots of logging to be helpfulā¦
text/x-generic send_sms_hook.php ( PHP script, ASCII text, with CRLF line terminators )
<?php
class SendSMSHook
{
public static function sms_log($message)
{
$logFile = 'custom/modules/CuSMS_SMS/sms_hook.log';
$date = date('Y-m-d H:i:s');
file_put_contents($logFile, "[$date] $message\n", FILE_APPEND);
}
public function sendSMS($bean, $event, $arguments)
{
self::sms_log("Hook triggered for record {$bean->id}");
if (!empty($bean->contact_id_c)) {
$contact = BeanFactory::getBean('Contacts', $bean->contact_id_c);
if ($contact && !empty($contact->phone_work)) {
$bean->phone_number_cs = $contact->phone_work;
self::sms_log("Auto-filled phone_number_cs from related contact: {$contact->phone_work}");
} else {
self::sms_log("Related contact found, but no phone_work field.");
}
} else {
self::sms_log("No contact_id_c found on record.");
}
if (!empty($bean->account_id_c)) {
$account = BeanFactory::getBean('Accounts', $bean->account_id_c);
if ($account && !empty($account->phone_office)) {
$bean->phone_number_cs = $account->phone_office;
self::sms_log("Auto-filled phone_number_cs from related account: {$account->phone_office}");
} else {
self::sms_log("Related account found, but no phone_office field.");
}
} else {
self::sms_log("No account_id_c found on record.");
}
$recipient = $bean->phone_number_cs;
$message = $bean->message_cs;
self::sms_log("Recipient phone number is '{$recipient}'");
if (empty($recipient)) {
self::sms_log("No recipient phone number on record {$bean->id}");
return;
}
$baseUrl = 'MYURL';
$deviceId = '';
$apiKey = 'APIKEY';
$url = $baseUrl . "gateway/devices/{$deviceId}/send-sms";
$data = json_encode([
'recipients' => [$recipient],
'message' => $message
]);
$headers = [
"x-api-key: $apiKey",
"Content-Type: application/json"
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
$error = curl_error($ch);
curl_close($ch);
if ($error) {
self::sms_log("cURL error sending SMS: $error");
} else {
self::sms_log("SMS sent successfully to $recipient. Response: $response");
}
}
public function sendBulkSMSFromTargetList($bean, $message)
{
$targetListName = $bean->target_list_id_c;
self::sms_log("Target List Name (from target_list_id_c): {$targetListName}");
if (empty($targetListName)) {
self::sms_log("No target list name set in the SMS record.");
return;
}
$targetListBean = BeanFactory::newBean('ProspectLists');
$targetListBeanList = $targetListBean->get_full_list("name", "name = '{$targetListName}'");
if (empty($targetListBeanList)) {
self::sms_log("No ProspectList found with name: {$targetListName}");
return;
}
$targetListBean = $targetListBeanList[0];
self::sms_log("Found Target List: {$targetListBean->name} (ID: {$targetListBean->id})");
$contactIds = [];
if ($targetListBean->load_relationship('prospects')) {
$prospects = $targetListBean->prospects->getBeans();
self::sms_log("Retrieved " . count($prospects) . " prospects.");
foreach ($prospects as $prospect) {
if (!empty($prospect->phone_work)) {
$contactIds[] = ['id' => $prospect->id, 'type' => 'Prospect', 'number' => $prospect->phone_work];
} else {
self::sms_log("Prospect {$prospect->id} has no phone_work number.");
}
}
} else {
self::sms_log("Failed to load 'prospects' relationship on target list.");
}
if ($targetListBean->load_relationship('contacts')) {
$contacts = $targetListBean->contacts->getBeans();
self::sms_log("Retrieved " . count($contacts) . " contacts.");
foreach ($contacts as $contact) {
if (!empty($contact->phone_work)) {
$contactIds[] = ['id' => $contact->id, 'type' => 'Contact', 'number' => $contact->phone_work];
} else {
self::sms_log("Contact {$contact->id} has no phone_work number.");
}
}
} else {
self::sms_log("Failed to load 'contacts' relationship on target list.");
}
if ($targetListBean->load_relationship('leads')) {
$leads = $targetListBean->leads->getBeans();
self::sms_log("Retrieved " . count($leads) . " leads.");
foreach ($leads as $lead) {
if (!empty($lead->phone_work)) {
$contactIds[] = ['id' => $lead->id, 'type' => 'Lead', 'number' => $lead->phone_work];
} else {
self::sms_log("Lead {$lead->id} has no phone_work number.");
}
}
} else {
self::sms_log("Failed to load 'leads' relationship on target list.");
}
self::sms_log("Total contacts to send SMS to: " . count($contactIds));
foreach ($contactIds as $entry) {
self::sms_log("Sending SMS to {$entry['type']} ID {$entry['id']} at {$entry['number']}");
$this->sendSingleSMS($entry['number'], $message);
}
self::sms_log("=== Bulk SMS processing complete ===");
}
public function sendSingleSMS($phoneNumber, $message)
{
self::sms_log("Preparing to send SMS to {$phoneNumber}");
$baseUrl = '';
$deviceId = '';
$apiKey = '';
$url = $baseUrl . "gateway/devices/{$deviceId}/send-sms";
$data = json_encode([
'recipients' => [$phoneNumber],
'message' => $message
]);
$headers = [
"x-api-key: $apiKey",
"Content-Type: application/json"
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
$error = curl_error($ch);
curl_close($ch);
if ($error) {
self::sms_log("cURL error sending SMS: $error");
} else {
self::sms_log("SMS sent successfully to {$phoneNumber}. Response: {$response}");
}
}
}

