diff --git a/.gitignore b/.gitignore index c2c30d1..47f0a28 100644 --- a/.gitignore +++ b/.gitignore @@ -31,3 +31,4 @@ node_modules .DS_Store public/styles/*.css +nodemailer.config.js diff --git a/keystone.js b/keystone.js index 017726f..29ab427 100644 --- a/keystone.js +++ b/keystone.js @@ -41,7 +41,7 @@ keystone.set('locals', { editable: keystone.content.editable, // Pug options - pretty: false, + pretty: false /* * Keep around for reference * Filters might be useful, but they don't work on dynamic content diff --git a/models/Enquiry.js b/models/Enquiry.js index 87e9d6a..7af9940 100644 --- a/models/Enquiry.js +++ b/models/Enquiry.js @@ -1,5 +1,9 @@ var keystone = require('keystone'); +var Email = require('keystone-email') var Types = keystone.Field.Types; +var nodemailerConfig = require('../nodemailer.config.js'); +var path = require('path'); +var util = require('util'); /** * Enquiry Model @@ -37,21 +41,52 @@ Enquiry.schema.post('save', function () { Enquiry.schema.methods.sendNotificationEmail = function (callback) { if (typeof callback !== 'function') { - callback = function () {}; + callback = function (err, response) { + /* Keep for debugging */ + /* + console.log(util.inspect(err, { + showHidden: false, + depth: null, + colors: true + })); + console.log(util.inspect(response, { + depth: null, + colors: true + })); + */ + }; } var enquiry = this; keystone.list('User').model.find().where('isAdmin', true).exec(function (err, admins) { if (err) return callback(err); - new keystone.Email({ - templateName: 'enquiry-notification', - }).send({ + Email.send('templates/emails/enquiry-notification.pug', { + transport: 'nodemailer' + }, { + // Email locals + // TODO: figure out the right way to get these + _: require('lodash'), + basedir: path.join(__dirname, '../', '/templates/helpers/emails'), + logo_src: '/images/logo-email.gif', + logo_width: 194, + logo_height: 76, + theme: { + email_bg: '#f9f9f9', + link_color: '#2697de', + buttons: { + color: '#fff', + background_color: '#2697de', + border_color: '#1a7cb7', + }, + }, + enquiry: enquiry + }, { to: admins, from: { name: 'National Go Center', email: 'contact@national-go-center.com', }, subject: 'New Enquiry for National Go Center', - enquiry: enquiry, + nodemailerConfig: nodemailerConfig }, callback); }); }; diff --git a/nodemailer.config.example.js b/nodemailer.config.example.js new file mode 100644 index 0000000..997e05a --- /dev/null +++ b/nodemailer.config.example.js @@ -0,0 +1,12 @@ +/* + Rename to nodemailer.config.js and add the api_key, which you can get from Nate Eagle + */ + +var smtpConfig = { + transport: 'SendGrid', + auth: { + api_key: '' + }, +}; + +module.exports = smtpConfig; diff --git a/package.json b/package.json index fbaeb83..4144d45 100644 --- a/package.json +++ b/package.json @@ -8,10 +8,13 @@ "dotenv": "^2.0.0", "fast-feed": "^1.5.5", "keystone": "^4.0.0-beta.4", + "keystone-email": "https://github.com/keystonejs/keystone-email.git", "lodash": "^4.13.1", "node-sass": "^3.8.0", "node-sass-middleware": "^0.9.7", "node-supervisor": "^1.0.2", + "nodemailer": "^2.7.0", + "nodemailer-sendgrid-transport": "https://github.com/starchup/nodemailer-sendgrid-transport", "pug": "^2.0.0-beta6", "restart": "0.0.4", "wgo": "^3.0.0-alpha.1" diff --git a/templates/emails/enquiry-notification.pug b/templates/emails/enquiry-notification.pug index 9e774c8..18b6df2 100644 --- a/templates/emails/enquiry-notification.pug +++ b/templates/emails/enquiry-notification.pug @@ -1,8 +1,7 @@ extends /layouts/default block body-contents - h1 Hi *|first_name|*, - p.text-larger An enquiry was just submitted to #{brand}: + p.text-larger New enquiry from the National Go Center site: if enquiry.name.full || enquiry.email p.text-larger From if enquiry.name.full @@ -21,4 +20,4 @@ block body-contents .text-larger !{enquiry.message.html} p.text-muted Sent #{enquiry._.createdAt.format()} p   - +button({ url: '/keystone/enquiries/' + enquiry.id, label: 'Open Keystone' }) + a(href='http://nationalgocenter.org/keystone/enquiries/' + enquiry.id) Open Keystone diff --git a/templates/helpers/emails/layouts/default.pug b/templates/helpers/emails/layouts/default.pug new file mode 100644 index 0000000..56a413b --- /dev/null +++ b/templates/helpers/emails/layouts/default.pug @@ -0,0 +1,41 @@ +include ../mixins/button + +doctype strict +head + meta(http-equiv="Content-Type", content="text/html; charset=utf-8") + meta(name="viewport" content="width=device-width") + include styles/default + +body: table.body: tr: td(class="center", align="center", valign="top"): center + + //- HEADER + //-table.row.row-header: tr: td(align="center").center: center + table.container: tr: td.wrapper.last + block header + if logo_src || logo + table.twelve.columns: tr + td(align="center").center: center + img(src=logo_src || logo, width=logo_width, height=logo_height).header__logo + td.expander + else + span= brand + + //- BODY + table.row.row-body: tr: td(align="center").center: center + table.container: tr: td + block body + table.row: tr: td.wrapper.last + table.twelve.columns: tr + td.text-pad + block body-contents + td.expander + + //- FOOTER + table.row.row-footer: tr: td(align="center").center: center + table.container: tr: td + block footer + table.row: tr: td.wrapper.last + table.twelve.columns: tr + td.text-pad + block footer-contents + td.expander diff --git a/templates/helpers/emails/layouts/styles/default.pug b/templates/helpers/emails/layouts/styles/default.pug new file mode 100644 index 0000000..6232112 --- /dev/null +++ b/templates/helpers/emails/layouts/styles/default.pug @@ -0,0 +1,111 @@ +//- Variables +//- ------------------------------ +- if (!theme.email_bg) theme.email_bg = '#fafafa'; +- if (!theme.body_bg) theme.body_bg = '#fff'; +- if (!theme.body_border_color) theme.body_border_color = '#ccc'; +- if (!theme.link_color) theme.link_color = '#08c'; +- if (!theme.link_hover_color) theme.link_hover_color = '#08c'; +- if (!theme.text_color) theme.text_color = '#333'; +- if (!theme.text_muted) theme.text_muted = '#999'; + + + +style(type="text/css"). + + /* resets */ + * { + box-sizing: border-box; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + } + + + + /* main */ + body { + background-color: #{theme.email_bg}; + } + body, table.body, h1, h2, h3, h4, h5, h6, p { + color: #{theme.text_color}; + } + a { + color: #{theme.link_color}; + } + a:hover, + a:focus { + color: #{theme.link_hover_color}; + } + a:active { + color: #{theme.link_color}; + } + a:visited { + color: #{theme.link_color}; + } + .text-larger, .text-larger p {font-size: 16px; line-height:22px;} + + + /* helpers */ + .text-muted { color: #{theme.text_muted}; } + .text-left { text-align: left; } + .text-center { text-align: center; } + .text-right { text-align: right; } + + + + /* header */ + .row-header { + text-align: center; + } + .header__logo { + float: none; + } + + + + /* body */ + .row-body .container { + background-color: #{theme.body_bg}; + border-width: 3px 1px 1px; + border-style: solid; + border-color: #{theme.link_color} #{theme.body_border_color} #{theme.body_border_color}; + } + + + + + /* footer */ + .row-footer {} + + + + /* + COMPONENTS + ------------------------------ + */ + + + /* info table */ + @media only screen and (min-width: 600px) { + .info-table td:first-child { + width: 100px; + } + } + + + + + /* + MEDIA QUERIES + ------------------------------ + */ + + @media only screen and (max-width: 600px) { + + /* ink seems to have missed this */ + table, + tr, + td, + tbody { + display: block; + } + } diff --git a/templates/helpers/emails/layouts/styles/ink.pug b/templates/helpers/emails/layouts/styles/ink.pug new file mode 100644 index 0000000..fc854e8 --- /dev/null +++ b/templates/helpers/emails/layouts/styles/ink.pug @@ -0,0 +1,651 @@ +- var padding_base = '15px'; + +style(type="text/css"). + /********************************************** + * Ink v1.0.4 - Copyright 2013 ZURB Inc * + **********************************************/ + + /* Client-specific Styles & Reset */ + + #outlook a { + padding:0; + } + + body{ + width:100% !important; + -webkit-text-size-adjust:100%; + -ms-text-size-adjust:100%; + margin:0; + padding:0; + } + + .ExternalClass { + width:100%; + } + + .ExternalClass, + .ExternalClass p, + .ExternalClass span, + .ExternalClass font, + .ExternalClass td, + .ExternalClass div { + line-height: 100%; + } + + #backgroundTable { + margin:0; + padding:0; + width:100% !important; + line-height: 100% !important; + } + + img { + outline:none; + text-decoration:none; + -ms-interpolation-mode: bicubic; + width: auto; + max-width: 100%; + float: left; + clear: both; + display: block; + } + + center { + width: 100%; + min-width: 580px; + } + + a img { + border: none; + } + + p { + margin: 0 0 10px 0; + } + + table { + border-spacing: 0; + border-collapse: collapse; + } + + td { + word-break: break-word; + -webkit-hyphens: auto; + -moz-hyphens: auto; + hyphens: auto; + border-collapse: collapse !important; + } + + table, tr, td { + padding: 0; + vertical-align: top; + text-align: left; + } + + hr { + color: #d9d9d9; + background-color: #d9d9d9; + height: 1px; + border: none; + } + + /* Responsive Grid */ + + table.body { + height: 100%; + width: 100%; + } + + table.container { + width: 580px; + margin: 0 auto; + text-align: inherit; + } + + table.row { + padding: 0px; + width: 100%; + position: relative; + } + + table.container table.row { + display: block; + } + + td.wrapper { + padding: #{padding_base} 20px 0px 0px; + position: relative; + } + + table.columns, + table.column { + margin: 0 auto; + } + + table.columns td, + table.column td { + padding: 0px 0px #{padding_base}; + } + + table.columns td.sub-columns, + table.column td.sub-columns, + table.columns td.sub-column, + table.column td.sub-column { + padding-right: #{padding_base}; + } + + td.sub-column, td.sub-columns { + min-width: 0px; + } + + table.row td.last, + table.container td.last { + padding-right: 0px; + } + + table.one { width: 30px; } + table.two { width: 80px; } + table.three { width: 130px; } + table.four { width: 180px; } + table.five { width: 230px; } + table.six { width: 280px; } + table.seven { width: 330px; } + table.eight { width: 380px; } + table.nine { width: 430px; } + table.ten { width: 480px; } + table.eleven { width: 530px; } + table.twelve { width: 580px; } + + table.one center { min-width: 30px; } + table.two center { min-width: 80px; } + table.three center { min-width: 130px; } + table.four center { min-width: 180px; } + table.five center { min-width: 230px; } + table.six center { min-width: 280px; } + table.seven center { min-width: 330px; } + table.eight center { min-width: 380px; } + table.nine center { min-width: 430px; } + table.ten center { min-width: 480px; } + table.eleven center { min-width: 530px; } + table.twelve center { min-width: 580px; } + + .body .columns td.one, + .body .column td.one, { width: 8.333333% !important; } + .body .columns td.two, + .body .column td.two { width: 16.666666% !important; } + .body .columns td.three, + .body .column td.three { width: 25% !important; } + .body .columns td.four, + .body .column td.four { width: 33.333333% !important; } + .body .columns td.five, + .body .column td.five { width: 41.666666% !important; } + .body .columns td.six, + .body .column td.six { width: 50% !important; } + .body .columns td.seven, + .body .column td.seven { width: 58.333333% !important; } + .body .columns td.eight, + .body .column td.eight { width: 66.666666% !important; } + .body .columns td.nine, + .body .column td.nine { width: 75% !important; } + .body .columns td.ten, + .body .column td.ten { width: 83.333333% !important; } + .body .columns td.eleven, + .body .column td.eleven { width: 91.666666% !important; } + .body .columns td.twelve, + .body .column td.twelve { width: 100% !important; } + + td.offset-by-one { padding-left: 50px; } + td.offset-by-two { padding-left: 100px; } + td.offset-by-three { padding-left: 150px; } + td.offset-by-four { padding-left: 200px; } + td.offset-by-five { padding-left: 250px; } + td.offset-by-six { padding-left: 300px; } + td.offset-by-seven { padding-left: 350px; } + td.offset-by-eight { padding-left: 400px; } + td.offset-by-nine { padding-left: 450px; } + td.offset-by-ten { padding-left: 500px; } + td.offset-by-eleven { padding-left: 550px; } + + td.sub-offset-by-one { padding-left: 5.172413% !important; } + td.sub-offset-by-two { padding-left: 13.793102% !important; } + td.sub-offset-by-three { padding-left: 22.413791% !important; } + td.sub-offset-by-four { padding-left: 31.034480% !important; } + td.sub-offset-by-five { padding-left: 39.655169% !important; } + td.sub-offset-by-six { padding-left: 48.275858% !important; } + td.sub-offset-by-seven { padding-left: 56.896547% !important; } + td.sub-offset-by-eight { padding-left: 65.517236% !important; } + td.sub-offset-by-nine { padding-left: 74.137925% !important; } + td.sub-offset-by-ten { padding-left: 82.758614% !important; } + td.sub-offset-by-eleven { padding-left: 91.379303% !important; } + + td.expander { + visibility: hidden; + width: 0px; + padding: 0 !important; + } + + table.columns .text-pad, + table.column .text-pad { + padding-left: #{padding_base}; + padding-right: #{padding_base}; + } + + table.columns .left-text-pad, + table.columns .text-pad-left, + table.column .left-text-pad, + table.column .text-pad-left { + padding-left: #{padding_base}; + } + + table.columns .right-text-pad, + table.columns .text-pad-right, + table.column .right-text-pad, + table.column .text-pad-right { + padding-right: #{padding_base}; + } + + /* Block Grid */ + + .block-grid { + width: 100%; + max-width: 580px; + } + + .block-grid td { + display: inline-block; + padding:10px; + } + + .two-up td { + width:270px; + } + + .three-up td { + width:173px; + } + + .four-up td { + width:125px; + } + + .five-up td { + width:96px; + } + + .six-up td { + width:76px; + } + + .seven-up td { + width:62px; + } + + .eight-up td { + width:52px; + } + + /* Alignment & Visibility Classes */ + + table.center, td.center { + text-align: center; + } + + h1.center, + h2.center, + h3.center, + h4.center, + h5.center, + h6.center { + text-align: center; + } + + span.center { + display: block; + width: 100%; + text-align: center; + } + + img.center { + margin: 0 auto; + float: none; + } + + .show-for-small, + .hide-for-desktop { + display: none; + } + + /* Typography */ + + body, table.body, h1, h2, h3, h4, h5, h6, p { + color: #222222; + font-family: "Helvetica", "Arial", sans-serif; + font-weight: normal; + padding:0; + margin: 0; + text-align: left; + line-height: 1.3; + } + + h1, h2, h3, h4, h5, h6 { + word-break: normal; + margin-bottom: 10px; + } + + h1 {font-size: 34px;} + h2 {font-size: 30px;} + h3 {font-size: 26px;} + h4 {font-size: 22px;} + h5 {font-size: 20px;} + h6 {font-size: 18px;} + body, table.body, p {font-size: 14px; line-height:19px;} + + p { + padding-bottom: #{padding_base}; + } + + small { + font-size: 10px; + } + + /* + a { + color: #2ba6cb; + text-decoration: none; + } + a:hover { + color: #2795b6; + } + a:active { + color: #2795b6; + } + a:visited { + color: #2ba6cb; + } + */ + + h1 a, + h2 a, + h3 a, + h4 a, + h5 a, + h6 a { + color: #2ba6cb; + } + + h1 a:active, + h2 a:active, + h3 a:active, + h4 a:active, + h5 a:active, + h6 a:active { + color: #2ba6cb !important; + } + + h1 a:visited, + h2 a:visited, + h3 a:visited, + h4 a:visited, + h5 a:visited, + h6 a:visited { + color: #2ba6cb !important; + } + + /* Panels */ + + td.panel { + background: #f2f2f2; + border: 1px solid #d9d9d9; + padding: 10px !important; + } + + /* Buttons */ + + table.button, + table.tiny-button, + table.small-button, + table.medium-button, + table.large-button { + width: 100%; + overflow: hidden; + } + + table.button td, + table.tiny-button td, + table.small-button td, + table.medium-button td, + table.large-button td { + display: block; + width: auto !important; + text-align: center; + background: #2ba6cb; + border: 1px solid #2284a1; + color: #ffffff; + padding: 8px 0; + } + + table.tiny-button td { + padding: 5px 0 4px; + } + + table.small-button td { + padding: 8px 0 7px; + } + + table.medium-button td { + padding: 12px 0 10px; + } + + table.large-button td { + padding: 21px 0 18px; + } + + table.button td a, + table.tiny-button td a, + table.small-button td a, + table.medium-button td a, + table.large-button td a { + font-weight: bold; + text-decoration: none; + font-family: Helvetica, Arial, sans-serif; + color: #ffffff; + font-size: 16px; + } + + table.tiny-button td a { + font-size: 12px; + font-weight: normal; + } + + table.small-button td a { + font-size: 16px; + } + + table.medium-button td a { + font-size: 20px; + } + + table.large-button td a { + font-size: 24px; + } + + table.button:hover td, + table.button:visited td, + table.button:active td { + background: #2795b6 !important; + } + + table.button:hover td a, + table.button:visited td a, + table.button:active td a { + color: #fff !important; + } + + table.button:hover td, + table.tiny-button:hover td, + table.small-button:hover td, + table.medium-button:hover td, + table.large-button:hover td { + background: #2795b6 !important; + } + + table.button:hover td a, + table.button:active td a, + table.button td a:visited, + table.tiny-button:hover td a, + table.tiny-button:active td a, + table.tiny-button td a:visited, + table.small-button:hover td a, + table.small-button:active td a, + table.small-button td a:visited, + table.medium-button:hover td a, + table.medium-button:active td a, + table.medium-button td a:visited, + table.large-button:hover td a, + table.large-button:active td a, + table.large-button td a:visited { + color: #ffffff !important; + } + + table.secondary td { + background: #e9e9e9; + border-color: #d0d0d0; + color: #555; + } + + table.secondary td a { + color: #555; + } + + table.secondary:hover td { + background: #d0d0d0 !important; + color: #555; + } + + table.secondary:hover td a, + table.secondary td a:visited, + table.secondary:active td a { + color: #555 !important; + } + + table.success td { + background: #5da423; + border-color: #457a1a; + } + + table.success:hover td { + background: #457a1a !important; + } + + table.alert td { + background: #c60f13; + border-color: #970b0e; + } + + table.alert:hover td { + background: #970b0e !important; + } + + table.radius td { + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; + } + + table.round td { + -webkit-border-radius: 500px; + -moz-border-radius: 500px; + border-radius: 500px; + } + + /* Outlook First */ + + body.outlook p { + display: inline !important; + } + + /* Media Queries */ + + @media only screen and (max-width: 600px) { + + table[class="body"] img { + width: auto !important; + height: auto !important; + } + + table[class="body"] center { + min-width: 0 !important; + } + + table[class="body"] .container { + width: 95% !important; + } + + table[class="body"] .row { + width: 100% !important; + display: block !important; + } + + table[class="body"] .wrapper { + display: block !important; + padding-right: 0 !important; + } + + table[class="body"] .columns, + table[class="body"] .column { + table-layout: fixed !important; + float: none !important; + width: 100% !important; + padding-right: 0px !important; + padding-left: 0px !important; + display: block !important; + } + + table[class="body"] .wrapper.first .columns, + table[class="body"] .wrapper.first .column { + display: table !important; + } + + table[class="body"] table.columns td, + table[class="body"] table.column td { + width: 100% !important; + } + + table[class="body"] td.offset-by-one, + table[class="body"] td.offset-by-two, + table[class="body"] td.offset-by-three, + table[class="body"] td.offset-by-four, + table[class="body"] td.offset-by-five, + table[class="body"] td.offset-by-six, + table[class="body"] td.offset-by-seven, + table[class="body"] td.offset-by-eight, + table[class="body"] td.offset-by-nine, + table[class="body"] td.offset-by-ten, + table[class="body"] td.offset-by-eleven { + padding-left: 0 !important; + } + + table[class="body"] .expander { + width: 9999px !important; + } + + table[class="body"] .right-text-pad, + table[class="body"] .text-pad-right { + padding-left: #{padding_base} !important; + } + + table[class="body"] .left-text-pad, + table[class="body"] .text-pad-left { + padding-right: #{padding_base} !important; + } + + table[class="body"] .hide-for-small, + table[class="body"] .show-for-desktop { + display: none !important; + } + + table[class="body"] .show-for-small, + table[class="body"] .hide-for-desktop { + display: inherit !important; + } + } \ No newline at end of file