MODX - Создание email рассылки

Александр Мальцев
12K
3
Содержание:
  1. Установка компонента Sendex
  2. Создание email шаблона письма
  3. Создание рассылки
  4. Создание ресурса «Email подписка»
  5. Автоматическое формирование тела email рассылки
  6. Настройка cron для запуска email рассылки по расписанию
  7. Пример содержимого email письма (рассылки)
  8. Комментарии

Статья, в которой рассмотрим, как на базе компонента Sendex организовать еженедельную email рассылку писем подписчикам сайта.

Создание автоматической email рассылки для CMS MODX Revolution

Создание email рассылки для MODX Revolution на основе дополнения Sendex будет состоять из следующих основных шагов:

  • установка компонента Sendex;
  • создания email шаблона письма;
  • создания подписки;
  • разработки ресурса, на котором зарегистрированный и анонимный пользователь смогут не только подписаться на email рассылку, но также отписаться от неё;
  • создания php скрипта create.letters.php для автоматического формирования основного содержимого email рассылки и очереди писем для отправки;
  • настройки планировщика cron, который будет запускать в определённые моменты времени файлы create.letters.php и send.php.

Установка компонента Sendex

Установка компонента Sendex осуществляется через поставщика modstore.pro. Если он у вас не установлен, то сначала создайте его. После этого загрузите и установите для CMS MODX Revolution дополнение Sendex.

Создание email шаблона письма

Разрабатывать рассылку начнём с создания шаблона. Он необходим для создания HTML структуры (email шаблона) письма. В качестве имени зададим ему, например, значение SendexTemplate.

Содержимое шаблона (пример):

<table style="background-color: #f1f1f1; width:100%; font-family:-apple-system, system-ui, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;" align="center" width="100%" border="0" cellpadding="0" cellspacing="0">
  <tbody>
    <tr>
      <td align="center" style="vertical-align:top;padding:30px 0;text-align:center">
        <table style="text-align:left;width:680px;margin:0 auto;font-size:14px;border-spacing:0px">
          <tbody> 
            <tr>
              <td bgcolor="#fff" style="padding: 15px;">
                <font color="#777" style="font-size:18px">[[+newsletter.name]] ([[+phx:input=`now`:strtotime:date=`%d.%m.%Yг.`]])</font>
              </td>
            </tr>
            <tr><td height="25"></td></tr>
            <tr>
              <td bgcolor="#fff" style="padding: 15px;">
                [[+newsletter.description]]
              </td>
            </tr>
            <tr><td height="25"></td></tr>
            <tr>
              <td bgcolor="#fff" style="padding: 20px 15px; color: #777; font-size: 14px;">
                <p>© 2017 Мой сайт.</p>
                <p style="font-size: 12px;">Это сообщение было отправлено на [[+subscriber.email]] потому, что вы подписались на еженедельную рассылку. Данное письмо не требует ответа.</p>
                <p style="font-size: 12px;">Если вы не хотите больше получать письма от нас, то щелкните <a href="[[~10?scheme=`full`&sx_action=`unsubscribe`&code=`[[+subscriber.code]]`]]" target="_blank">здесь</a>.</p>
              </td>
            </tr>
          </tboy>
        </table>
      </td>
    </tr>
  </tbody>
</table>

Назначение ссылки и плейсхолдеров в содержимом шаблона SendexTemplate:

  • [[+newsletter.name]] - название подписки;
  • [[+newsletter.description]] - описание (основное содержимое) подписки;
  • [[+subscriber.email]] - email адрес подписчика;
  • ~10 - формирует ссылку на 10 ресурс сайта (этот ресурс, а точнее сниппет Sendex, расположенный в нём, будет осуществлять отписку от рассылки, если конечно пользователь перейдёт по ней);
  • [[+subscriber.code]] - код подписчика.

Создание рассылки

Для создания рассылки откроем в админке MODX страницу Sendex (Приложения -> Sendex). Переключимся на вкладку "Подписки" и нажмём на кнопку "Создать".

MODX Sender - Создание подписки
MODX Sender - Создание подписки

В диалоговом окне "Создать подписку" заполним поля формы следующими значениями:

  • Название - Информационная рассылка;
  • Шаблон - SendexTemplate;
  • Тема письма - Мой сайт - Еженедельная информационная рассылка;
  • Ответный email - no-reply@mysite.ru;
  • Исходящий email - no-reply@mysite.ru;
  • Отправитель - Мой сайт.

Поле "Описание" заполнять не будем. Его наполнение будем осуществлять с помощью php скрипта create.letters.php. Данный скрипт будем запускать с помощью планировщика cron раз в неделю.

MODX Sender - Отображение созданной подписки (имеющей id = 1) в таблице рассылок
MODX Sender - Отображение созданной подписки (имеющей id = 1) в таблице рассылок

Создание ресурса «Email подписка»

Создадим в админке MODX Revolution ресурс (pagetitle - Email подписка).

В содержимое ресурса поместим вызов 2 сниппетов:

[[!SendexEventTracking]]
[[!Sendex? 
  &id=`1`
]]

Сниппет Sendex

Сниппет Sendex осуществляет подписку пользователя на рассылку (в данном случае ту, которая имеет идентификатор 1), а также отписку от неё.

Подписку на рассылку, а также отписку от неё авторизированный пользователь осуществляет с помощью щелчка по кнопке.

MODX Sender - Форма подписки на email рассылку для авторизированного пользователя (пример)
MODX Sender - Форма подписки на email рассылку для авторизированного пользователя

Анонимный же пользователь осуществляет подписку через ссылку в письме. Для получения письма он должен ввести свой email адрес в форму подписки и нажать на кнопку «Подписаться».

MODX Sender - Форма подписки на email рассылку для анонимного (не авторизированного) пользователя (пример)
MODX Sender - Форма подписки на email рассылку для анонимного (не авторизированного) пользователя

Отписка от рассылки также осуществляется с помощью ссылки, которую, например можно расположить в футере письма. Если анонимный пользователь больше не захочет получать еженедельную информационную рассылку, то ему будет достаточно просто перейти по ней. Идентификация подписчика осуществляется по коду.

Настройка вывода форм, связанных с подпиской, сниппет Sendex осуществляет с помощью параметров:

  • tplSubscribeGuest - чанк (по умолчанию tpl.Sendex.subscribe.guest), содержащий форму, с помощью которой анонимный пользователь может подписаться на рассылку.
  • tplActivate - чанк (по умолчанию tpl.Sendex.activate), содержащий email шаблон, на основании которого будет формироваться письмо анонимному пользователю. Основное содержимое письма – это ссылка, по которой ему необходимо перейти для того, чтобы подтвердить подписку.
  • tplSubscribeAuth – чанк (по умолчанию tpl.Sendex.subscribe.auth), содержащий форму подписки, которая будет показываться авторизированному пользователю;
  • tplUnsubscribe – чанк (по умолчанию tpl.Sendex.unsubscribe), содержащий форму, посредством которой авторизированный пользователь может отписаться от рассылки.

При необходимости вы можете настроить содержимое каждого чанка. Но лучше это делать не в исходных чанках, а в их копиях, которые затем указать сниппету с помощью соответствующих параметров:

Например:

[[!Sendex? 
  &id=`1`
  &tplSubscribeAuth=`tplSendexSubscribeAuth`  
  &tplSubscribeGuest=`tplSendexSubscribeGuest`
  &tplUnsubscribe=`tplSendexUnsubscribe`  
  &tplActivate=`tplSendexActivate`
]]

Сниппет SendexEventTracking

Сниппет SendexEventTracking предназначен для отображения на странице информационных сообщений, связанных с email подпиской.

Вывод того или иного сообщения зависит от наличия в составе URL одного из следующих параметров: sx_subscribed, sx_confirmed, sx_unsubscribed.

Код сниппета SendexEventTracking:

<?php
$output = '';
$subscribed = $modx->getOption('subscribed', $scriptProperties, 'tplSendexEventSubscribed');
$confirmed = $modx->getOption('confirmed', $scriptProperties, 'tplSendexEventConfirmed');
$unsubscribed = $modx->getOption('unsubscribed', $scriptProperties, 'tplSendexEventUnsubscribed');
if ($_GET['sx_subscribed']) {
  $output = $modx->getChunk($subscribed);
}
if ($_GET['sx_confirmed']) {
  $output = $modx->getChunk($confirmed);  
}
if ($_GET['sx_unsubscribed']) {
  $output = $modx->getChunk($unsubscribed);  
}
return $output;

Все информационные сообщения хранятся в чанках (по умолчанию): tplSendexEventSubscribed, tplSendexEventConfirmed, tplSendexEventUnsubscribed.

Код чанка tplSendexEventSubscribed (пример):

<div class="alert alert-danger">На указанный почтовый ящик отправлено письмо, содержащее ссылку. Перейдите по ссылке для подтверждения email адреса, на который будут высылаться раз в неделю новые статьи.</div>

Код чанка tplSendexEventConfirmed (пример):

<div class="alert alert-danger">Вы успешно подписаны на еженедельную email рассылку сайта.</div>

Код чанка tplSendexEventUnsubscribed (пример):

<div class="alert alert-danger">Вы успешно отписаны от рассылки новых статей сайта.</div>
MODX Sender - Отображения информационного сообщения о том что указанный email адрес необходимо подтвердить, чтобы на него получать рассылку
MODX Sender - Отображения информационного сообщения о том что указанный email адрес необходимо подтвердить, чтобы на него получать рассылку

Автоматическое формирование тела email рассылки

Формировать тело рассылки будем выполнять автоматически с помощью php файла. Для этого создадим файл create.letters.php, например, в директории cron (/core/components/sendex/cron/) со следующим содержимым:

<?php
require_once dirname(dirname(dirname(dirname(dirname(__FILE__))))) . '/config.core.php';
require_once MODX_CORE_PATH.'model/modx/modx.class.php';
$modx = new modX();
$modx->initialize('web');
$modx->getService('error','error.modError', '', '');

// id раздела, в котором расположены статьи
$parent = array(5,6,7);
// создадим запрос на выборку новых статей, расположенных в указанных разделах (дата публикации не позже 7 дней)
$query = $modx->newQuery('modResource', array(
  'publishedon:>=' => strtotime('-7 days'),
  'parent:IN' => $parent
));
// ограничим выборку 5 элементами
$query->limit(5);
// получим статьи
$resources = $modx->getCollection('modResource', $query);

$output = '';
// переберём статьи и сформируем ответ
foreach ($resources as $resource) {
  $id = $resource->get('id');
  $pagetitle = $resource->get('pagetitle');
  $description = $resource->get('description');
  $url = $modx->makeUrl($id,'','','https');
  // получим tv поле image (id=2)
  $image = $modx->getObject('modTemplateVarResource',array( 'tmplvarid' => 2, 'contentid' => $id ));  
  if (is_object($image)) {
    $image = 'http://mysite.ru/assets/images/'.$image->get('value');
  } else {
    $image = '';
  }
  $output .= $modx->getChunk('tpl.newsletter.article',array(
    'pagetitle' => $pagetitle,
    'description' => $description,
    'url' => $url,
    'image' => $image
  ));
}
$count = count($resources);

// не будем формировать очередь, если количество новых статей равно нулю
if ($count==0) {
  exit();
}

// формируем очередь (создаём письма для отправки подписанным пользователям)
$modx->addPackage('sendex', MODX_CORE_PATH . 'components/sendex/model/');
/** @var sxNewsletter $newsLetter */
if ($newsLetter = $modx->getObject('sxNewsletter', 1)) {
  $newsLetter = $modx->getObject('sxNewsletter', 1);
  $newsLetter->set('description',$output);
  $newsLetter->save();
  $response = $newsLetter->addQueues();
}

exit();

Пример чанка, который будет использовать для оформления каждой статьи в письме (tpl.newsletter.article):

<tr>
  <td bgcolor="#fff" style="padding: 15px;">
    <table border="0" cellpadding="0" cellspacing="0" align="left" width="100%">
      <tbody>        
        <tr>          
          <td width="12" valign="middle" style="padding:10px 0;">
            <span style="display:block;border-left:5px solid #2ecc71">
              <font style="font-size:20px"> </font>
            </span>
          </td>                  
          <td valign="middle" style="padding: 10px 0;">
            <font color="#2ecc71" style="font-size:20px">[[+pagetitle]]</font>
          </td>
        </tr>
      </tbody>
    </table>
  </td>
</tr>
<tr>
  <td valign="top" bgcolor="#fff">
    <table border="0" cellpadding="0" cellspacing="0" align="left" style="width:100%;">
      <tbody>        
        <tr>
          <td valign="top">
            <img itemprop="image" src="[[+image]]" alt="[[+pagetitle]]" style="max-width: 100%;">
          </td>
        </tr>
        <tr>
          <td valign="top" style="padding: 15px;">
            <font color="#777" style="font-size:14px">[[+description]]</font>
          </td>
        </tr>
        <tr>          
          <td align="right" style="padding: 5px 15px 10px 0px;"> 
            <a href="[[+url]]" target="_blank">
              <font color="#2ecc71" style="font-size:14px">
              Читать далее...</font></a>
          </td>
        </tr>
      </tbody>
    </table>
  </td>
</tr>    
<tr><td height="25"></td></tr>
MODX Sender - Пустая очередь писем (до запуска файла create.letters.php)
MODX Sender - Пустая очередь писем (до запуска файла create.letters.php)
MODX Sender - Письма для отправки (после запуска файла create.letters.php)
MODX Sender - Письма добавленные в очередь для отправки (после запуска файла create.letters.php)

Настройка cron для запуска email рассылки по расписанию

Заключительное действие - это добавление в программу-планировщик cron двух заданий для запуска их в определённое время с определённой периодичностью.

Например:

  1. файл create.letters.php (формирование писем и додавление их в очередь) - например, каждый четверг в 6 часов утра (0 6 * * 4);
  2. файл send.php (отправка писем) - например, каждый четверг, начиная с 7 часов утра (*/12 7-9 * * 4).

Если подписчиков много, то письма можно отправлять небольшими порциями (например, по 50 штук) каждые 5 минут (*/12) в течение 3 часов (7-9). Файл send.php необходимо запускать после выполнения файла create.letters.php.

Содержимое файла send.php:

<?php

require_once dirname(dirname(dirname(dirname(dirname(__FILE__))))) . '/config.core.php';
require_once MODX_CORE_PATH . 'config/' . MODX_CONFIG_KEY . '.inc.php';
require_once MODX_CONNECTORS_PATH . 'index.php';

