Отложенная отправка через SMPP позволяет передать SMS оператору заранее и указать время доставки в поле schedule_delivery_time. Такой подход подходит для напоминаний, уведомлений о начале смены, изменении статуса заказа и других сообщений, которые должны прийти по расписанию. В статье разберём формат времени, часовые пояса, контроль DLR и логику повторной отправки, чтобы малый бизнес мог собрать простой SMS-шедулер без ручной загрузки сообщений.
Что делает schedule_delivery_time в SMPP?
При обычной отправке приложение передаёт сообщение сразу. При отложенной отправке оно добавляет к запросу submit_sm значение schedule_delivery_time. SMS-центр или SMPP-шлюз принимает сообщение, сохраняет его до заданного момента и затем передаёт в сеть оператора.
Поле задаёт момент, к которому нужно привязать обработку сообщения. Точный результат зависит от настроек SMPP-провайдера: один шлюз поддерживает отложенную доставку на своей стороне, другой передаёт запрос дальше оператору, а третий может игнорировать расписание, если функция не включена для подключения. Поэтому первый тест проводят на небольшом количестве номеров и проверяют время фактической передачи.
Для приложения полезно разделить два события:
- шлюз принял сообщение и вернул
message_id; - оператор сообщил итог через DLR, то есть delivery receipt.
Положительный ответ на submit_sm подтверждает приём запроса, но не означает, что абонент уже получил SMS. Именно поэтому планировщик должен сохранять идентификатор сообщения и связывать его с последующим DLR. Для технической схемы контроля статусов пригодится материал о настройке каскада для доставки SMS-кода и статуса.
Как подготовить время отправки и часовой пояс?
Самая частая ошибка появляется, когда бизнес хранит расписание по местному времени, а приложение формирует SMPP-поле в другом часовом поясе. Например, менеджер выбирает отправку на 09:00 по Минску, а сервер работает в UTC. Если приложение не преобразует время заранее, SMS уйдёт с ошибкой в несколько часов.
Для каждого сообщения храните как минимум четыре значения:
- исходное время, которое выбрал пользователь;
- часовой пояс этого времени;
- рассчитанный момент отправки в едином формате;
- статус задачи: запланирована, передана, доставлена или завершилась ошибкой.
Для клиентов в Беларуси можно установить единый часовой пояс в настройках проекта. Для зарубежных получателей часовой пояс лучше хранить у контакта или определять по правилам отдельного сегмента. Телефонный код страны не всегда достаточно надёжно показывает фактическое местное время: клиент может находиться в поездке, а корпоративный номер может обслуживать другой регион.
Практичная схема выглядит так: пользователь выбирает дату и время в привычном виде, сервер переводит значение в единый внутренний формат, а перед отправкой формирует schedule_delivery_time согласно требованиям конкретного SMPP-шлюза. В интерфейсе рядом со временем полезно показывать его часовой пояс, чтобы оператор видел, к какому региону относится расписание.
Какой формат передавать в schedule_delivery_time?
Формат поля нужно сверить с документацией SMPP-подключения. Нельзя автоматически переносить в него строку из базы данных вроде «11.08.2026 09:00». SMPP использует специальное представление даты и времени, а отдельные шлюзы устанавливают дополнительные ограничения на точность, часовой пояс и допустимый горизонт планирования.
Перед запуском проверьте четыре параметра:
- поддерживает ли соединение отложенную отправку;
- какой формат даты принимает шлюз;
- какую точность времени он использует: минуты или секунды;
- что происходит с сообщением, если указанное время уже прошло.
В тестовой отправке задайте время на несколько минут вперёд и сравните три отметки: момент создания задачи, время приёма запроса шлюзом и время, указанное в DLR. Если шлюз возвращает ошибку, сохраните код и текст ответа. Он пригодится при разборе причины, особенно когда проблема связана с форматом поля или недоступностью функции.
Текст сообщения тоже влияет на планирование. Кириллица и специальные символы меняют правила кодирования и длину SMS, поэтому перед передачей проверьте настройку кириллицы в SMPP, UCS-2 и длину SMS. Иначе планировщик отработает правильно, но приложение получит больше сегментов, чем рассчитывалось.
Как не потерять DLR у запланированных сообщений?
Шедулер должен считать задачу выполненной только после понятного результата. После вызова submit_sm сохраните внутренний идентификатор задачи, message_id от шлюза, номер получателя, запланированное время и содержимое сообщения или его безопасный идентификатор. DLR затем сопоставляется по message_id, а при необходимости дополнительно проверяется по номеру и времени отправки.
| Событие | Что сохранить | Действие приложения |
|---|---|---|
| Задача создана | Получатель, текст, время и часовой пояс | Поставить статус «запланирована» |
| submit_sm принят | Код ответа и message_id | Перевести задачу в «передана шлюзу» |
| Пришёл DLR | Статус доставки и время события | Обновить итоговый статус |
| Ответ с ошибкой | Код ошибки и причина | Отметить сбой и решить, нужна ли повторная попытка |
| DLR не пришёл | Время ожидания и историю проверок | Передать задачу в контроль очереди |
Повторная отправка требует отдельного правила. Если приложение не получило DLR, это ещё не доказывает, что SMS не доставили: задержка могла возникнуть на стороне шлюза или оператора. Поэтому повторять сообщение сразу после тайм-аута рискованно. Для критичных уведомлений задайте ограниченное число проверок, храните историю попыток и не создавайте новый запрос без понятного основания.
Для расчёта расходов учитывайте каждую фактически отправленную часть длинного сообщения, а не только одну запись в очереди. Подход к расчёту стоимости через SMPP разобран в материале о стоимости SMS через SMPP в 2026 году.
Как устроить простой SMPP-шедулер для малого бизнеса?
Минимальная архитектура состоит из очереди задач, воркера и обработчика DLR. Очередь хранит сообщения с будущим временем отправки. Воркер регулярно выбирает задачи, срок которых наступил, открывает или использует SMPP-сессию и отправляет их через submit_sm. Обработчик входящих уведомлений меняет статусы в базе.
Не стоит отправлять все запланированные сообщения одним длинным циклом. Разделите работу на небольшие пачки и задайте ограничение скорости для конкретного соединения. Так проще пережить временный отказ, переподключение или рост очереди. Если бизнес отправляет объёмный трафик, отдельно контролируйте количество активных SMPP-сессий и доступный лимит на стороне провайдера.
В таблице задач полезно иметь поля scheduled_at, timezone, status, attempt_count, provider_message_id и last_error. Перед отправкой воркер блокирует выбранную строку, чтобы два процесса не передали одно SMS одновременно. После перезапуска сервера задачи со статусом «в работе» возвращаются в контрольную выборку по понятному правилу.
Какие ошибки чаще всего ломают отложенную отправку?
- Приложение передаёт локальное время сервера вместо времени клиента.
- В
schedule_delivery_timeпопадает формат, который не поддерживает шлюз. - Задача считается доставленной сразу после положительного ответа на
submit_sm. - Воркер повторяет отправку без проверки уже сохранённого
message_id. - После перезапуска сервера сообщения со статусом «в работе» остаются без владельца.
- Тест проводят только на одном времени и не проверяют переход между часовыми поясами.
Для первого запуска достаточно взять один сценарий, например напоминание о записи, и проверить путь целиком: создание задачи, преобразование времени, передачу через SMPP, получение DLR и обработку сбоя. Затем добавьте часовые пояса и пакетную отправку. Если требуется подключить высокообъёмный трафик к конкретной системе, техническую часть можно заказать у специалиста по SMPP, сохранив собственную бизнес-логику расписаний.
3 шага, которые можно сделать на этой неделе:
- Уточнить у SMPP-провайдера поддержку
schedule_delivery_time, формат поля и правила DLR. - Добавить в очередь задачи часовой пояс, внутренний статус и
provider_message_id. - Провести тест на несколько минут вперёд и сверить плановое время с отметками передачи и доставки.



