Отложенная отправка писем при помощи FormIT + Scheduler
        Сегодня в нашем телеграм-чатике  задали вопрос — 
Можно ли как то реализовать отложенную отправку письма, через форму formIT.
Этот вопрос напомнил мне о моих планах, написать инструкцию именно об этом.
По сути подобная задача уже реализована в miniShop2 на базе компонента Scheduler, не так давно опубликованного в Modstore.pro.
Итак, давайте разберемся как же все таки отправить отложенное письмо при помощи FormIt + Scheduler
Как отправлять письма используя FormIt — все знают. Вызываем сниппет FormIT (или, использующие его компоненты ajaxForm, FetchIT). В качестве хука указываем email, который берет на себя функционал мгновенной отправки писем. Если нужно отложить отправку, то напишем свой хук, который будем подключать вместо email;
Создадим пару сниппетов, необходимых на следующих шагах
scheduler_hook
Это хук, который будем подключать в вызов ajaxForm, вместо email
send_email
Это сниппет, который позже в фоновом запланированном режиме будет отправлять письмо
Далее настроим компонент Scheduler. После установки, перейдите в него, откройте вкладку задания и нажмите создать задание

Заполним задание следующим образом:

Замените в вызове formIT или ajaxForm хук email на хук scheduler_hook
После отправки формы, в вашем планировщике должно появиться задание, в котором будет видно заполненные данные клиента, что само по себе уже является плюсом и позволяет отслеживать письма и их содержимое

Обратите внимание на, то, что компонент запускается сервером через серверный планировщик задач CRON
Чтобы выполнение отложенных задач работало — нужно добавить CRON запись на вашем хостинге. Как это сделать описано в документации Scheduler
    
    
                                                        Можно ли как то реализовать отложенную отправку письма, через форму formIT.
Этот вопрос напомнил мне о моих планах, написать инструкцию именно об этом.
По сути подобная задача уже реализована в miniShop2 на базе компонента Scheduler, не так давно опубликованного в Modstore.pro.
Итак, давайте разберемся как же все таки отправить отложенное письмо при помощи FormIt + Scheduler
Как отправлять письма используя FormIt — все знают. Вызываем сниппет FormIT (или, использующие его компоненты ajaxForm, FetchIT). В качестве хука указываем email, который берет на себя функционал мгновенной отправки писем. Если нужно отложить отправку, то напишем свой хук, который будем подключать вместо email;
Шаг 1
Создадим пару сниппетов, необходимых на следующих шагах
scheduler_hook
Это хук, который будем подключать в вызов ajaxForm, вместо email
<?php
/** @var Scheduler $scheduler */
$path = $modx->getOption(
    'scheduler.core_path',
    null,
    $modx->getOption('core_path') . 'components/scheduler/'
);
$scheduler = $modx->getService('scheduler', 'Scheduler', $path . 'model/scheduler/');
$task = $scheduler->getTask('formit', 'form_email');
// Перечисляем какие поля вы заполняете в сниппете, из тех что требуются для отправки писем
$fields = [
    'emailTo',
    'emailSubject',
    'successMessage',
    'fields'
];
$params = [];
foreach($fields as $key) {
    if (!empty($scriptProperties[$key])) {
        $params[$key] = $scriptProperties[$key];
    }
}
if ($task instanceof sTask) {
     // Здесь можете указать через какое время выполнить задание.   
    // + 1 second - мгновенно,  + 2 minutes,  + 3 hours. 
    //  Также допустимы точные указания времени
    $task->schedule('+1 second', $params);
} 
return true;send_email
Это сниппет, который позже в фоновом запланированном режиме будет отправлять письмо
unset($scriptProperties['task']);
unset($scriptProperties['run']);
$scriptProperties['hooks'] = 'email';
$_POST = $scriptProperties['fields'];
unset($scriptProperties['fields']);
$modx->runSnippet('FormIt', $scriptProperties);
if (!empty($scriptProperties['successMessage'])) {
    return $scriptProperties['successMessage'];
}
return 'done';Шаг 2
Далее настроим компонент Scheduler. После установки, перейдите в него, откройте вкладку задания и нажмите создать задание

Заполним задание следующим образом:
- Название — любое произвольное на английском. Я назвал form_email
 - Тип задания — на основе сниппета
 - Категория — formIT
 - Сниппет — созданный на шаге 1 сниппет send_email
 

Шаг 3
Замените в вызове formIT или ajaxForm хук email на хук scheduler_hook
После отправки формы, в вашем планировщике должно появиться задание, в котором будет видно заполненные данные клиента, что само по себе уже является плюсом и позволяет отслеживать письма и их содержимое