$modx->addPackage('sendex', MODX_CORE_PATH . 'components/sendex/model/');

$q = $modx->newQuery('sxQueue');
$q->limit($modx->getOption('sendex_queue_limit', null, 50, true)); // 50 - количество писем, отправляемых за один раз

$queue = $modx->getCollection('sxQueue', $q);
/** @var sxQueue $email */
foreach ($queue as $email) {
	$email->send();
}
Пример создания новой задачи для cron с помощью панели управления виртуальным хостингом
Пример создания новой задачи для cron с помощью панели управления виртуальным хостингом

Пример содержимого email письма (рассылки)

После отправки рассылки, каждый подписанный пользователь получит на свой адрес письмо, содержащий материал собранный create.letters.php.

Пример содержимого еженедельной email рассылки
Пример содержимого еженедельной email рассылки

Комментарии ()

  1. Людмила
    20 ноября 2020, 00:23
    Благодарю за сайт и статью! Скажите, почему выходит ошибка при cron-запуске create.letters.php:

    Parse error: syntax error, unexpected '[' in /home/host1604701/oartemi-slovo.ru/htdocs/www/core/model/modx/modx.class.php on line 283

    в 283 строке действительно есть строка с квадратными скобками: private $loggedDeprecatedFunctions = [];

    но ведь это стандартная поставка modx: htdocs\www\core\model\modx\modx.class.php

    Начало create.letters.php как у Вас:

    require_once dirname(dirname(dirname(dirname(dirname(__FILE__))))). '/config.core.php';
    require_once MODX_CORE_PATH.'model/modx/modx.class.php';
    1. Александр Мальцев
      21 ноября 2020, 12:43
      Файл «create.letters.php» расположен в «/core/components/sendex/cron/». Для того что из него добраться до «config.core.php» нужно 5 раз использовать dirname. На следующей строчке подключается «modx.class.php», который расположен на хостинге по адресу «MODX_CORE_PATH.'model/modx/modx.class.php'».
      1. Людмила
        22 ноября 2020, 18:35
        Кстати, send.php выдает точно такую же ошибку…

        Parse error: syntax error, unexpected '[' in /home/host1604701/oartemi-slovo.ru/htdocs/www/core/model/modx/modx.class.php on line 283

        1. Людмила
          21 ноября 2020, 16:27
          а если я подключаю require_once MODX_CORE_PATH.'model/modx/modx.class.php';

          то парсер конкретно говорит не об ошибке create.letters.php, а об ошибке modx.class.php. Но это же стандартный класс, я в нём ничего не меняла, как может быть ошибка в нём?

          Parse error: syntax error, unexpected '[' in /home/host1604701/oartemi-slovo.ru/htdocs/www/core/model/modx/modx.class.php on line 283
          1. Людмила
            21 ноября 2020, 16:22
            Благодарю за ответ, но если я подключаю только
            require_once dirname(dirname(dirname(dirname(dirname(__FILE__))))). '/config.core.php';

            то выходит сообщение:

            Class 'modX' not found in /home/host1604701/oartemi-slovo.ru/htdocs/www/core/components/sendex/cron/create.letters.php on line 5.

            понятно, что не подключен modx.class.php.
            1. Виталий
              24 ноября 2020, 18:45
              Проверьте версию PHP, на которой работает ваш cron на хостинге. Она часто отличается от той, которая установлена для сайта, у меня, например была 5.2. и тоже были ошибки
              1. Людмила
                24 ноября 2020, 20:41
                Ура! Решено! Был на cron PHP 5.3, а на сайте PHP 5.6, всё решили на хостинге. Благодарю! Слава Богу!
        2. Людмила
          19 ноября 2020, 23:09
          Здравствуйте! На вкладке Sendex «Очередь писем», где «Добавить письма рассылки в очередь», я выбираю свою подписку, и сразу формируются письма подписчикам. Потом я нажимаю «Отправить всё», письма уходят, но уходит пустой шаблон, без материалов, которые должен сформировать create.letters.php. Почему не срабатывает create.letters.php? Он на месте.
          1. Александр Мальцев
            21 ноября 2020, 12:47
            Здравствуйте! «create.letters.php» нужен для программного создания писем. Он к ручному формированию и тем более к шаблону, который для этого используется вообще никакого отношения не имеет.
            1. Людмила
              21 ноября 2020, 16:22
              Благодарю, поняла.
          2. Виталий
            19 ноября 2020, 13:02
            Здравствуйте, Александр!
            Подскажите, пожалуйста, как правильно написать условие для
            $parent =
            , если нужно выбрать несколько разделов, некоторые из которых еще и контейнеры (указать глубину).
            Например, разделы 1,3,5,7, из которых 3 и 5 содержат подразделы.
            Про
            $parent = $modx->getChildIds(2,3);
            прочитал, а как поступить если таких парентов несколько, и плюс обычные разделы?
            Спасибо за Ваш сайт, и за Ваш труд!
            1. Александр Мальцев
              19 ноября 2020, 13:24
              Здравствуйте!
              В PHP имеется функция array_merge с помощью которой слить несколько массивов в один.
              1. Виталий
                19 ноября 2020, 13:26
                Благодарю!
            2. Людмила
              25 октября 2020, 16:32
              Добрый день! Благодарю за сайт, обычно так всё понятно и хорошо написано. Только сейчас немного запуталась. Почему может получиться такое: copy.oartemi-slovo.ru/email-podpiska?
              Вроде всё делаю по инструкции.
              1. Александр Мальцев
                27 октября 2020, 16:39
                Добрый день! Спасибо за отзыв! Страница должна иметь обычный шаблон, т.е. тот который имеют другие страницы у вас на сайте. Может быть вы в качестве шаблона выбрали «Sendex»? «Sendex» используется в качестве шаблона только для email сообщений, его не нужно устанавливать для страниц сайта.
                1. Людмила
                  28 октября 2020, 00:48
                  Благодарю, простите за невнимательность.
              2. _Iris_
                27 мая 2020, 20:35
                Александр, здравствуйте!
                Спасибо за статью!
                Подскажите, пожалуйста, а можно ли с помощью Sendex отправлять письма пользователям, если их ресурс (где пользователь автор) опубликован и оповещать их, если приближается дата отмены публикации?
                Для доски объявлений
                1. Александр Мальцев
                  28 мая 2020, 02:14
                  Здравствуйте, конечно можете. Для этого напишите соответствующую логику в «create.letters.php» и настройки cron, например, раз в час. Cron будет запускать на выполнение скрипт «create.letters.php» и формировать письма на отправку.
                  1. _Iris_
                    28 мая 2020, 14:26
                    Спасибо за ответ! А не подскажете, как задать условие, чтобы письмо отправлялось именно автору?
                    Понимаю, что надо через createdby делать
                    1. _Iris_
                      28 мая 2020, 15:20
                      Вот так вот не работает
                      $user = $modx->getObject('modUser',$userId);
                      $query = $modx->newQuery('modResource', array(
                        'published:<>' => empty,
                        'parent:IN' => $parent,
                        'createdby:' => $user,
                      ));
                      1. Александр Мальцев
                        02 июня 2020, 14:26
                        Конечно, работать не будет.
                        Знак «не равно» записывается так:
                        'name:!=' => 'Тимур', /* не равно */
                        
                        В поле published хранится 1 или 0. Если published равно 1, то это значит, что ресурс опубликован. В createdby хранится id пользователя (число).

                        1. _Iris_
                          02 июня 2020, 14:40
                          Спасибо большое, лексика у меня страдает))
                          Только с пользователем не понятно, как по id пользователя формировать рассылку? чтобы только автору приходило письмо
                          1. Александр Мальцев
                            02 июня 2020, 15:17
                            Просто не вижу смысла здесь использовать Sendex. Он необходим чтобы пользователь мог подписаться на рассылку, или отписаться от неё, если он больше не хочет получать информационные сообщения.
                            Если вам это не нужно, то просто используйте modMail, который идёт вместе с MODX Revolution.
                            Пример, как его использовать:
                            $message = $modx->getChunk('myEmailTemplate');
                            
                            $modx->getService('mail', 'mail.modPHPMailer');
                            $modx->mail->set(modMail::MAIL_BODY,$message);
                            $modx->mail->set(modMail::MAIL_FROM,'me@example.org');
                            $modx->mail->set(modMail::MAIL_FROM_NAME,'Johnny Tester');
                            $modx->mail->set(modMail::MAIL_SUBJECT,'Check out my new email template!');
                            $modx->mail->address('to','user@example.com');
                            $modx->mail->address('reply-to','me@xexample.org');
                            $modx->mail->setHTML(true);
                            if (!$modx->mail->send()) {
                                $modx->log(modX::LOG_LEVEL_ERROR,'An error occurred while trying to send the email: '.$modx->mail->mailer->ErrorInfo);
                            }
                            $modx->mail->reset();
                            
                            1. _Iris_
                              02 июня 2020, 15:38
                              Александр, спасибо за совет! Попробую этот вариант!
                2. Nik
                  21 апреля 2020, 08:51
                  Доброго дня Александр! У меня вопрос о компонентах Sendex и bxSender. Второй платный, и более функциональный, и подкупает тем что есть статистика по письмам, отслеживание прочтения писем. Но хотелось бы услышать мнение профессионального человека, вы пользовались bxSender? Сильно ли данный компонент грузит систему? И насколько сложная там настройка после установки, по сравнению с Sendex? Если не пользовались, то вопрос конечно же исчерпан.
                  Автор компонента почему-то перестал отвечать на комментарии (modx.pro)
                  1. Александр Мальцев
                    21 апреля 2020, 13:54
                    Привет! Не знаю, не пользовался. Если нужно для аналитики, то мне, кажется, лучше просто прикрутить utm метки к рассылкам, а потом всё это дело анализировать в Google Analytics или Яндекс Метрике. Как по мне, то это всё лучше анализировать в одном месте, чем на какой-то странице в админке MODX. Также эти utm метки можно привязать и к ссылкам, например, размещаемых в социальных сетях, а потом всё это смотреть в одном месте. Но, в bxsender кроме аналитики есть ещё много других плюшек, если они нужны, то можете рассмотреть вопрос о его покупке. У меня опыта работы с этим компонентом нет. На странице в магазине есть видео как его настроить, думаю поэтому поводу проблем не должно возникнуть.
                    1. Nik
                      21 апреля 2020, 14:12
                      Благодарю! Вариант с utm метками отличное решение! в принципе пока больше ничего и не надо в ближайшее время
                  2. Роман
                    18 февраля 2019, 13:48
                    Добрый день.

                    Создал группу пользователей Sendex, в настройках minishop2 указал, что бы все новые пользователи добавлялись в эту группу.

                    Создал ресурс отписки от рассылки — в письме получавшему будет ссылка. Перешел, отписался.

                    Но как указать, что бы когда пользователь отписывается исключался из этой группы?

                    Смысл в том, пользователь делая заказ на сайте попадает в группу рассылки, а если не хочет получать её то нажимает ссылку в письме и исключается из группы. В Sendex нет инструментов по выбору пользователей для рассылки, или по одному всех подряд или группу, но отправлять пользователю который отписался от рассылки не правильно.

                    Прошу помощи.
                    1. Александр Мальцев
                      18 февраля 2019, 15:13
                      Добрый!
                      Методы Sendex (в том числе и метод отписывающий пользователя от рассылки) находятся в файле «\core\components\sendex\model\sendex\sxnewsletter.class».
                      В метод unSubscribe вам необходимо дополнительно добавить код для удаления пользователя из группы.
                      1. Роман
                        18 февраля 2019, 15:38
                        Александр, будет большой наглостью, если я вас попрошу привести пример кода, как это должно выглядеть? Самостоятельно не справлюсь.
                        1. Александр Мальцев
                          18 февраля 2019, 17:24
                          Пример:
                          public function unSubscribe($code) {
                            if ($subscriber = $this->xpdo->getObject('sxSubscriber', array('code' => $code))) {
                              // получаем id пользователя
                              $userId = $subscriber->get('user_id');
                              // получаем пользователя
                              $user = $this->xpdo->getObject('modUser', array('id' => $userId));
                              // если он есть, то удаляем
                              if (is_object($user)) {
                                $user->remove();
                              }
                              return $subscriber->remove();
                            }
                            return false;
                          }
                          
                          1. Роман
                            18 февраля 2019, 20:03
                            Указал удаление группы, но из группы не удаляется. Я не правильно понял, что нужно?
                            2 — это ID этой группы
                            public function unSubscribe($code) {
                            	if ($subscriber = $this->xpdo->getObject('sxSubscriber', array('code' => $code))) {
                            		// получаем id пользователя
                            		$userId = $subscriber->get('user_id');
                            		// получаем пользователя
                            		$user = $this->xpdo->getObject('modUser', array('id' => $userId));
                            		// если он есть, то удаляем
                            		if (is_object($user)) {
                            			$user->leaveGroup(2);
                            			$user->remove();	
                            		}
                            		return $subscriber->remove();
                            	}
                            
                            	return false;
                            }
                            
                            1. Роман
                              18 февраля 2019, 20:41
                              Видимо закешировалось, вот так заработало

                              public function unSubscribe($code) {
                              	  if ($subscriber = $this->xpdo->getObject('sxSubscriber', array('code' => $code))) {
                              		// получаем id пользователя
                              		$userId = $subscriber->get('user_id');
                              		// получаем пользователя
                              		$user = $this->xpdo->getObject('modUser', array('id' => $userId));
                              		// если он есть, то удаляем
                              		if (is_object($user)) {
                              			$user->leaveGroup('Sendex');
                              		}
                              		return $subscriber->remove();
                              	  }
                              	  return false;
                              	}
                              
                    2. Женёк
                      08 ноября 2018, 15:08
                      Добрый день!
                      Можно ли сделать так, чтобы когда добавляется новость на сайт, то сразу рассылка была автоматически?
                      1. Александр Мальцев
                        11 ноября 2018, 13:41
                        Добрый! Например, это можно выполнить так. Создать плагин на событие OnDocPublished. Данное событие возникает при публикации ресурса через контекстное меню. В данном плагине создать код, как это реализовано в файле create.letters.php. Отправку писем можно оставить как в статье, т.е. посредством cron; только в качестве интервала для вызова файла send.php установить интервал каждые 5 минут.
                      2. Слава
                        17 июля 2018, 21:45
                        Все впринцыпе получилось все работает, но вопрос в другом. Я собирался просто сделать рассылку, базу с имейлами купил) как мне добавить 3 тыс имейл адресов для рассылки?
                        1. Arhivar
                          24 августа 2018, 12:45
                          А я написал такой скрипт, который базу закачивает, использовал библиотеку phpExcel и статью «Программное создание пользователей для modx revo»!

                          Вот ссылки на инфу, которой пользовался для написания:
                          r-band.ru/how-to/chtenie-faylov-excel-na-php-osnovnye-metody-klassa-phpexcel.html
                          www.createit.ru/blog/modx/2012/programmatically-creating-users
                          Могу скрипт продать 3000р))
                        2. Андрей
                          07 июля 2018, 13:38
                          скажите а как очистить очередь писем после отправки?
                          письма формируются, отправляются, но остаются в очереди и по следующему запуску скрипта отправки писем снова уходят.
                          1. Александр Мальцев
                            07 июля 2018, 16:29
                            Очистить очередь можно так:
                            $modx->addPackage('sendex', MODX_CORE_PATH . 'components/sendex/model/');
                            // очистка очереди Sendex
                            $q = $modx->newQuery('sxQueue');
                            $queue = $modx->getCollection('sxQueue', $q);
                            foreach ($queue as $email) {
                                $email->remove();
                            }
                            
                          2. Андрей
                            03 июня 2018, 12:09
                            Спасибо, отличная статья!
                            Подскажите как лучше сделать рассылку, где будет выборка по нескольким родителям, но для каждого из них будет свой шаблон?
                            Вижу 2 варианта:
                            1. create.letters.php сделать еще одну выборку, но тогда там нужно формировать подзаголовки для каждой выборки, что мне кажется не очень красиво
                            2. прописать 2 или больше подзаголовка в шаблоне SendexTemplate, но тогда я не понимаю как быть со скриптом create.letters.php он как я понял формирует и все в одно место выдает
                            1. Александр Мальцев
                              05 июня 2018, 14:16
                              Спасибо!
                              Можно просто написать условие:
                              ...
                              $parent = $resource->get('parent');
                              ...
                              if ($parent == 5) {
                                $tpl_newsletter = 'tpl.newsletter.article';
                              } else {
                                $tpl_newsletter = 'tpl.newsletter.article2';
                              }
                              $output .= $modx->getChunk($tpl_newsletter, array(
                                'pagetitle' => $pagetitle,
                                ...
                              
                              1. Андрей
                                05 июня 2018, 15:34
                                что-то не понял как это сработает…
                                исходя из кода в зависимости от родителя будет выбран тот или иной шаблон, а мне нужно чтобы были использованы оба шаблона в одной рассылке для $parent == 5 tpl.newsletter.article, а для $parent == 6 — tpl.newsletter.article2
                                то есть идет текст рассылки
                                <h2>Новости</h2>
                                новости выводятся по одному шаблону
                                <h2>Статья</h2>
                                шаблон для статей
                                <h2>Фотки</h2>
                                шаблон для фоток
                                1. Александр Мальцев
                                  06 июня 2018, 06:41
                                  Не так понял. Тогда нужно создать шаблоны для раздела «Новости», «Статья» и «Фотки». И сформировать сначала их. После этого их передать в конечный шаблон (чанк).
                                  Например:
                                  // получаем новости
                                  $query = $modx->newQuery('modResource', array(
                                    'publishedon:>=' => strtotime('-7 days'),
                                    'parent:IN' => array(5,6);
                                  
                                  ));
                                  $query->limit(5); // ограничим выборку 5 элементами
                                  $resources = $modx->getCollection('modResource', $query);
                                  $output_news = '';
                                  foreach ($resources as $resource) {
                                    $id = $resource->get('id');
                                    $pagetitle = $resource->get('pagetitle');
                                    ...
                                    $output_news.= $modx->getChunk('tpl.newsletter.news',array(
                                      'pagetitle' => $pagetitle,
                                      ...
                                    ));
                                  }
                                  
                                  // получаем статьи
                                  $query = $modx->newQuery('modResource', array(
                                    'publishedon:>=' => strtotime('-7 days'),
                                    'parent:IN' => array(7,8);
                                  
                                  ));
                                  $query->limit(5); // ограничим выборку 5 элементами
                                  $resources = $modx->getCollection('modResource', $query);
                                  $output_articles = '';
                                  foreach ($resources as $resource) {
                                    $id = $resource->get('id');
                                    $pagetitle = $resource->get('pagetitle');
                                    ...
                                    $output_articles .= $modx->getChunk('tpl.newsletter.article',array(
                                      'pagetitle' => $pagetitle,
                                      ...
                                    ));
                                  }
                                  
                                  // получаем фотки
                                  $query = $modx->newQuery('modResource', array(
                                    'publishedon:>=' => strtotime('-7 days'),
                                    'parent:IN' => array(9,10,11);
                                  
                                  ));
                                  $query->limit(5); // ограничим выборку 5 элементами
                                  $resources = $modx->getCollection('modResource', $query);
                                  $output_photos = '';
                                  foreach ($resources as $resource) {
                                    $id = $resource->get('id');
                                    $pagetitle = $resource->get('pagetitle');
                                    ...
                                    $output_photos .= $modx->getChunk('tpl.newsletter.photo',array(
                                      'pagetitle' => $pagetitle,
                                      ...
                                    ));
                                  }
                                  
                                  // формируем конечный результат
                                  $output_photos = $modx->getChunk('tpl.newsletter',array(
                                    'news' => $output_news,
                                    'articles' => $output_articles,
                                    'photos' => $output_photos,
                                  ));
                                  
                                  Содержимое чанка tpl.newsletter:
                                  <h2>Новости</h2>
                                  [[+news]]
                                  <h2>Статья</h2>
                                  [[+articles]]
                                  <h2>Фотки</h2>
                                  [[+photos]]
                                  
                                  Ну, соответственно содержимое чанков tpl.newsletter.news, tpl.newsletter.article и tpl.newsletter.photo формируете так как это необходимо.
                                  1. Андрей
                                    14 июня 2018, 22:46
                                    Спасибо, то что нужно!
                                    А еще вопрос — как я понимаю в текущем варианте идет выборка с глубиной 0? а как добавить глубины выборки например 5?
                                    пробовал
                                    $parent = array(281,7);
                                    
                                    $query = $modx->newQuery('modResource', array(
                                      'publishedon:>=' => strtotime('-7 days'),
                                      'parent:IN' => $parent,
                                      'depth' => '5'
                                    ));
                                    и всяие
                                    'depth:=' => '5'
                                    'depth:IN' => '5'
                                    и тп — ничего не работает…
                                    1. Андрей
                                      16 июня 2018, 00:05
                                      сам нашел решение — нужно глубину поиска переложить на этапе определения родителей
                                      $parent = $modx->getChildIds(281,3);
                                      где первая цифра id раздела, вторая — глубина поиска наследников с таким учетом, чтобы их дети и были нужны в выборке.
                                      надеюсь понятно объяснил, может кому пригодится)
                            2. Роман
                              07 марта 2018, 22:04
                              Спасибо за статью!

                              Скажите как можно организовать подписку не перезагружая страницу? Проблема в том, что форма с подпиской находится почти в самом низу страницы, а она не маленькая! Ситуация: ты вводишь свой e-mail страница перезагружается и вообще не понятно что происходит!?

                              В идеале, перезагружается этот блок и выводится сообщение из снипета SendexEventTracking вместо этой формы! Можно ли такое сделать? Если как, то куда смотреть, как организовать?

                              Спасибо!
                              1. Александр Мальцев
                                09 марта 2018, 12:24
                                Можно, но не в рамках этой инструкции. Возьму на заметку. Чтобы это сделать необходимо использовать AJAX.
                              2. miami
                                01 марта 2018, 09:16
                                Александр, добрый день!
                                Подскажите, как реализовать в
                                $query = $modx->newQuery('modResource', array(
                                'publishedon:>=' => strtotime('-7 days'),
                                'parent:IN' => $parent
                                ));

                                что бы было равно сегодняшней дате.

                                'publishedon:==' => сегодня,

                                Идея: Создал статьи и выставил дату публикации на будущее (каждый четверг). Скрипт должен проверить в четверг найти все статьи созданные в этот день и сформировать очередь.
                                Сейчас он формирует все новости, ограничивается только $query->limit(5);

                                Надеюсь на Вашу помощь.
                                1. Александр Мальцев
                                  05 марта 2018, 15:52
                                  Здравствуйте!
                                  Все варианты условий можно посмотреть на этой странице. Они расположены в пункте, который начинается с текста «xPDOQuery.where...».
                                  Знак «равно» задаётся так:
                                  (1 способ)
                                  'publishedon' => mktime(),
                                  (2 способ)
                                  'publishedon:=' => mktime(),
                                  
                                  В вашем случае неправильно задавать такое условие, т.к. дата, скорее всего включает в себя ещё и время.
                                  Необходимо, для выбора ресурсов с текущей датой, использовать следующее:
                                  'publishedon:>=' => mktime(0,0,0),
                                  'publishedon:<=' => mktime(23,59,59),
                                  
                                  1. miami
                                    12 марта 2018, 09:07
                                    Спасибо, выручили.
                                    Не подскажите еще по одному вопросу.
                                    Sendex останавливает работу если адрес не верный или не существующий, и приходиться запускать заново удаляя из таблицы проблемный емейл.
                                    Может возможно перепрыгивать проблемные мейлы и отсылать дальше.
                                    Как возможно решить этот вопрос?
                                    1. Александр Мальцев
                                      12 марта 2018, 15:43
                                      Нет, никаких проблем не должно быть. Просто это письмо не отправиться, оно не должно влиять на другие.
                                      1. miami
                                        12 марта 2018, 16:20
                                        Странно, вот прямо сейчас не хочет отправлять письма, просто стоит. Я думал при проблемных мейл он застревает т.к. в
                                        $q->limit($modx->getOption('sendex_queue_limit', null, 50, true));
                                        сейчас стоит 2.
                                        При лимите 100 он не плохо все отправил, но мейл не любит таких.
                                        По каким причинам еще он может просто застревать?
                                        P.S.: В ручную по одному письму отправляет. Через send.php и cron не хочет. На той недели отправлял но запинался на проблемных.
                                        1. miami
                                          12 марта 2018, 17:12
                                          Поставил лимит 5 отправляет только 2 письма.
                                          3 видимо проблемные адреса, если сейчас встретит еще 2 проблемных работа рассылки остановится.
                                          1. Александр Мальцев
                                            23 марта 2018, 14:48
                                            Тогда необходимо изменить часть скрипта send.php.
                                            foreach ($queue as $email) {
                                                $email->send();
                                            }
                                            
                                            А именно заменить вышеприведённый блок кода на этот:
                                            foreach ($queue as $email) {
                                                if ($email->send()!==true) {
                                                    $email->remove();
                                                }
                                            }
                                            
                                2. Sergey
                                  04 декабря 2017, 15:43
                                  Спасибо, за статью. Подскажите пожалуйста, как лучше реализовать, чтобы подписчики сразу становились пользователями «Аноним»? Нужно администрировать подписчиков между рассылками.
                                  1. Александр Мальцев
                                    05 декабря 2017, 12:38
                                    Любой не авторизированный пользователь на MODX — уже аноним. Подписчики есть в базе, можете просто создать страничку и администрировать их на ней.
                                    1. Sergey
                                      05 декабря 2017, 16:08
                                      В Sendex есть анонимы, которые подписались через сайт, но перенести их в другую рассылку нельзя, т.е. на кнопке «Добавить пользователя» их нет
                                      s1.bild.me/bilder/110417/4942049screenshot_2017-12-05_005.png
                                  2. daddydj
                                    03 ноября 2017, 03:58
                                    Отличная статья. Все понятно и доступно.
                                    Возник вопрос, а выборка для еженедельной отправки делается среди новых ресурсов?
                                    Т.е. он может на момент запуска скрипта посмотреть что нового публиковалось в какой-то категории и отправить это в рассылку? Как такое можно реализовать?

                                    И второй вопрос, возможно ли, чтоб при добавлении статьи автоматически происходила отправка, допустим, первых двух абзацев на почту подписчикам с кнопкой «Подробнее»? Как связать sendex со статьями, чтоб он подхватывал картинку из ресурса и текст контента?
                                    Спасибо.
                                    1. Александр Мальцев
                                      04 ноября 2017, 15:25
                                      Спасибо.
                                      Да, среди новых (на момент запуска скрипта, выбираются только те ресурсы, которые имеют дату публикации не позже 7 дней). Разделы, из которых это необходимо осуществить настраиваются с помощью переменой $parent.
                                      Для решения второго вопроса, нужно создать плагин на событие OnDocPublished. В обработчике этого события написать код, подобный тому, который приведён в файлах create.letters.php и send.php.
                                      1. daddydj
                                        13 ноября 2017, 01:01
                                        Что-то все по статье делаю, но выборка не происходит. На почту приходит пустое письмо, причем шаблона Sendex Template и все.
                                        Скрипт из панели Cron на Beget пробовал вручную запускать, тоже ничего не происходит. При том, что ресурсы, перечисленные в Parent младше 7 дней давности.

                                        И еще, если имя TV картинки отличается от image, его везде надо переписать или достаточно только в теле шаблона tpl.newsletter.article?

                                        И что делать с send.php? Судя по статье Cron должен стартовать только первый скрипт? Или создать задания надо на оба файла?
                                        1. Александр Мальцев
                                          14 ноября 2017, 16:00
                                          Если что-то не получается с выборкой, то попрубуйте её сначала создать на отдельной странице.
                                          Выбор TV картинки в скрипте выполняется по id, т.е. имя TV не используется.
                                          В примере id TV имеет значение 2:
                                          'tmplvarid' => 2
                                          
                                          Снчала должен запускаться скрипт create.letters.php. Он формирует письма и добавляет их в очередь. После него send.php. Он отправляет их.
                                          1. Роман
                                            23 сентября 2019, 07:50
                                            Как выборку создать на отдельной странице?

                                            п.с. тоже не получается передать TV в тело письма (((
                                            1. Александр Мальцев
                                              23 сентября 2019, 14:23
                                              Тут вроде бы всё просто.
                                              Для этого создаём php-файл, например, «letters.php» в корне сайта:
                                              <?php
                                              
                                              require_once 'config.core.php';
                                              require_once MODX_CORE_PATH.'model/modx/modx.class.php';
                                              $modx = new modX();
                                              $modx->initialize('web');
                                              $modx->getService('error','error.modError', '', '');
                                              
                                              $pdoTools = $modx->getService('pdoTools');
                                              
                                              $output = '';
                                              
                                              $parent = array(5,6,7);
                                              $query = $modx->newQuery('modResource', array(
                                                'publishedon:>=' => strtotime('-7 days'),
                                                'parent:IN' => $parent
                                              ));
                                              $query->limit(5);
                                              $resources = $modx->getCollection('modResource', $query);
                                              
                                              $count = count($resources);
                                              
                                              if ($count == 0) {
                                                exit();
                                              }
                                              
                                              foreach ($resources as $resource) {
                                                $id = $resource->get('id');
                                                $pagetitle = $resource->get('pagetitle');
                                                $description = $resource->get('description');
                                                $url = $modx->makeUrl($id,'','','https');
                                                $image = $modx->getObject('modTemplateVarResource',array( 'tmplvarid' => 2, 'contentid' => $id ));  
                                                if (is_object($image)) {
                                                  $image = 'http://mysite.ru/assets/images/'.$image->get('value');
                                                } else {
                                                  $image = '';
                                                }
                                                $output .= $pdoTools->getChunk('@FILE chunks/tpl.newsletter.article',array(
                                                  'pagetitle' => $pagetitle,
                                                  'description' => $description,
                                                  'url' => $url,
                                                  'image' => $image
                                                ));
                                              }
                                              
                                              $output = $pdoTools->getChunk('@FILE chunks/tpl.newsletter.wrapper.tpl',array(
                                                'output' => $output
                                              ));
                                              
                                              echo $output;
                                              
                                              exit();
                                              
                                              Открываем его браузере и проверяем.
                                              1. Роман
                                                23 сентября 2019, 18:59
                                                Вывел, но дальше что то не пошло joxi.ru/D2PJvY5Tq93wBr

                                                Что делаю не так?
                                                1. Александр Мальцев
                                                  24 сентября 2019, 13:51
                                                  Проверьте может что-то опустили или сделали не так.
                                                  Попробуйте просто вывести значения на экран:
                                                  foreach ($resources as $resource) {
                                                    print_r($resource->toArray());
                                                  }
                                                  
                                                  1. Роман
                                                    24 сентября 2019, 14:19
                                                    Вывелось: joxi.ru/V2V4jLZHdQwyEr

                                                    Чанки:
                                                    tpl.newsletter.article.tpl
                                                    tpl.newsletter.wrapper.tpl

                                                    На месте, и заполнены

                                                    Весь мой код этой страницы:
                                                    <?php
                                                    
                                                    require_once 'config.core.php';
                                                    require_once MODX_CORE_PATH.'model/modx/modx.class.php';
                                                    $modx = new modX();
                                                    $modx->initialize('web');
                                                    $modx->getService('error','error.modError', '', '');
                                                    
                                                    $pdoTools = $modx->getService('pdoTools');
                                                    
                                                    $output = '';
                                                    
                                                    $parent = array(19);
                                                    $query = $modx->newQuery('modResource', array(
                                                      'publishedon:>=' => strtotime('-7 days'),
                                                      'parent:IN' => $parent
                                                    ));
                                                    $query->limit(5);
                                                    $resources = $modx->getCollection('modResource', $query);
                                                    
                                                    $count = count($resources);
                                                    
                                                    if ($count == 0) {
                                                      exit();
                                                    }
                                                    
                                                    foreach ($resources as $resource) {
                                                      $id = $resource->get('id');
                                                      $pagetitle = $resource->get('pagetitle');
                                                      $description = $resource->get('description');
                                                      $url = $modx->makeUrl($id,'','','https');
                                                      $image = $modx->getObject('modTemplateVarResource',array( 'tmplvarid' => 2, 'contentid' => $id ));  
                                                      if (is_object($image)) {
                                                        $image = 'http://mysite.ru/assets/images/'.$image->get('value');
                                                      } else {
                                                        $image = '';
                                                      }
                                                      $output .= $pdoTools->getChunk('@FILE chunks/tpl.newsletter.article.tpl',array(
                                                        'pagetitle' => $pagetitle,
                                                        'description' => $description,
                                                        'url' => $url,
                                                        'image' => $image
                                                      ));
                                                    }
                                                    
                                                    
                                                    
                                                    $output = $pdoTools->getChunk('@FILE chunks/tpl.newsletter.wrapper.tpl',array(
                                                      'output' => $output
                                                    ));
                                                    
                                                    echo $output;
                                                    
                                                    foreach ($resources as $resource) {
                                                      print_r($resource->toArray());
                                                    }
                                                    
                                                    exit();
                                                    1. Александр Мальцев
                                                      24 сентября 2019, 14:42
                                                      В этом примере чанки должны быть расположены по пути «core/elements/chunks/».
                                                      В чанке «tpl.newsletter.wrapper.tpl» плейсхолдер [[+newsletter.description]] необходимо заменить на {$output}, т.к. он используется в коде.
                                                      1. Роман
                                                        24 сентября 2019, 15:12
                                                        Чанки там и лежали. Запустилось пошло.

                                                        Теперь осталось понять, почему мои TV не выводятся
                                                        1. Александр Мальцев
                                                          24 сентября 2019, 15:31
                                                          Выведи значение:
                                                          if (is_object($image)) {
                                                            echo 'TV value:' . $image->get('value');
                                                          } else {
                                                            echo 'TV value:';
                                                          }
                                                          
                                                          1. Роман
                                                            24 сентября 2019, 17:12
                                                            Разобрался. Спасибо
                                            2. daddydj
                                              14 ноября 2017, 19:43
                                              все так и есть. ID поля совпадает с ID tv-поля с картинкой. Да и само письмо не формируется почему-то из чанка шаблона. В самом Sendex формируются письма, когда для отправки выбираю единственно созданную рассылку(по примеру). И формируются письма по кол-ву подписчиков. И при отправке письмо приходит пустое в оформлении шаблона Sendex Template. Два раза перепроверил последовательность действий по уроку, пока не разобрался, в чем дело. Modx Revo 2.6.0

                                              Категории новостей с ресурсами в виде коллекции.
                                      2. kovasal
                                        02 ноября 2017, 08:55
                                        Добрый день, Александр!
                                        У меня в форме обратной связи на сайте чекбокс «подписаться на новости».
                                        Решил сделать хук для Formit.
                                        Проверку на подписанность юзера в таблице sendex'а сделать вроде соображу как.
                                        А как из этого сниппета запустить sendex, чтобы он отработал так же, как при нажатии кнопки «подписаться» подскажите?
                                        1. Александр Мальцев
                                          04 ноября 2017, 15:07
                                          Добрый день!
                                          В этом случае вам необходимо самостоятельно организовать логику, используя методы Sendex.
                                          Например:
                                          <?php
                                          /** @var array $scriptProperties */
                                          /** @var Sendex $Sendex */
                                          $Sendex = $modx->getService('sendex','Sendex',$modx->getOption('sendex_core_path',null,$modx->getOption('core_path').'components/sendex/').'model/sendex/',$scriptProperties);
                                          if (!($Sendex instanceof Sendex)) return '';
                                          
                                          $email = $hook->getValue('email'); // получаем значение email
                                          $id = '0'; // id пользователя (по умолчанию)
                                          $linkTTL = 1800; // время жизни ссылки
                                          $tplActivate = 'tpl.Sendex.activate'; // чанк, содержащий email шаблон
                                          $output = '';
                                          $result = false;
                                          
                                          // авторизирован ли пользователь (true - авторизован, false - нет)
                                          $isAuthenticated = $modx->user->isAuthenticated($modx->context->key);
                                          if ($isAuthenticated) {
                                              $id = $modx->user->id; // получаем id пользователя
                                          }
                                          $newsletter = $modx->getObject('sxNewsletter', 1); // sxNewsletter (1 - id подписки)
                                          // отправка проверочного кода на email анонимного юзера
                                          $response = $newsletter->checkEmail($email, $id, $linkTTL);
                                          if ($response === true) {
                                              // пользователь уже подписан
                                              $output = 'Пользователь уже подписан';
                                          } elseif ($response === false) {
                                              // если email пустой или он является не корректным
                                              $output = 'Указан не корректный email';
                                          } else {
                                              // отправка проверочного кода
                                              $params['hash'] = $response; // хэш
                                              $params['sx_action'] = 'confirm'; // действие
                                              $placeholders['link'] = $modx->makeUrl($modx->resource->id, $modx->context->key, $params, 'full');
                                              $placeholders['email_body'] = $modx->getChunk($tplActivate, $placeholders);
                                              $response = $Sendex->sendEmail($email, $placeholders);
                                              if ($response !== true) {
                                                  // ошибка при отправке email
                                                  $output = 'Ошибка при отправке email';
                                              } else {
                                                  // email отправлен
                                                  $output = 'Email отправлен. Перейдите по ссылке из письма!';
                                                  $result = true;
                                              }	
                                          }
                                          $hook->setValue('rsubscribe', $output);
                                          return $result;
                                          
                                          1. kovasal
                                            05 ноября 2017, 21:39
                                            Большую работу проделываете, Александр, помогая и подсказывая начинающим. И статьи очень интересные и понятные. Вы педагог от бога!
                                            1. kovasal
                                              04 ноября 2017, 19:46
                                              Спасибо. А я так понимаю нужно еще поле name=«rsubscribe» создать, чтобы туда прописывались сообщения?
                                              1. Александр Мальцев
                                                05 ноября 2017, 05:09
                                                Не знаю, всё зависит от вашей формы. Можете просто создать плейсхолдер для вывода сообщений без поля rsubscribe.
                                          2. Владимир
                                            18 октября 2017, 22:45
                                            Здравствуйте, подскажите пожалуйста куда надо вставить — Пример чанка, который будет использовать для оформления каждой статьи в письме? Или как назвать чанк?
                                            1. Александр Мальцев
                                              19 октября 2017, 15:50
                                              Здравствуйте! Добавил данную информацию в статью.
                                              1. Владимир
                                                19 октября 2017, 23:30
                                                Огромное спасибо! Разобрался.
                                            2. Александр
                                              16 октября 2017, 04:56
                                              Александр, отличное руководство! Скажите в чём может быть проблема, создаю статью в ручную и в админке sendex рассылаю вручную письма с рассылкой для проверки, письма приходят только с пустым шаблоном, где копать?

                                              И непонятно как прописать время рассылки в файле: create.letters.php?
                                              1. Александр Мальцев
                                                18 октября 2017, 11:05
                                                Спасибо!
                                                Выборка ресурсов осуществляется с помощью следующего кода:
                                                $parent = array(5,6,7);
                                                $query = $modx->newQuery('modResource', array(
                                                  'publishedon:>=' => strtotime('-7 days'),
                                                  'parent:IN' => $parent
                                                ));
                                                $query->limit(5);
                                                $resources = $modx->getCollection('modResource', $query);
                                                
                                                Проверьте, опубликованы ли созданные ресурсы. А также корректно ли вы выставили значение переменной $parent.

                                                Время рассылки настраивается с помощью cron, а не в файле. Файл create.letters.php не может сам себя запустить. Его запуск осуществляет планировщик cron.
                                              2. sergey
                                                13 октября 2017, 12:19
                                                modstore.com/ это верный сайт с Sendex?
                                                1. Александр Мальцев
                                                  14 октября 2017, 04:37
                                                  Исправил. Правильный поставщик конечно же modstore.pro.
                                                2. Arhivar
                                                  16 августа 2017, 11:07
                                                  А как сделать чтобы Sendex все сообщения брал из папки en lexicon/en/default.inc.php.
                                                  ($_lang['sendex_menu_desc'] = 'Newsletters management'; — так нужно)
                                                  То есть, как его на английский перевести, чтоб все предупреждения типа «введите emal», на английском были.
                                                  1. Александр Мальцев
                                                    17 августа 2017, 14:24
                                                    Обычно это задаётся посредством настроек контекстов.
                                                    Например, у вас есть контекст сайта на английском языке. В настройки это контекста вы добавляете параметр cultureKey со значением en.После этого вся информация у вас на сайте будет отображаться на английском языке.
                                                    1. Arhivar
                                                      17 августа 2017, 17:24
                                                      Спасибо! помогло. С контекстами заодно познакомился..) До этого не приходилось сталкиваться!
                                                    2. Arhivar
                                                      16 августа 2017, 12:28
                                                      И еще вопрос: Вставил подписку в модальное окно, из этой статьи -https://itchief.ru/lessons/bootstrap-3/bootstrap-3-modal-window

                                                      Но при нажатии на кнопку, подписать, закрывается модальное окно! Как сделать чтоб окно не закрывалось, при нажатии на кнопку отправить?

                                                      Сделал так:
                                                      [[!AjaxForm?
                                                      &form=`tplSendexSubscribeGuest`
                                                      &snippet=`Sendex`
                                                      &id=`1`
                                                      ]]
                                                      Ничего не работает!
                                                      1. Александр Мальцев
                                                        17 августа 2017, 14:46
                                                        AjaxForm заточен под FormIt и так просто это не получится осуществить.
                                                    3. Анатолий
                                                      09 июля 2017, 21:57
                                                      Александр, очень хороший сайт у вас. Спасибо.

                                                      Вопросы чуть поподробнее.
                                                      1.Куда вставить этот чанк??
                                                      Пример чанка, который будет использовать для оформления каждой статьи в письме:
                                                      2. Как создать эту задачу??
                                                      Пример создания новой задачи для cron с помощью панели управления виртуальным хостингом
                                                      Спасибо за сайт.
                                                      1. Александр Мальцев
                                                        11 июля 2017, 10:23
                                                        Спасибо.
                                                        1. Данный чанк должен иметь имя tpl.newsletter.article.
                                                        2. Это зависит от хостера. Необходимо в его справке найти соответствующий раздел и посмотреть, как это делается. Вот пример справки от Beget: _https://beget.com/ru/manual/crontab
                                                      2. Arhivar
                                                        19 июня 2017, 20:36
                                                        Прямо, ждал эту статью!!! )
                                                        1. Александр Мальцев
                                                          20 июня 2017, 14:57
                                                          Рад, что статья понравилась.
                                                        Войдите, пожайлуста, в аккаунт, чтобы оставить комментарий.