MODx Letters (бывший EasyNewsletter)

Upd-доступно для установки из Extras!
UPD проверьте папку cache в корне модуля и добавьте ее если она отсутствует!!!
Переписал EasyNewsletter.

Сервисы почтовой рассылки сейчас очень популярны. Однако не все компании прибегают к платным услугам рассылки и подписки на новости. Главные задачи сервиса почтовых рассылок: ведение клиентской базы и рассылка им писем. Очень важным этапом подготовки к внедрению сервиса почтовых рассылок является правильная настройка домена для того, чтобы письма, отправленные на адреса, не попадали в спам. Сюда входит не только правильная настройка mx-записей, но и настройка dkim и spf.
MODx Letters — это бесплатное готовое дополнение для MODx Evolution, включающее в себя достаточно функциональный модуль для управления письмами и списком подписчиков, а также сниппет. Теперь перейду к более детальному описанию функциональности MODx Letters.

В этой разработке я использовал php шаблонизатор Twig, который мне показался довольно простым в освоении. На нем большая часть модуля написано, есть пара кусков, которые еще не адаптированы.

Интерфейс MODx Letters составлен с использованием библиотеки Twitter Bootstrap.
Интерфейс и описание функциональности
Вкладка «Подписчики». Здесь отображаются все подписчики, находящиеся в системе. Для удобного вывода подписчиком использована библиотека jQuery Datatable. Объекты ajax'ом передаются в json формат и динамически подгружаются в таблицу.


Редактирование и добавление нового подписчика во всплывающем окне происходит в фоновом режиме.


В модуле также предусмотрен импорт подписчиков из файла csv. В ходе загрузки файла отображается прогресс отображения в реальном времени процесса записи в базу данных информации о подписчиках. Импорт тоже происходит аяксом.

В хэдере есть кнопка обновления и селект фильтрации по категориям.

Ну а ниже, соответственно футер. Это все базовый функционал jQuery DataTables.

Вкладка «Письма». Здесь собственно добавляются письма и редактируются. Письму обязательно надо указать категорию и выбрать шаблон. В противном случае изменения не сохранятся.

Если выбрать письмо, то будет доступна отправка письма, отправка письма по категориям (письмо отправится подписчикам, имеющим такую же категорию).
Функционал Отчетов пока не разработан!

Расширенная отправка

Кстати, отправка сейчас работает, если превышено максимальное время выполнения скрипта.

Вкладка «Категории». Тут собственно все понятно. Добавляем категорию — потом ее присваиваем подписчикам и письмам. Присваивать можно сразу несколько категорий.



Вкладка «Шаблоны». В коде шаблона пишем Ваш ранее сверстанный хэдер, футер и т.д. Указываем переменные. В переменную {{ content|raw }} вставляется тело письма.



Вкладка «Настройки». Все настройки отправки почты беруться из конфигурации MODx.

Сниппет Letters

Сниппет имеет ряд параметров.
<?php
/*
 * @lng
 * Язык
 * По умолчанию - russian-UTF8
 * Имена файлов в папке languages
 *
 * @tpl
 * Шаблон формф подписки.
 * По умолчанию так, как определено ниже.
 * Возможные значения - имя чанка в системе
 *
 * @tpl_unsuscribe
 * Шаблон отписки от рассылки
 * Значение: чанк из системы
 *
 * @cat_id
 * Список категорий через запятую, который будет присвоен подписчику
 * Пример 1 или 2,4 или 2,3,4,5
 *
 * @formname
 * Имя формы атрибута name
 * String
 */

1. Вводим email

2. Идем на почту

3. Кликаем на ссылку, ура, отписались.

_________________

Установка

копируем папку, инклудим модуль и сниппет, выполняем install.sql, включаем full url в tinyMCE

Версия для тестирования, ознакомления.

Посетить сайт и Скачать MODxLetters

UPD

