Send welcome and unsubscribe confirmation emails
This commit is contained in:
parent
15ed41741e
commit
9e3b42e11c
12 changed files with 189 additions and 33 deletions
|
@ -34,8 +34,6 @@ database="mailtrain"
|
|||
charset="utf8mb4"
|
||||
# enter path for mysql command line application
|
||||
command="mysql"
|
||||
# required database schema version
|
||||
schema_version=1
|
||||
|
||||
[redis]
|
||||
# enable to use Redis session cache or disable if Redis is not installed
|
||||
|
|
16
index.js
16
index.js
|
@ -12,7 +12,6 @@ let sender = require('./services/sender');
|
|||
let importer = require('./services/importer'); // eslint-disable-line global-require
|
||||
let verpServer = require('./services/verp-server'); // eslint-disable-line global-require
|
||||
let testServer = require('./services/test-server'); // eslint-disable-line global-require
|
||||
let settings = require('./lib/models/settings');
|
||||
|
||||
let port = config.www.port;
|
||||
let host = config.www.host;
|
||||
|
@ -34,20 +33,7 @@ let server = http.createServer(app);
|
|||
* Listen on provided port, on all network interfaces.
|
||||
*/
|
||||
|
||||
settings.list(['db_schema_version'], (err, configItems) => {
|
||||
if (err) {
|
||||
throw err;
|
||||
}
|
||||
let dbSchemaVersion = Number(configItems.dbSchemaVersion) || 0;
|
||||
|
||||
if (dbSchemaVersion < config.mysql.schema_version) {
|
||||
log.error('Database', 'Database schema outdated. Run `npm run sql` to upgrade');
|
||||
return process.exit(1);
|
||||
}
|
||||
|
||||
server.listen(port, host);
|
||||
|
||||
});
|
||||
server.listen(port, host);
|
||||
|
||||
server.on('error', err => {
|
||||
if (err.syscall !== 'listen') {
|
||||
|
|
|
@ -182,6 +182,10 @@ module.exports.subscribe = (cid, optInIp, callback) => {
|
|||
subscription = {};
|
||||
}
|
||||
|
||||
subscription.cid = cid;
|
||||
subscription.list = listId;
|
||||
subscription.email = email;
|
||||
|
||||
let optInCountry = geoip.lookupCountry(optInIp) || null;
|
||||
module.exports.insert(listId, {
|
||||
email,
|
||||
|
@ -200,11 +204,7 @@ module.exports.subscribe = (cid, optInIp, callback) => {
|
|||
}
|
||||
connection.query('DELETE FROM confirmations WHERE `cid`=? LIMIT 1', [cid], () => {
|
||||
connection.release();
|
||||
callback(null, {
|
||||
list: listId,
|
||||
cid,
|
||||
email
|
||||
});
|
||||
callback(null, subscription);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -361,8 +361,8 @@ module.exports.get = (listId, cid, callback) => {
|
|||
return callback(null, false);
|
||||
}
|
||||
|
||||
let list = tools.convertKeys(rows[0]);
|
||||
return callback(null, list);
|
||||
let subscription = tools.convertKeys(rows[0]);
|
||||
return callback(null, subscription);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
@ -448,7 +448,7 @@ module.exports.unsubscribe = (listId, email, campaignId, callback) => {
|
|||
return callback(err);
|
||||
}
|
||||
|
||||
connection.query('SELECT id, status FROM `subscription__' + listId + '` WHERE `email`=?', [email], (err, rows) => {
|
||||
connection.query('SELECT * FROM `subscription__' + listId + '` WHERE `email`=?', [email], (err, rows) => {
|
||||
connection.release();
|
||||
if (err) {
|
||||
return callback(err);
|
||||
|
@ -457,8 +457,13 @@ module.exports.unsubscribe = (listId, email, campaignId, callback) => {
|
|||
return callback(null, false);
|
||||
}
|
||||
|
||||
let id = rows[0].id;
|
||||
module.exports.changeStatus(id, listId, campaignId, 2, callback);
|
||||
let subscription = tools.convertKeys(rows[0]);
|
||||
module.exports.changeStatus(subscription.id, listId, campaignId, 2, err => {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
return callback(null, subscription);
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "grunt",
|
||||
"start": "node index.js",
|
||||
"start": "node setup/sql/sql.js && node index.js",
|
||||
"sql": "node setup/sql/sql.js",
|
||||
"sqldump": "node setup/sql/dump.js | sed -e '/^--.*$/d' > setup/sql/mailtrain.sql",
|
||||
"sqldrop": "node setup/sql/drop.js"
|
||||
|
|
|
@ -35,7 +35,7 @@ router.get('/subscribe/:cid', (req, res, next) => {
|
|||
return next(err);
|
||||
}
|
||||
|
||||
settings.list(['defaultHomepage', 'serviceUrl', 'pgpPrivateKey'], (err, configItems) => {
|
||||
settings.list(['defaultHomepage', 'serviceUrl', 'pgpPrivateKey', 'defaultAddress', 'defaultFrom'], (err, configItems) => {
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
|
@ -47,6 +47,45 @@ router.get('/subscribe/:cid', (req, res, next) => {
|
|||
preferences: '/subscription/' + list.cid + '/manage/' + subscription.cid,
|
||||
hasPubkey: !!configItems.pgpPrivateKey
|
||||
});
|
||||
|
||||
fields.list(list.id, (err, fieldList) => {
|
||||
if (err) {
|
||||
return log.error('Fields', err);
|
||||
}
|
||||
|
||||
let encryptionKeys = [];
|
||||
fields.getRow(fieldList, subscription).forEach(field => {
|
||||
if (field.type === 'gpg' && field.value) {
|
||||
encryptionKeys.push(field.value.trim());
|
||||
}
|
||||
});
|
||||
|
||||
mailer.sendMail({
|
||||
from: {
|
||||
name: configItems.defaultFrom,
|
||||
address: configItems.defaultAddress
|
||||
},
|
||||
to: {
|
||||
name: [].concat(subscription.firstName || []).concat(subscription.lastName || []).join(' '),
|
||||
address: subscription.email
|
||||
},
|
||||
subject: list.name + ': Subscription Confirmed',
|
||||
encryptionKeys
|
||||
}, {
|
||||
html: 'emails/subscription-confirmed-html.hbs',
|
||||
text: 'emails/subscription-confirmed-text.hbs',
|
||||
data: {
|
||||
title: list.name,
|
||||
contactAddress: configItems.defaultAddress,
|
||||
preferencesUrl: urllib.resolve(configItems.serviceUrl, '/subscription/' + list.cid + '/manage/' + subscription.cid),
|
||||
unsubscribeUrl: urllib.resolve(configItems.serviceUrl, '/subscription/' + list.cid + '/unsubscribe/' + subscription.cid)
|
||||
}
|
||||
}, err => {
|
||||
if (err) {
|
||||
log.error('Subscription', err.stack);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -362,12 +401,56 @@ router.post('/:lcid/unsubscribe', passport.parseForm, passport.csrfProtection, (
|
|||
|
||||
let email = req.body.email;
|
||||
|
||||
subscriptions.unsubscribe(list.id, email, req.body.campaign, err => {
|
||||
subscriptions.unsubscribe(list.id, email, req.body.campaign, (err, subscription) => {
|
||||
if (err) {
|
||||
req.flash('danger', err.message || err);
|
||||
return res.redirect('/subscription/' + encodeURIComponent(req.params.lcid) + '/unsubscribe/' + encodeURIComponent(req.body.cid) + '?' + tools.queryParams(req.body));
|
||||
}
|
||||
res.redirect('/subscription/' + req.params.lcid + '/unsubscribe-notice');
|
||||
|
||||
fields.list(list.id, (err, fieldList) => {
|
||||
if (err) {
|
||||
return log.error('Fields', err);
|
||||
}
|
||||
|
||||
let encryptionKeys = [];
|
||||
fields.getRow(fieldList, subscription).forEach(field => {
|
||||
if (field.type === 'gpg' && field.value) {
|
||||
encryptionKeys.push(field.value.trim());
|
||||
}
|
||||
});
|
||||
|
||||
settings.list(['defaultHomepage', 'defaultFrom', 'defaultAddress', 'serviceUrl'], (err, configItems) => {
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
|
||||
mailer.sendMail({
|
||||
from: {
|
||||
name: configItems.defaultFrom,
|
||||
address: configItems.defaultAddress
|
||||
},
|
||||
to: {
|
||||
name: [].concat(subscription.firstName || []).concat(subscription.lastName || []).join(' '),
|
||||
address: subscription.email
|
||||
},
|
||||
subject: list.name + ': Subscription Confirmed',
|
||||
encryptionKeys
|
||||
}, {
|
||||
html: 'emails/unsubscribe-confirmed-html.hbs',
|
||||
text: 'emails/unsubscribe-confirmed-text.hbs',
|
||||
data: {
|
||||
title: list.name,
|
||||
contactAddress: configItems.defaultAddress,
|
||||
subscribeUrl: urllib.resolve(configItems.serviceUrl, '/subscription/' + list.cid + '?cid=' + subscription.cid)
|
||||
}
|
||||
}, err => {
|
||||
if (err) {
|
||||
log.error('Subscription', err.stack);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -13,5 +13,5 @@ respawn limit 10 0
|
|||
|
||||
script
|
||||
cd /opt/mailtrain
|
||||
exec node index.js >> /var/log/mailtrain.log 2>&1
|
||||
exec npm start >> /var/log/mailtrain.log 2>&1
|
||||
end script
|
||||
|
|
|
@ -178,6 +178,6 @@ runUpdates(err => {
|
|||
log.error('sql', err);
|
||||
process.exit(1);
|
||||
}
|
||||
log.info('sql', 'Database update completed');
|
||||
log.info('sql', 'Database check completed');
|
||||
process.exit(0);
|
||||
});
|
||||
|
|
30
views/emails/subscription-confirmed-html.hbs
Normal file
30
views/emails/subscription-confirmed-html.hbs
Normal file
|
@ -0,0 +1,30 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>{{title}}: Subscription Confirmed</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<h1>{{title}}</h1>
|
||||
|
||||
<h2>Your subscription to our list has been confirmed.</h2>
|
||||
|
||||
<p>
|
||||
If you want to modify your subscription then you can:
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<a href="{{preferencesUrl}}">manage your preferences</a>
|
||||
<span style="color: #444444;"> or </span>
|
||||
<a href="{{unsubscribeUrl}}">unsubscribe here</a>
|
||||
</p>
|
||||
|
||||
<p>For questions about this list, please contact:
|
||||
<br/>{{contactAddress}}</p>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
16
views/emails/subscription-confirmed-text.hbs
Normal file
16
views/emails/subscription-confirmed-text.hbs
Normal file
|
@ -0,0 +1,16 @@
|
|||
{{{title}}}
|
||||
Subscription Confirmed
|
||||
======================
|
||||
|
||||
Your subscription to our list has been confirmed.
|
||||
|
||||
If you want to modify your subscription then you can:
|
||||
|
||||
manage your preferences: {{preferencesUrl}}
|
||||
|
||||
- or -
|
||||
|
||||
unsubscribe here: {{unsubscribeUrl}}
|
||||
|
||||
For questions about this list, please contact:
|
||||
{{{contactAddress}}}
|
26
views/emails/unsubscribe-confirmed-html.hbs
Normal file
26
views/emails/unsubscribe-confirmed-html.hbs
Normal file
|
@ -0,0 +1,26 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>{{title}}: You are now unsubscribed</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<h1>{{title}}</h1>
|
||||
|
||||
<h2>We have removed your email address from our list.</h2>
|
||||
|
||||
<p>
|
||||
If you unsubscribed by mistake, you can re-subscribe at:
|
||||
</p>
|
||||
|
||||
<p><a href="{{subscribeUrl}}" class="btn-primary" itemprop="url" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; color: #FFF; text-decoration: none; line-height: 2em; font-weight: bold; text-align: center; cursor: pointer; display: inline-block; border-radius: 5px; text-transform: capitalize; background-color: #348eda; margin: 0; border-color: #348eda; border-style: solid; border-width: 10px 20px;">Subscribe</a></p>
|
||||
|
||||
<p>For questions about this list, please contact:
|
||||
<br/>{{contactAddress}}</p>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
12
views/emails/unsubscribe-confirmed-text.hbs
Normal file
12
views/emails/unsubscribe-confirmed-text.hbs
Normal file
|
@ -0,0 +1,12 @@
|
|||
{{{title}}}
|
||||
You are now unsubscribed
|
||||
========================
|
||||
|
||||
We have removed your email address from our list.
|
||||
|
||||
If you unsubscribed by mistake, you can re-subscribe at:
|
||||
|
||||
Subscribe: {{subscribeUrl}}
|
||||
|
||||
For questions about this list, please contact:
|
||||
{{{contactAddress}}}
|
|
@ -10,6 +10,6 @@
|
|||
</a>
|
||||
or
|
||||
<a class="btn btn-primary" href="{{preferences}}" role="button">
|
||||
<span class="glyphicon glyphicon-wrench" aria-hidden="true"></span> manage you preferences
|
||||
<span class="glyphicon glyphicon-wrench" aria-hidden="true"></span> manage your preferences
|
||||
</a>
|
||||
</p>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue