This commit is contained in:
Evert Prants 2017-08-24 16:42:57 +03:00
parent 22a820893c
commit 4120248d75
Signed by: evert
GPG Key ID: 1688DA83D222D0B5
10 changed files with 793 additions and 15 deletions

708
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -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
View 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
}

View File

@ -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}
} }
} }

View File

@ -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()
} }

View File

@ -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()

View File

@ -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()
}) })
} }

View 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.

View File

@ -0,0 +1 @@
|Welcome to Icy Network!

2
templates/test/html.pug Normal file
View File

@ -0,0 +1,2 @@
h1 Hello #{display_name}
p this is a test email