github.com/sazanof/MODxLetters/commit/c392f9b370365894451971c86fc969734b0a1348
Добавлена проверка почты на существование. К сожалению, как я понял, эта штука работает не всегда верным образом. Но в целом, удовлетворяет.
Спасибо Serg28 за наводку, однако пришлось сменить реализацию на другую, в виду того, что при тестировании не «очень срослось» =)

94 комментария

avatar
Шикарная вещь!!! Уже была идея писать свой модуль, но Вы опередили. Буду тестировать. Спасибо.
Комментарий отредактирован 2017-01-27 09:46:15 пользователем Serg28
avatar
Спасибо. По возможности буду развивать проект, появилось время.
avatar
Кстати, рекомендую сразу оформить модуль как пакет для установки через Extras, чтобы все автоматизировать. А то вручную неудобно заливать файлы и дамп.
avatar
Будет такое дело!
avatar
так же как и тесты? :)
avatar
Все может быть=).
Вот поражаюсь я иногда — вам «нате», а вы «фи».
avatar
В первую очередь делаю для себя
Не все сразу)
Комментарий отредактирован 2017-01-27 11:37:56 пользователем siuzi_drum
avatar
просто забросили тесты :) ничего плохого не хотел сказать
avatar
Все силы уходят, уходили в борьбу с коррупцией. 2016-й был тяжелым =)
Я дофига чего забросил после рождения сына.
+ Стоительство дома / бани / гаража…

Старею =)

А сейчас на работе выдалась неделька-другая =)
Комментарий отредактирован 2017-01-27 11:49:02 пользователем siuzi_drum
avatar
а ссылка на git? :)
avatar
А ссылка на гит внизу странички
sazanof.ru/veb-razrabotka/modx-letters-modul-podpiski-i-rassylki.html
но держите отдельно, если так уж github.com/sazanof/MODxLetters/releases
avatar
да, спасибо, хотелось посмотреть как вы все это организовали в коде, что описали в статье. А в данном топике «скачать» по дефолту подумалось то, что и написано, но никак не переход на ваш сайт
за решение спасибо, при возможности, если будет задача на модуль рассылки попробуем его в боевых условиях :)
avatar
Организовал как умею =)
avatar

class Categories
{
    public function getCategories ($where=false,$order=''){
        global $modx;
        $fields='id,title,description';
        if ($order!==''){
            $order_ext = 'ORDER BY '.$modx->db->escape($order);
        }
        $sql = $modx->db->select($fields,TBL_CATEGORIES,$where,$order_ext);
        return $modx->db->makeArray($sql);
    }
...


Лучше вот так:
class Categories
{
    protected $modx = null;

    public function __construct (\documentParser $modx) {
        $this->modx = $modx;
    }

