emailer
This commit is contained in:
parent
22a820893c
commit
4120248d75
708
package-lock.json
generated
708
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -38,6 +38,7 @@
|
|||||||
"body-parser": "^1.17.2",
|
"body-parser": "^1.17.2",
|
||||||
"connect-redis": "^3.3.0",
|
"connect-redis": "^3.3.0",
|
||||||
"connect-session-knex": "^1.3.4",
|
"connect-session-knex": "^1.3.4",
|
||||||
|
"email-templates": "^2.7.1",
|
||||||
"express": "^4.15.3",
|
"express": "^4.15.3",
|
||||||
"express-rate-limit": "^2.9.0",
|
"express-rate-limit": "^2.9.0",
|
||||||
"express-session": "^1.15.3",
|
"express-session": "^1.15.3",
|
||||||
|
64
server/api/emailer.js
Normal file
64
server/api/emailer.js
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
import {EmailTemplate} from 'email-templates'
|
||||||
|
import path from 'path'
|
||||||
|
import bluebird from 'bluebird'
|
||||||
|
import nodemailer from 'nodemailer'
|
||||||
|
import config from '../../scripts/load-config'
|
||||||
|
|
||||||
|
const templateDir = path.join(__dirname, '../../', 'templates')
|
||||||
|
|
||||||
|
let templateCache = {}
|
||||||
|
let transporter
|
||||||
|
|
||||||
|
function sendMail (email, headers) {
|
||||||
|
if (!transporter) return
|
||||||
|
transporter.sendMail({
|
||||||
|
from: config.email.admin,
|
||||||
|
to: email,
|
||||||
|
subject: headers.subject,
|
||||||
|
html: headers.html,
|
||||||
|
text: headers.text
|
||||||
|
}, (error, info) => {
|
||||||
|
if (error) {
|
||||||
|
return console.error(error)
|
||||||
|
}
|
||||||
|
console.debug(info)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
async function pushMail (template, email, context) {
|
||||||
|
if (!transporter) return
|
||||||
|
let templ = null
|
||||||
|
|
||||||
|
if (!templateCache[template]) {
|
||||||
|
templ = templateCache[template] = new EmailTemplate(path.join(templateDir, template))
|
||||||
|
} else {
|
||||||
|
templ = templateCache[template]
|
||||||
|
}
|
||||||
|
|
||||||
|
let result = await templ.render(context)
|
||||||
|
|
||||||
|
console.debug('Mail being sent: %s to %s', template, email)
|
||||||
|
|
||||||
|
sendMail(email, result)
|
||||||
|
}
|
||||||
|
|
||||||
|
async function init () {
|
||||||
|
if (!config.email || config.email.enabled === false) return
|
||||||
|
transporter = nodemailer.createTransport(config.email.transport)
|
||||||
|
|
||||||
|
console.debug('Setting up mail transporter')
|
||||||
|
|
||||||
|
try {
|
||||||
|
await transporter.verify()
|
||||||
|
console.debug('Mail transporter initialized')
|
||||||
|
} catch (e) {
|
||||||
|
console.error('Email server verification failed')
|
||||||
|
console.error(e)
|
||||||
|
transporter = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
pushMail: pushMail,
|
||||||
|
init: init
|
||||||
|
}
|
@ -6,6 +6,7 @@ import models from './models'
|
|||||||
import crypto from 'crypto'
|
import crypto from 'crypto'
|
||||||
import notp from 'notp'
|
import notp from 'notp'
|
||||||
import base32 from 'thirty-two'
|
import base32 from 'thirty-two'
|
||||||
|
import emailer from './emailer'
|
||||||
|
|
||||||
const emailRe = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
|
const emailRe = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
|
||||||
|
|
||||||
@ -190,8 +191,10 @@ const API = {
|
|||||||
return emailRe.test(email)
|
return emailRe.test(email)
|
||||||
},
|
},
|
||||||
newAccount: async function (regdata) {
|
newAccount: async function (regdata) {
|
||||||
|
let email = config.email && config.email.enabled
|
||||||
let data = Object.assign(regdata, {
|
let data = Object.assign(regdata, {
|
||||||
created_at: new Date()
|
created_at: new Date(),
|
||||||
|
activated: email ? 0 : 1
|
||||||
})
|
})
|
||||||
|
|
||||||
let userTest = await API.User.get(regdata.username)
|
let userTest = await API.User.get(regdata.username)
|
||||||
@ -216,8 +219,16 @@ const API = {
|
|||||||
type: 1
|
type: 1
|
||||||
})
|
})
|
||||||
|
|
||||||
// TODO: Send email
|
// Send Activation Email
|
||||||
console.log(activationToken)
|
console.debug('Activation token:', activationToken)
|
||||||
|
if (email) {
|
||||||
|
await emailer.pushMail('activate', user.email, {
|
||||||
|
domain: config.server.domain,
|
||||||
|
display_name: user.display_name,
|
||||||
|
activation_token: activationToken
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
return {error: null, user: user}
|
return {error: null, user: user}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,7 @@ class OAuth2Provider {
|
|||||||
|
|
||||||
express () {
|
express () {
|
||||||
return (req, res, next) => {
|
return (req, res, next) => {
|
||||||
console.debug('attached')
|
console.debug('OAuth2 Injected into request')
|
||||||
req.oauth2 = this
|
req.oauth2 = this
|
||||||
next()
|
next()
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ import wrap from '../../scripts/asyncRoute'
|
|||||||
import http from '../../scripts/http'
|
import http from '../../scripts/http'
|
||||||
import API from '../api'
|
import API from '../api'
|
||||||
import News from '../api/news'
|
import News from '../api/news'
|
||||||
|
import email from '../api/emailer'
|
||||||
|
|
||||||
import apiRouter from './api'
|
import apiRouter from './api'
|
||||||
import oauthRouter from './oauth2'
|
import oauthRouter from './oauth2'
|
||||||
@ -411,6 +412,11 @@ router.get('/activate/:token', wrap(async (req, res) => {
|
|||||||
|
|
||||||
router.use('/api', apiRouter)
|
router.use('/api', apiRouter)
|
||||||
|
|
||||||
|
/*router.get('/test', (req, res, next) => {
|
||||||
|
email.pushMail('test', req.session.user.email, req.session.user).catch((e) => {next(e)})
|
||||||
|
res.jsonp({})
|
||||||
|
})*/
|
||||||
|
|
||||||
router.use((err, req, res, next) => {
|
router.use((err, req, res, next) => {
|
||||||
console.error(err)
|
console.error(err)
|
||||||
next()
|
next()
|
||||||
|
@ -11,6 +11,7 @@ import routes from './routes'
|
|||||||
import flash from '../scripts/flash'
|
import flash from '../scripts/flash'
|
||||||
import config from '../scripts/load-config'
|
import config from '../scripts/load-config'
|
||||||
import database from '../scripts/load-database'
|
import database from '../scripts/load-database'
|
||||||
|
import email from './api/emailer'
|
||||||
|
|
||||||
let app = express()
|
let app = express()
|
||||||
let SessionStore = connectSession(session)
|
let SessionStore = connectSession(session)
|
||||||
@ -68,5 +69,6 @@ module.exports = (args) => {
|
|||||||
|
|
||||||
app.listen(args.port, () => {
|
app.listen(args.port, () => {
|
||||||
console.log('Listening on 0.0.0.0:' + args.port)
|
console.log('Listening on 0.0.0.0:' + args.port)
|
||||||
|
email.init()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
5
templates/activate/html.pug
Normal file
5
templates/activate/html.pug
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
h1 Welcome to Icy Network, #{display_name}!
|
||||||
|
p Before you can log in, you must activate your account.
|
||||||
|
p Click on or copy the following link into your URL bar in order to activate your Icy Network account
|
||||||
|
a.activate(href=domain + "/activate/" + activation_token, target="_blank", rel="nofollow")= domain + "/activate/" + activation_token
|
||||||
|
p If you did not register for an account on Icy Network, please ignore this email.
|
1
templates/activate/subject.pug
Normal file
1
templates/activate/subject.pug
Normal file
@ -0,0 +1 @@
|
|||||||
|
|Welcome to Icy Network!
|
2
templates/test/html.pug
Normal file
2
templates/test/html.pug
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
h1 Hello #{display_name}
|
||||||
|
p this is a test email
|
Reference in New Issue
Block a user