added email notification support for general smtp and mailgun

This commit is contained in:
Ro 2019-01-16 16:36:30 -05:00
parent 46f2bcf1ec
commit 2bdeb81979
12 changed files with 468 additions and 100 deletions

View file

@ -1,41 +0,0 @@
var express = require('express');
var router = express.Router();
var api_key = 'key-4ef13da32fb39b9d9f0370c9efba7f06';
var domain = 'communique.playvicio.us';
var mailgun = require('mailgun-js')({
apiKey: api_key,
domain: domain
});
router.post('/', function (req, res, next) {
// create reusable transporter object using the default SMTP transport
// setup e-mail data with unicode symbols
var mailOptions = {
from: req.body.email, // sender address
to: 'ro@playvicio.us', // list of receivers
subject: 'Availability Inquiry', // Subject line
text: "Message from: " + req.body.client + " <" + req.body.email + "> - " + req.body.description + " - " + req.body.type
};
mailgun.messages().send(mailOptions, function (error, body) {
if (error) {
res.json({
error: error
});
}
console.log(body);
res.json({
message: "message sent"
});
});
});
module.exports = router;

82
brain/api/mail/mailer.js Normal file
View file

@ -0,0 +1,82 @@
var express = require('express');
var router = express.Router();
var nodemailer = require('nodemailer');
var mg = require('nodemailer-mailgun-transport');
const fs = require('fs-extra');
const pug = require('pug');
router.post('/', function(req, res, next)
{
fs.readJson('config/site-settings.json').then(settings =>
{
let transport = ''
switch (settings.email.active)
{
case "option-smtp":
var auth = {
host: settings.email.smtp.domain,
port: 587,
secure: false,
auth:
{
type:"login",
email: settings.email.smtp,
password: settings.email.smtp.password
}
}
transport = nodemailer.createTransport((auth));
break;
case "option-mg":
var auth = {
auth:
{
api_key: settings.email.mailgun['api-key'],
domain: settings.email.mailgun.domain
}
}
transport = nodemailer.createTransport(mg(auth));
break
}
let render = pug.compileFile('themes/dash/email/base.pug');
let html = render(
{
title: settings.title,
header: "a note from " + settings.title,
content: req.body.content,
footer: "powered by fipamo"
})
transport.sendMail(
{
from: 'control@playvico.us',
to: 'are0h@protonmail.com', // An array if you have multiple recipients.
subject: 'Hey beautiful',
//You can use "html:" to send HTML email content. It's magic!
html: html
//You can use "text:" to send plain-text content. It's oldschool!
//text: 'Mailgun rocks, pow pow!'
}, function(err, info)
{
if (err)
{
console.log(err)
res.json(
{
message: "MAIL ERROR",
desc: err
});
}
else
{
console.log(info)
res.json(
{
message: "MAIL SENT",
desc: info
});
}
});
}).catch(err =>
{
console.error(err)
})
});
module.exports = router;

View file

@ -49,11 +49,12 @@ var navDashboard = require('./routes/back/dash_nav');
//api
var postLibrary = require('./api/content/posts');
var settings = require('./api/content/settings');
var mailer = require('./api/content/mailer');
var mailer = require('./api/mail/mailer');
// API PATHS
app.use('/api/post', postLibrary);
app.use('/api/settings', settings);
app.use('/api/mail', mailer);
// PAGES
app.use('/', front);
app.use('/@/dashboard', back);

139
content/fipamo_email.html Executable file
View file

@ -0,0 +1,139 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Email title or subject</title>
<style type="text/css">
/* reset */
#outlook a {
padding: 0;
}
/* Force Outlook to provide a "view in browser" menu link. */
.ExternalClass {
width: 100%;
}
/* Force Hotmail to display emails at full width */
.ExternalClass,
.ExternalClass p,
.ExternalClass span,
.ExternalClass font,
.ExternalClass td,
.ExternalClass div {
line-height: 100%;
}
/* Forces Hotmail to display normal line spacing. More on that: http://www.emailonacid.com/forum/viewthread/43/ */
p {
margin: 0;
padding: 0;
font-size: 0px;
line-height: 0px;
}
/* squash Exact Target injected paragraphs */
table td {
border-collapse: collapse;
}
/* Outlook 07, 10 padding issue fix */
table {
border-collapse: collapse;
mso-table-lspace: 0pt;
mso-table-rspace: 0pt;
}
/* remove spacing around Outlook 07, 10 tables */
/* bring inline */
img {
display: block;
outline: none;
text-decoration: none;
-ms-interpolation-mode: bicubic;
}
a img {
border: none;
}
a {
text-decoration: none;
color: #000001;
}
/* text link */
a.phone {
text-decoration: none;
color: #000001 !important;
pointer-events: auto;
cursor: default;
}
/* phone link, use as wrapper on phone numbers */
span {
font-size: 13px;
line-height: 17px;
font-family: monospace;
color: #000001;
}
</style>
<!--[if gte mso 9]>
<style>
/* Target Outlook 2007 and 2010 */
</style>
<![endif]-->
</head>
<body style="width:100%; margin:0; padding:0; -webkit-text-size-adjust:100%; -ms-text-size-adjust:100%; background: #161d23;">
<!-- body wrapper -->
<table cellpadding="0" cellspacing="0" border="0" style="margin:0; padding:0; width:100%; line-height: 100% !important;">
<tr>
<td valign="top">
<!-- edge wrapper -->
<table cellpadding="0" cellspacing="0" border="0" align="center" width="600" style="background: #374857;">
<tr>
<td valign="top" style="vertical-align: top;">
<!-- ///////////////////////////////////////////////////// -->
<table cellpadding="0" cellspacing="0" border="0" align="center" style="width:100%">
<tr>
<td valign="top" style="vertical-align: top;text-align: center; padding: 10px">
<span style="font-family: Arial,Helvetica Neue,Helvetica,sans-serif; color:#f5ab35; font-size:20px; font-weight: bold;">
HEADER
</span>
</td>
</tr>
<tr>
<td valign="top" style="vertical-align: top; background: #161d23; padding:10px;">
<span style="font-family: Arial,Helvetica Neue,Helvetica,sans-serif; color:#cecece; font-size:16px;">
BIG BODY
</span>
</td>
</tr>
<tr>
<td valign="top" style="vertical-align: top; padding: 10px;">
<span style="font-family: Arial,Helvetica Neue,Helvetica,sans-serif; color:#b2cce5; font-size:12px;">
footer text
</span>
</td>
</tr>
</table>
<!-- //////////// -->
</td>
</tr>
</table>
<!-- / edge wrapper -->
</td>
</tr>
</table>
<!-- / page wrapper -->
</body>
</html>

43
package-lock.json generated
View file

@ -1090,6 +1090,11 @@
"resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz",
"integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg=="
},
"async-series": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/async-series/-/async-series-0.0.1.tgz",
"integrity": "sha1-UCTXV/OLBCluH4ofyko2S1fcUuw="
},
"asynckit": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
@ -4576,11 +4581,26 @@
"resolved": "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.1.tgz",
"integrity": "sha512-eWw5r+PYICtEBgrBE5hhlT6aAa75f411bgDz/ZL2KZqYV03USvucsxcHUIlGTDTECs1eunpI7HOV7U+WLDvNdQ=="
},
"lodash.pickby": {
"version": "4.6.0",
"resolved": "https://registry.npmjs.org/lodash.pickby/-/lodash.pickby-4.6.0.tgz",
"integrity": "sha1-feoh2MGNdwOifHBMFdO4SmfjOv8="
},
"lodash.some": {
"version": "4.6.0",
"resolved": "https://registry.npmjs.org/lodash.some/-/lodash.some-4.6.0.tgz",
"integrity": "sha1-G7nzFO9ri63tE7VJFpsqlF62jk0="
},
"lodash.sortby": {
"version": "4.7.0",
"resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz",
"integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg="
},
"lodash.startswith": {
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/lodash.startswith/-/lodash.startswith-4.2.1.tgz",
"integrity": "sha1-xZjErc4YiiflMUVzHNxsDnF3YAw="
},
"longest": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz",
@ -4992,6 +5012,29 @@
"resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-4.6.8.tgz",
"integrity": "sha512-A3s7EM/426OBIZbLHXq2KkgvmKbn2Xga4m4G+ZUA4IaZvG8PcZXrFh+2E4VaS2o+emhuUVRnzKN2YmpkXQ9qwA=="
},
"nodemailer-mailgun-transport": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/nodemailer-mailgun-transport/-/nodemailer-mailgun-transport-1.4.0.tgz",
"integrity": "sha512-oLNmye2Km8xALu+U2AJh+U+kpBXePNP5KhSC0QSHauaSZTtKq/kaaYtzGhnzDCur+cyELlWrQIiVF2vAGn6PIg==",
"requires": {
"async-series": "0.0.1",
"consolidate": "^0.14.0",
"lodash.pickby": "^4.3.0",
"lodash.some": "^4.3.0",
"lodash.startswith": "^4.0.1",
"mailgun-js": "^0.18.0"
},
"dependencies": {
"consolidate": {
"version": "0.14.5",
"resolved": "https://registry.npmjs.org/consolidate/-/consolidate-0.14.5.tgz",
"integrity": "sha1-WiUEe8dvcwcmZ8jLUsmJiI9JTGM=",
"requires": {
"bluebird": "^3.1.1"
}
}
}
},
"nopt": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.1.tgz",