    public function getCategories ($where=false,$order=''){
        $fields='id,title,description';
        if ($order!==''){
            $order_ext = 'ORDER BY '.$this->modx->db->escape($order);
        }
        $sql = $this->modx->db->select($fields,TBL_CATEGORIES,$where,$order_ext);
        return $this->modx->db->makeArray($sql);
    }
...
avatar
Спасибо, мне есть чему учиться, не буду скрывать.
avatar
Ну и если развивать дальше, то нужна очередь отправки писем.
avatar
То есть? Не совсем понимаю.
avatar
Например, чтобы обойти лимиты на отправку писем, отправляя их не сразу все, а по 100 в час или как-то еще.
avatar
А, вы про лимиты на отправку. Тогда я вас понял! Спасибо!
avatar
У меня сделано так — допустим подписчиков 100.
max_execution time = 10 сек
каждый раз после отправки письма пользователю во временный файл пишется его id,
после 10 сек делается вновь и вновь ajax запрос start limit, формирующий массив, за исключением тех адресов, письма которым отправились. И так ajax будет до тех пор, пока массив не опустеет.

Т.е делится на очереди
0 — 10 сек = 1-10 подписчик
10 — 20 сек = 11 — 20 подписчиик…
Ну думаю вы поняли
Комментарий отредактирован 2017-01-27 10:13:54 пользователем siuzi_drum
avatar
Ого! Спасибо. Буду смотреть, выглядит внушительно :)
avatar
А есть проверка адреса на подлинность? Я имею ввиду, что при регистрации/подписке идет проверка, существует ли вообще такой адрес или это пустышка?
avatar
да наверное это самое интересное на проверку от ботов
avatar
Я на предыдущей версии этого модуля сам дописывал эту проверку, много таких нерабочих адресов фильтровало. Хотя иногда бывает даже боты рабочие адреса пишут, но все же дополнительная защита
avatar
Можете поделиттся.
В любом случае сделаю, тк функционал нужный.
Спасибо за подскащку, совсем запамятовал.
avatar
Еще не плохо ее же добавитт при импорте, так как бывает дают файл, а там за несколько тысяч адресов и не все действующие
avatar
Отправил в личку информацию
avatar
github.com/sazanof/MODxLetters/commit/c392f9b370365894451971c86fc969734b0a1348
Сделал проверку на реальность почтового адреса при импорте, отправке, добавлении/редактировании.
avatar
включаем full url в tinyMCE

Это где? В конфигурации плагина? нет такой настройки, в конфигурации Modx тоже
avatar
Отчего может быть в консоли ошибка 500 и белый экран при запуске модуля?
avatar
Перенес файлы на сервер, выполнил через восстановление install.sql, инклудом подключил модуль и сниппет. При запуске модуля выдает ошибку 500 в консоли и белый экран только появлется и все.
avatar
А сервеные логи посмотреть? Там всё будет понятно.
avatar
Либо включите отображение всех ошибок, либо смотрите логи. Могу попробовать помочь. Пишите
avatar
Да, в конфе Тини. Там что тот типа absolute, relarive… url
avatar
siuzi_drum, чет я туплю, а как сниппет настроить, чтобы посетителю нужно было только e-mail ввести?
avatar
Пока только отредактировав сам сниппет
avatar
github.com/sazanof/MODxLetters/blob/master/assets/modules/letters/snippet.php#L105
Это здесь идет проверка на заполнение? Можно просто удалить эту строчку?
avatar
Нет, Вы пробовали просто не заполняя поле имени добавиться как подписчик?
avatar
А еще есть параметр &tpl
Измените его как вам надо
avatar
Только надо еще сниппет подправить на существование фио.
На гитхабе напишите эту проблемку
avatar
Для того, чтобы модуль работал с PHP 7,
убираем везде, где используются массивы, предыдущее присваивание результатирующему массиву пустого значения, так как он тогда становится string и вываливаетсяошибка.

меняем $duplicate = '';
на $duplicate = array();
меняем $res = '';
на $res = array();
avatar
Спасибо! Подправлю.
avatar
Функция отправить у всех работает?
окно висит и ничего не происходит:
<code>Uncaught SyntaxError: Unexpected token N in JSON at position 109
    at Function.parse (<anonymous>)
    at Function.a.parseJSON (VM6413 jquery-migrate-1.4.1.min.js:2)
    at Object.success (VM6656 letters.actions.js:34)
    at i (VM6412 jquery-3.1.1.min.js:2)
    at Object.fireWith [as resolveWith] (VM6412 jquery-3.1.1.min.js:2)
    at A (VM6412 jquery-3.1.1.min.js:4)
    at XMLHttpRequest.<anonymous> (VM6412 jquery-3.1.1.min.js:4)
a.parseJSON @ VM6413 jquery-migrate-1.4.1.min.js:2
success @ VM6656 letters.actions.js:34
i @ VM6412 jquery-3.1.1.min.js:2
fireWith @ VM6412 jquery-3.1.1.min.js:2
A @ VM6412 jquery-3.1.1.min.js:4
(anonymous) @ VM6412 jquery-3.1.1.min.js:4
</code>
Modx 1.2.1-d9.1.2
Комментарий отредактирован 2017-04-16 17:44:53 пользователем zabudkin
avatar
разбираюсь с этим
avatar
responce в браузере что отдает?
avatar
{«num»:1,«answer»:"\u041e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 \u043f\u0438\u0441\u044c\u043c\u0430..."}No route to host (113)
No route to host (113)
avatar
тогда можете отключить проверку на существование email
github.com/sazanof/MODxLetters/blob/master/assets/modules/letters/inc/send.inc.php#L82
avatar
позже вынесу в настройки этот пункт
avatar
добавил 1==1 и всё работает! :)
avatar
ну тоесть отключил проверку получается))))
Ну круто. вообще — эта проверка работает не всегда…
avatar
если есть баги или пожелания — пишите на гит_))
avatar
в сниппете:

