Введение
Почти в каждом проекте приходится думать об отправке писем по электронной почте. Основными требованиями при этом являются, помимо надежности доставки, привлекательность и удобство электронных писем.
Основные нюансы при формировании таких писем:
- Все стили должны встраиваться (inline) в виде атрибута
style
для конкретного HTML-элемента. - Все изображения должны встраиваться, либо как отдельные вложения в в письме, либо в виде base64-кодированных данных (второе банально удобнее).
- Письмо должно поддерживать DKIM (настройка мэйлера).
Ранее я использовал для формирования HTML-писем проект Premailer, созданный на Ruby. Пришлось даже заняться поддержкой проекта (сейчас времени на это нет, мэйнтейнеры приветствуются).
Сейчас же хотелось избежать внедрения Ruby, в то время, как Node проник везде.
Juice
К счастью, современная экосистема Node предоставляет богатые возможности по формированию электронных писем. Мы выбрали цепочку по формированию электронной почты в виде pug-шаблонов, преобразованию оных с помощью juice и подстановки конкретных данных на бэкэнде (у нас это Perl).
Установка
npm install gulp-cli -g npm install gulp --save-dev npm install gulp-rename --save-dev npm install gulp-pug --save-dev npm install premailer-gulp-juice --save-dev npm install gulp-postcss --save-dev npm install autoprefixer --save-dev npm install gulp-less --save-dev
gulpfile.babel.js:
'use strict'; import gulp from 'gulp'; import mail from './builder/tasks/mail'; gulp.task('mail', mail);
builder/tasks/mail.js:
'use strict'; import gulp from 'gulp'; import stylesheets from './mail/stylesheets'; import templates from './mail/templates'; import clean from './mail/clean'; const mail = gulp.series(clean, stylesheets, templates); export default mail;
builder/tasks/mail/stylesheets.js
'use strict'; import gulp from 'gulp'; import config from 'config'; import rename from 'gulp-rename'; import postcss from 'gulp-postcss'; import autoprefixer from 'autoprefixer'; import less from 'gulp-less'; const stylesheetsPath = config.get('srcPath') + '/mail/stylesheets'; const stylesheetsGlob = stylesheetsPath + '/**/*.less'; const mailStylesheets = () => { return gulp.src(stylesheetsGlob) .pipe(less()) .pipe(postcss([ autoprefixer({browsers: ['last 2 versions']}), ])) .pipe(gulp.dest(stylesheetsPath)); }; export default mailStylesheets;
builder/tasks/mail/templates.js:
'use strict'; import gulp from 'gulp'; import config from 'config'; import pug from 'gulp-pug'; import rename from 'gulp-rename'; import juice from 'premailer-gulp-juice'; const templatesPath = config.get('srcPath') + '/mail'; const mailPath = config.get('mailPath'); const templatesGlob = templatesPath + '/**/*.pug'; const mailTemplates = () => { return gulp.src(templatesGlob) .pipe(rename(path => { path.extname = '.html'; })) .pipe(pug({ client: false })) .pipe(juice({ webResources: { relativeTo: templatesPath, images: 100, strict: true } })) .pipe(gulp.dest(mailPath)); }; export default mailTemplates;
'use strict'; import del from 'del'; import gutil from 'gulp-util'; const clean = done => { return del([ 'mail/*.html', 'src/mail/stylesheets/*.css' ]).then(() => { gutil.log(gutil.colors.green('Delete src/mail/stylesheets/*.css and mail/*.html')); done(); }); }; export default clean;
Типичный шаблон выглядит так (generic.pug):
include base.pug +base tr(height='74') td.b-mail__table-row--heading(align='left', valign='top') Привет, tr td(align='left', valign='top') | <%== $html %>
Где base.pug:
mixin base(icon, alreadyEncoded) doctype html head meta(charset="utf8") link(rel="stylesheet", href="/stylesheets/mail.css") body table(width='100%', border='0', cellspacing='0', cellpadding='0') tbody tr td.b-mail(align='center', valign='top', bgcolor='#ffffff') br br table(width='750', border='0', cellspacing='0', cellpadding='0') tbody.b-mail__table tr.b-mail__table-row(height='89') tr.b-mail__table-row td(align='left', valign='top', width='70') img(src='/images/logo.jpg') td(align='left', valign='top') table(width='480', border='0', cellspacing='0', cellpadding='0') tbody if block block td(align='right', valign='top') if alreadyEncoded img.fixed(src!=icon, data-inline-ignore) else if icon img.fixed(src!=icon) br br tr td(align='center', valign='top')
Собственно, болванка готова, шаблоны компилируются. Формирование модуля config тривиально и необязательно.
gulp mail
ViewAction
Многие почтовые клиенты, такие, как GMail/Inbox, поддерживают специальные действия в режиме просмотра сообщений. Внедрить их проще простого, добавив в содержимое сообщения следующие тэги:
div(itemscope, itemtype="http://schema.org/EmailMessage") div(itemprop="action", itemscope, itemtype="http://schema.org/ViewAction") link(itemprop="url", href="https://github.com/imlucas/gulp-juice/pull/9") meta(itemprop="name", content="View Pull Request") meta(itemprop="description", content="View this Pull Request on GitHub")
ссылка на оригинал статьи https://habrahabr.ru/post/317810/
Добавить комментарий