Шаг 4
Обратите внимание на, то, что компонент запускается сервером через серверный планировщик задач CRON
Чтобы выполнение отложенных задач работало — нужно добавить CRON запись на вашем хостинге. Как это сделать описано в документации Scheduler
            
                Поблагодарить автора            
            
                 Отправить деньги            
        
        
            Комментарии: 8
                Классный хак с повторным вызовом FormIT и пробросом туда параметров из задания через $_POST, очень элегантно!
Мне вот на подобие этого нужно было как-то вызывать хук для формита с API-вызовами к внешнему сервису но без отправки формы, так пришлось его код копировать и в сниппет выносить, а стоило сделать вот так как в заметке сделан сниппет send_email, чтобы не дублировать код и не поддерживать потом 2 версии…
К стати дополню список — в AjaxFormitLogin этот метод тоже будет работать
                    Мне вот на подобие этого нужно было как-то вызывать хук для формита с API-вызовами к внешнему сервису но без отправки формы, так пришлось его код копировать и в сниппет выносить, а стоило сделать вот так как в заметке сделан сниппет send_email, чтобы не дублировать код и не поддерживать потом 2 версии…
К стати дополню список — в AjaxFormitLogin этот метод тоже будет работать
                Изобрел — пока статью писал.            
                    
                Николай, правильно ли я понимаю, что этими действиями мы заменяем хук email и отправка писем (хуки email + FormItAutoResponder) будут откладываться на заданное время?
А если ситуация такая когда отправляются 3 письма: Заявка ушла админу/менеджеру, непонимание ушло клиенту — это всё мгновенно должно уходить после отправки формы. А третье через 15 минут уходит опять же клиенту.
Как на схеме, как прикрутить этот компонент? Заранее благодарен
            
                    А если ситуация такая когда отправляются 3 письма: Заявка ушла админу/менеджеру, непонимание ушло клиенту — это всё мгновенно должно уходить после отправки формы. А третье через 15 минут уходит опять же клиенту.
Как на схеме, как прикрутить этот компонент? Заранее благодарен
            
                Да верно. Мы заменяем хук email. Насчет хука FormItAutoResponder…
В сниппете send_email в список выполняемых хуков нужно просто добавить все нужные хуки.
Чтобы письма отправлялись в разное время, нужно просто перебрать email и каждому поставить свою задачу. Перепишем кусок поставновки задачи вот так:
                    В сниппете send_email в список выполняемых хуков нужно просто добавить все нужные хуки.
Чтобы письма отправлялись в разное время, нужно просто перебрать email и каждому поставить свою задачу. Перепишем кусок поставновки задачи вот так:
// Перечисляем какие поля вы заполняете в сниппете, из тех что требуются для отправки писем
$fields = [
    'emailTo',
    'emailSubject',
    'successMessage',
    'fields'
];
$params = [];
foreach($fields as $key) {
    if (!empty($scriptProperties[$key])) {
        $params[$key] = $scriptProperties[$key];
    }
}
if ($task instanceof sTask) {
    $emails = $params['emailTo'];
    unset($params['emailTo']);
    $emails = array_map('trim', explode(',', $emails));
    foreach($emails as $email) {
        $params['emailTo'] = $email;
        // Здесь можете указать через какое время выполнить задание. 
        switch($email) {
            case 'bigboss@mail.ru':
                //   Этому отправляем сразу
                $task->schedule('+1 second', $params);
            case 'smallboss@mail.ru':
                //   Этому отправляем через 5 минут
                $task->schedule('+5 minutes', $params);
            break;
        }  
    }
   
}            
                >> Чтобы письма отправлялись в разное время, нужно просто перебрать email и каждому поставить свою задачу.
Но проблема в том, что мы заранее не знаем почту клиента.
                    Но проблема в том, что мы заранее не знаем почту клиента.
                Заполненные поля формы доступны в параметре $params['fields']. Достаньте email оттуда, нет проблем.            
                    
                Николай, прошу прощения за может быть нелепый вопрос, но могу ли я сделать третью отправку с задержкой отдельным хуком. А email и FormItAutoResponder оставить в вызове FormIt как есть. Там проблема в том, что клиенту отправляются два разных по содержанию письма, а параметр fiarTpl я поменять не могу(            
                    
                Можете. Общий Принцип взаимоотношений с менеджером очередей я показал. Доступ к настройкам сниппета, к полям формы есть. Крутите ими как хотите, все данные для этого доступны.            
                    
                            Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.