case 'subscribe':
            if ($_POST['sub'] == 1 && !empty($_POST['token']) && $_GET['type'] === 'suscribe') {

так subscribe или suscribe (без b)?
:)
и это не только в сниппете
Комментарий отредактирован 2017-04-16 18:22:03 пользователем zabudkin
avatar
пока в case'ах добавил 'suscribe' и 'unsuscribe' :)
avatar
Поэтому и призываю к тестированию
avatar
и ещё в конце сниппета надо делать не echo, а return

теперь вроде всё работает. такое ощущение, что только мы двое и пользуемся :))
Комментарий отредактирован 2017-04-16 18:27:48 пользователем zabudkin
avatar
А ретурн разве в файлах работает?
avatar
какая разница где :) вы же его иклудите.

И ещё в сниппете лучше так наверное?:

//добавляем подписчика
  $data['cat_id'] = $cat_id;
  if ($subscribers->InsOrUpdSubscriber($data, '') === true) {
  // header('Location: ' . $_SERVER['REQUEST_URI']);
     $out .= $lang['thankyou'];
}
avatar
Конечно, так лучше)
avatar
какая разница где :) вы же его иклудите.
Не работает в файлах
avatar
Ну круто, что могу сказать. Надо учесть все это и обновить.
Не, не вдвоем. Мне еще тайком пишут :)
avatar
теперь вроде всё работает. такое ощущение, что только мы двое и пользуемся :))
Я воспользоваться пока не успел, но глаз положил.

А вообще — такое ощущение, что всей MODX Evo человека три пользуются :D
Комментарий отредактирован 2017-04-16 19:05:27 пользователем Aharito
avatar
Конечно везде subscribe
И в форме конечно же тоже)
avatar
а вы проверьте :) я же не придумал
avatar
За-пу-лить на гит можете?
avatar
не умею им пользоваться
avatar
1 — github.com/sazanof/MODxLetters/commit/ff89a862ad0c6316f57fb16a1a2c8d6d1307f5cd
2 — добавьте папку cache в корень! почему-то нет ее в релизе

обновлю как смогу
Комментарий отредактирован 2017-04-16 17:57:11 пользователем siuzi_drum
avatar
avatar
А как отписаться? Что написать на странице отписки, как вызвать сниппет, чтобы отписаться мог человек? Хелпаните плиз.
avatar
Создаете ресурс, где вызываете сниппет с параметром unsubscribe
В письме в тело или в футер вставляете линк на эту страницу.
avatar
Ребята, а как установить сие чудо, я в этом не силен
avatar
Расслабили вас Extras =)
Раньше всегда все ручками ставили
Создайте модуль и вставьте в него
require_once(MODX_BASE_PATH.'assets/modules/letters/module.php');
создайте сниппет и вставьте в него
<?php
require MODX_BASE_PATH.'assets/modules/letters/snippet.php';
Комментарий отредактирован 2017-05-15 08:51:05 пользователем siuzi_drum
avatar
Спасибо все заработало, только вот проблема, у меня почему к путям к изображениям в письме дописывается site.by/manager хотя должно site.by/ Кто нибудь сталкивался с таким?
avatar
В конфиге TinyMCE абсолютный(полный) урл должен стоять, поэкспериментируйте
avatar
ставил, все равно тоже самое
avatar
Добрый день.
Можна ли форму отправить аяксом?
я пробовол вот так, почему то не работает:
<div id="formSubsc">
        [!MODxLetters? &cat_id=`4` &formname=`SubscribeForm` &lng=`[[switch?ua=`ukraine-utf8` &ru=`russian-UTF8`]]` &tpl=`letters_tpl`!]
