SMS Providers

Collapse
This is a sticky topic.
X
X
 
  • Time
  • Show
Clear All
new posts
  • mkas
    Junior Member
    • Feb 2021
    • 26

    #16
    Originally posted by Kyle
    2FA can send SMS
    Formula
    or write some code

    There is no user ability to send an SMS
    Awesome, thanks.

    Comment

    • Kritika
      Junior Member
      • May 2022
      • 14

      #17
      Hello. can you add a provider?
      SMS Центр – сервис для отправки и приема SMS-сообщений, EMS и бинарные SMS, E-mail2sms, HLR, MMS, Voice, E-mail рассылки и другое. Гарантированная доставка сообщений по всему миру, удобные тарифы и API-интеграция.

      Comment

      • Dozent
        Junior Member
        • Oct 2022
        • 8

        #18
        Hi. You can do provider integration RocketSMS. He has an API

        Comment

        • axyl
          Member
          • Jun 2021
          • 37

          #19
          I created an extension, which uses the SMS Providers Extension to let users send SMS from Contacts, etc.

          Forum post is here.
          Hey Everyone, I needed a way to let staff send ad-hoc SMS's when looking at contacts and some custom Entities. I've created that as an extension and put it on Github if anyone else wants to use it or use it as a base for their own tweaks. We use this with branded SMS's, so I didn't need to handle replies. Code is here -

          Comment

          • robson
            Junior Member
            • May 2019
            • 24

            #20
            SMSPlanet integration for EspoCRM (custom provider + GSM normalization)


            SMS Plante can send worldwide. I use it for Poland.

            I’ve implemented a working SMSPlanet provider for EspoCRM SMS extension and wanted to share it with the community. yuri please add to the repo if it makes sense for you

            This solution:
            • integrates with SMSPlanet API
            • supports Bearer token or key/password auth
            • forces GSM-7 encoding (removes Polish diacritics & smart characters → avoids 70-char SMS limit)
            • sets fixed sender: SSkladki.pl
            • works with Formula (ext\sms\send) and automations
            Features
            • SMSPlanet API (https://api2.smsplanet.pl/sms)
            • GSM normalization (ą→a, ę→e, etc.)
            • Handles Word/Outlook characters (quotes, dashes, etc.)
            • Multipart detection (logs segments)
            • Works with EspoCRM Sms entity
            • Production tested
            File


            Create:
            custom/Espo/Modules/SmsProviders/SmsPlanet/SmsPlanetSender.php Full code:

            <?php

            namespace Espo\Modules\SmsProviders\SmsPlanet;

            use Espo\Core\Exceptions\Error;
            use Espo\Core\Sms\Sender;
            use Espo\Core\Sms\Sms;
            use Espo\Core\Utils\Config;
            use Espo\Core\Utils\Log;
            use Espo\Core\Utils\Metadata;
            use Espo\Entities\Integration;
            use Espo\ORM\EntityManager;

            class SmsPlanetSender implements Sender
            {
            private const BASE_URL = 'https://api2.smsplanet.pl';
            private const TIMEOUT = 30;
            private const FROM_NAME = 'SSkladki.pl';
            private const FORCE_ASCII = true;

            private Config $config;
            private EntityManager $entityManager;
            private Log $log;
            private Metadata $metadata;

            public function __construct(
            Config $config,
            EntityManager $entityManager,
            Log $log,
            Metadata $metadata
            ) {
            $this->config = $config;
            $this->entityManager = $entityManager;
            $this->log = $log;
            $this->metadata = $metadata;
            }

            public function send(Sms $sms): void
            {
            foreach ($sms->getToNumberList() as $number) {
            $this->sendToNumber($sms, $number);
            }
            }

            private function sendToNumber(Sms $sms, string $toNumber): void
            {
            $integration = $this->entityManager
            ->getEntity(Integration::ENTITY_TYPE, 'SmsPlanet');

            if (!$integration || !$integration->get('enabled')) {
            throw new Error('SmsPlanet integration not enabled.');
            }

            $token = $integration->get('smsPlanetToken');

            if (!$token) {
            throw new Error('SmsPlanet: API token required.');
            }

            $body = $sms->getBody();

            if (self::FORCE_ASCII) {
            $body = self::normalizeToGsm7($body);
            }

            $to = self::formatNumber($toNumber);

            $params = http_build_query([
            'from' => self::FROM_NAME,
            'to' => $to,
            'msg' => $body,
            ]);

            $ch = curl_init(self::BASE_URL . '/sms');

            curl_setopt_array($ch, [
            CURLOPT_POST => true,
            CURLOPT_POSTFIELDS => $params,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_HTTPHEADER => [
            'Authorization: Bearer ' . $token,
            'Content-Type: application/x-www-form-urlencoded',
            ]
            ]);

            $response = curl_exec($ch);
            $error = curl_errno($ch);
            $status = curl_getinfo($ch, CURLINFO_HTTP_CODE);

            curl_close($ch);

            if ($error) {
            throw new Error('SmsPlanet cURL error');
            }

            if ($status !== 200) {
            throw new Error('SmsPlanet HTTP error: ' . $status);
            }

            $decoded = json_decode($response, true);

            if (empty($decoded['messageId'])) {
            throw new Error('SmsPlanet: Invalid response');
            }
            }

            private static function formatNumber(string $number): string
            {
            $digits = preg_replace('/[^0-9]/', '', $number);

            if (strlen($digits) === 9) {
            return '+48' . $digits;
            }

            if (strlen($digits) === 11 && substr($digits, 0, 2) === '48') {
            return '+' . $digits;
            }

            return '+' . $digits;
            }

            private static function normalizeToGsm7(string $text): string
            {
            $map = [
            'ą'=>'a','ć'=>'c','ę'=>'e','ł'=>'l','ń'=>'n','ó'=> 'o','ś'=>'s','ż'=>'z','ź'=>'z',
            'Ą'=>'A','Ć'=>'C','Ę'=>'E','Ł'=>'L','Ń'=>'N','Ó'=> 'O','Ś'=>'S','Ż'=>'Z','Ź'=>'Z'
            ];

            $text = strtr($text, $map);

            $text = strtr($text, [
            '–'=>'-','—'=>'-','„'=>'"','”'=>'"',
            '’'=>"'",'…'=>'...','€'=>'EUR'
            ]);

            return preg_replace('/[^\x20-\x7E]/u', '', $text);
            }
            }

            Usage (Formula example)

            $body = 'Test SMS from EspoCRM';

            $phoneNumber = phoneNumber;

            // normalize PL numbers
            $phoneNumber = string\replace($phoneNumber, ' ', '');
            ifThen(
            string\length($phoneNumber) == 9,
            $phoneNumber = string\concatenate('+48', $phoneNumber)
            );

            $smsId = record\create(
            'Sms',
            'to', $phoneNumber,
            'body', $body
            );

            ext\sms\send($smsId);

            Notes
            • Polish characters → GSM conversion prevents SMS splitting (160 vs 70 chars)
            • Numbers without prefix are auto-converted to +48
            • Works with workflows, formulas, and automation

            Next improvements (if anyone interested)
            • SMS Templates (like Email Templates)
            • UI modal for sending SMS from Lead/Contact
            • Delivery status (DLR webhook)
            Attached Files

            Comment

            Working...