View file

@ -43,6 +43,7 @@
"morgan": "latest",
"multer": "latest",
"nodemailer": "latest",
"nodemailer-mailgun-transport": "^1.4.0",
"pg": "^7.5.0",
"pg-hstore": "^2.3.2",
"pug": "latest",

View file

@ -8445,7 +8445,64 @@ function () {
}();
exports.default = SettingsActions;
},{"../../../../../brain//tools/utilities/DataUtils":"../../../../brain/tools/utilities/DataUtils.js","../../../../../brain//tools/utilities/StringUtils":"../../../../brain/tools/utilities/StringUtils.js","../../../../../brain/tools/utilities/DateUtils":"../../../../brain/tools/utilities/DateUtils.js","../../../../../brain/tools/events/DataEvent":"../../../../brain/tools/events/DataEvent.js"}],"controllers/SettingsIndex.js":[function(require,module,exports) {
},{"../../../../../brain//tools/utilities/DataUtils":"../../../../brain/tools/utilities/DataUtils.js","../../../../../brain//tools/utilities/StringUtils":"../../../../brain/tools/utilities/StringUtils.js","../../../../../brain/tools/utilities/DateUtils":"../../../../brain/tools/utilities/DateUtils.js","../../../../../brain/tools/events/DataEvent":"../../../../brain/tools/events/DataEvent.js"}],"actions/Mailer.js":[function(require,module,exports) {
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _DataUtils = _interopRequireWildcard(require("../../../../../brain//tools/utilities/DataUtils"));
var DataEvent = _interopRequireWildcard(require("../../../../../brain/tools/events/DataEvent"));
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
var Mailer =
/*#__PURE__*/
function () {
//--------------------------
// constructor
//--------------------------
function Mailer() {
_classCallCheck(this, Mailer);
this.dataUtils = new _DataUtils.default();
} //--------------------------
// methods
//--------------------------
_createClass(Mailer, [{
key: "sendMail",
value: function sendMail() {
var self = this;
var mailData = {
content: "This is a test email"
};
self.dataUtils.request('/api/mail', DataEvent.SETTINGS_UPDATED, _DataUtils.REQUEST_TYPE_POST, _DataUtils.CONTENT_TYPE_JSON, mailData).then(function (response) {
console.log(response);
}).catch(function (err) {
console.log(err);
});
} //--------------------------
// event handlers
//--------------------------
}]);
return Mailer;
}();
exports.default = Mailer;
},{"../../../../../brain//tools/utilities/DataUtils":"../../../../brain/tools/utilities/DataUtils.js","../../../../../brain/tools/events/DataEvent":"../../../../brain/tools/events/DataEvent.js"}],"controllers/SettingsIndex.js":[function(require,module,exports) {
"use strict";
Object.defineProperty(exports, "__esModule", {
@ -8459,6 +8516,8 @@ var _DataUtils = _interopRequireWildcard(require("../../../../../brain/tools/uti
var DataEvent = _interopRequireWildcard(require("../../../../../brain/tools/events/DataEvent"));
var _Mailer = _interopRequireDefault(require("../actions/Mailer"));
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
@ -8480,6 +8539,7 @@ function () {
this.start();
this.dataUtils = new _DataUtils.default();
this.mailer = new _Mailer.default();
} //--------------------------
// methods
//--------------------------
@ -8515,6 +8575,9 @@ function () {
document.getElementById("privacy-toggle").addEventListener("click", function (e) {
return _this.togglePrivacy(e);
});
document.getElementById("send-mail").addEventListener("click", function (e) {
return _this.handleMailer(e);
}); //handle theme toggle
var themeBtns = document.querySelectorAll('.theme-select');
@ -8551,6 +8614,11 @@ function () {
e.target.innerHTML = "SITE IS PRIVATE";
}
}
}, {
key: "handleMailer",
value: function handleMailer() {
this.mailer.sendMail();
}
}, {
key: "handleThemes",
value: function handleThemes(e) {
@ -8626,7 +8694,7 @@ function () {
}();
exports.default = SettingsIndex;
},{"../actions/SettingsActions":"actions/SettingsActions.js","../../../../../brain/tools/utilities/DataUtils":"../../../../brain/tools/utilities/DataUtils.js","../../../../../brain/tools/events/DataEvent":"../../../../brain/tools/events/DataEvent.js"}],"actions/NavActions.js":[function(require,module,exports) {
},{"../actions/SettingsActions":"actions/SettingsActions.js","../../../../../brain/tools/utilities/DataUtils":"../../../../brain/tools/utilities/DataUtils.js","../../../../../brain/tools/events/DataEvent":"../../../../brain/tools/events/DataEvent.js","../actions/Mailer":"actions/Mailer.js"}],"actions/NavActions.js":[function(require,module,exports) {
"use strict";
Object.defineProperty(exports, "__esModule", {

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,94 @@
doctype strict
head
meta(http-equiv='Content-Type' content='text/html; charset=utf-8')
meta(name='viewport' content='width=device-width, initial-scale=1.0')
title #{title}
style(type='text/css').
/* reset */
#outlook a {
padding: 0;
}
/* Force Outlook to provide a "view in browser" menu link. */
.ExternalClass {
width: 100%;
}
/* Force Hotmail to display emails at full width */
.ExternalClass,
.ExternalClass p,
.ExternalClass span,
.ExternalClass font,
.ExternalClass td,
.ExternalClass div {
line-height: 100%;
}
/* Forces Hotmail to display normal line spacing. More on that: http://www.emailonacid.com/forum/viewthread/43/ */
p {
margin: 0;
padding: 0;
font-size: 0px;
line-height: 0px;
}
/* squash Exact Target injected paragraphs */
table td {
border-collapse: collapse;
}
/* Outlook 07, 10 padding issue fix */
table {
border-collapse: collapse;
mso-table-lspace: 0pt;
mso-table-rspace: 0pt;
}
/* remove spacing around Outlook 07, 10 tables */
/* bring inline */
img {
display: block;
outline: none;
text-decoration: none;
-ms-interpolation-mode: bicubic;
}
a img {
border: none;
}
a {
text-decoration: none;
color: #000001;
}
/* text link */
a.phone {
text-decoration: none;
color: #000001 !important;
pointer-events: auto;
cursor: default;
}
/* phone link, use as wrapper on phone numbers */
span {
font-size: 13px;
line-height: 17px;
font-family: monospace;
color: #000001;
}
//if gte mso 9
style.
/* Target Outlook 2007 and 2010 */
// body wrapper
table(cellpadding='0' cellspacing='0' border='0' style='margin:0; padding:0; width:100%; line-height: 100% !important;')
tr
td(valign='top')
// edge wrapper
table(cellpadding='0' cellspacing='0' border='0' align='center' width='600' style='background: #374857;')
tr
td(valign='top' style='vertical-align: top;')
// /////////////////////////////////////////////////////
table(cellpadding='0' cellspacing='0' border='0' align='center' style='width:100%')
tr
td(valign='top' style='vertical-align: top;text-align: center; padding: 10px')
span(style='font-family: Arial,Helvetica Neue,Helvetica,sans-serif; color:#f5ab35; font-size:20px; font-weight: bold;')
| #{header}
tr
td(valign='top' style='vertical-align: top; background: #161d23; padding:10px;')
span(style='font-family: Arial,Helvetica Neue,Helvetica,sans-serif; color:#cecece; font-size:16px;')
| #{content}
tr
td(valign='top' style='vertical-align: top; padding: 10px;')
span(style='font-family: Arial,Helvetica Neue,Helvetica,sans-serif; color:#b2cce5; font-size:12px;')
| #{footer}

View file

@ -58,5 +58,6 @@ block main-content
include partials/mailforms
br
button#send-mail SEND MAIL
button#save-toggle SAVE SETTINGS

View file

@ -1,69 +1,41 @@
import Animate from '../tools/effects/Animate.jsx';
import TextEffects from '../tools/effects/TextEffects.jsx';
class Mailer {
import DataUtils,
{
REQUEST_TYPE_GET,
REQUEST_TYPE_PUT,
REQUEST_TYPE_POST,
REQUEST_TYPE_DELETE,
CONTENT_TYPE_JSON,
CONTENT_TYPE_FORM
}
from '../../../../../brain//tools/utilities/DataUtils';
import * as DataEvent from '../../../../../brain/tools/events/DataEvent';
export default class Mailer
{
//--------------------------
// constructor
//--------------------------
constructor(element) {
this.response = element
if (document.getElementById('request-btn')) {
document.getElementById('request-btn').addEventListener("click", f => {
f.preventDefault();
this.sendMail()
})
}
constructor()
{
this.dataUtils = new DataUtils();
}
//--------------------------
// methods
//--------------------------
sendMail()
{
var self = this;
//if(!this.validateForm())
var mailData = []
let requestForm = document.forms.namedItem("request-form");
let serviceType = document.getElementById('service_type')
//console.log(serviceType.options[serviceType.selectedIndex].text);
mailData = {
"email": requestForm.email.value,
"client": requestForm.client.value,
"description": requestForm.description.value,
"type": serviceType.options[serviceType.selectedIndex].text
};
var request = new XMLHttpRequest();
request.open("POST", "/mailer", true);
request.setRequestHeader("Content-type", "application/json")
request.onload = function(oEvent) {
if (request.status == 200) {
let response = JSON.parse(request.response);
if (response.message == "message sent") {
requestForm.reset();
self.response.innerHTML = "HEY. THANKS FOR REACHING OUT. YOU'RE AWESOME"
new TextEffects().scramble(self.response, 50, function () {
});
} else {
//console.log(response.detail);
}
} else {
//console.log(request);
}
};
request.send(JSON.stringify(mailData));
let mailData = {
content: "This is a test email"
}
self.dataUtils.request('/api/mail', DataEvent.SETTINGS_UPDATED, REQUEST_TYPE_POST, CONTENT_TYPE_JSON, mailData).then((response) =>
{
console.log(response)
}).catch((err) =>
{
console.log(err)
})
}
//--------------------------
// event handlers
//--------------------------
}
export {Mailer as default}
}

View file

@ -10,6 +10,7 @@ import DataUtils,
}
from "../../../../../brain/tools/utilities/DataUtils";
import * as DataEvent from '../../../../../brain/tools/events/DataEvent';
import Mailer from '../actions/Mailer';
export default class SettingsIndex
{
//--------------------------
@ -19,6 +20,7 @@ export default class SettingsIndex
{
this.start();
this.dataUtils = new DataUtils();
this.mailer = new Mailer();
}
//--------------------------
// methods
@ -53,6 +55,7 @@ export default class SettingsIndex
}, false);
//handle privacy toggle
document.getElementById("privacy-toggle").addEventListener("click", e=>this.togglePrivacy(e));
document.getElementById("send-mail").addEventListener("click", e=>this.handleMailer(e));
//handle theme toggle
let themeBtns = document.querySelectorAll('.theme-select');
for (var i = 0, length = themeBtns.length; i < length; i++)
@ -83,6 +86,11 @@ export default class SettingsIndex
}
}
handleMailer()
{
this.mailer.sendMail();
}
handleThemes(e){
e.stopPropagation();
e.preventDefault();