</div>
        <script>
                        $(function(){
                                $(document).on("submit","#SubscribeForm",function(e){
                                        e.preventDefault();
                                        var m_method=$(this).attr('method');
                                        var m_action=$(this).attr('action');
                                        var m_data=$(this).serialize();
                                        $.ajax({
                                                type: m_method,
                                                url: m_action,
                                                data: m_data,
                                                resetForm: 'true',
                                                success: function(result){
                                                        var data = $(result).find("#formSubsc").html();
                                                        $("#formSubsc").html(data);
                                                }
                                        });
                                });
                        });
                </script>

в форме:
<form action="[~[*id*]~]?type=subscribe" method="post" name="[+formname+]" id="SubscribeForm">
<input type="hidden" name="token" value="[+token+]">
...
<button type="submit" name="sub" value="1" class="btn btn-print bg-blue order-blue">[(__send_subscribe)]</button>
</form>
Комментарий отредактирован 2017-09-04 10:22:03 пользователем kozak_vova
avatar
так не будет, стуканите в личку, помогу,
avatar
Компонент отличный! Спасибо!
Только нужно поправить то, что писали выше под php 7 и еще бы экспорт почт в csv добавить.
  • Shin
  • 0
avatar
как можно прикрутить вложение
avatar
дописать скрипт на прикрутку вложений
avatar
Не люблю чужие игрушки ломать, т.к если обновление выйдет нужно будет опять допиливать
avatar
Допишите, сделайте пулл-реквест, и не придется опять допиливать)
А если лень — оставьте хотя бы Ишшу
avatar
Ишшу???
avatar
avatar
Доброго времени суток, поскажите почему сниппет может возвращать ошибку 500
avatar
вангануть не получится, нужно больше информации
Комментарий отредактирован 2018-10-23 06:14:52 пользователем siuzi_drum
avatar
Честно я сам хз, на сайте установлен shopkeeper, вызываю сниппет как в примере, сраница выдает ошибку 500, установил последнюю версию модуля, версия модх 1.4.5
avatar
Смотрите логи апача, там всё есть
avatar
Подскажите, пожалуйста, как можно в подписчики MODx Letters передать email при регистрации на сайте через сниппет WebSignup (входит в комплект WebLogin).
avatar
в версии ModX Evo 1.4.8 снипет выдает ошибку /manager/includes/controls/phpmailer/class.phpmailer.php): failed to open stream: No such file or directory. Я так понял, что класс уже другой и нужно переписывать весь модуль рассылки?
avatar
Не. Он там перемещен) создайте этот файлик и укажите в нем подключение текущего)
/manager/includes/controls/phpmailer/PHPMailer.php
avatar
Как запустить на 1.4.8? Установил из Extras. Пробовал менять путь /manager/includes/controls/phpmailer/class.phpmailer.php на /manager/includes/controls/phpmailer/PHPMailer.php, при выводе страница отдает 500 ошибку
avatar
Поддерживаю вопрос!
avatar
Попробуйте это:
В файле сниппета assets/modules/letters/snippet.php — закоменьтить подключение файла class.phpmailer.php.
/*$mailer_file = MODX_MANAGER_PATH.'includes/controls/phpmailer/class.phpmailer.php';
require_once ($mailer_file);
$mail = new PHPMailer();*/

И подключить там же отправку через API:
$modx->loadExtension('MODxMailer');
$mail = $modx->mail;

И в файле /assets/modules/letters/inc/send.inc.php — найти и закоментить условие проверки файла на наличие и подключение:
//if (file_exists($mailer_file)) {
//require_once $mailer_file;
// подключаемся к PHP Mailer
$lt = $letters->getLetter($id);
$body = $letters->generateTplFromCode($lt['template'],$lt['newsletter']);
//$mail = new PHPMailer();

И подключить там же отправку через API:

$modx->loadExtension('MODxMailer');
$mail = $modx->mail;

Должно работать. Но не получается пока настроить отписку, если получится дайте знать)
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.