Skip to content

Commit

Permalink
initial
Browse files Browse the repository at this point in the history
  • Loading branch information
andris9 committed Aug 2, 2017
0 parents commit 155b138
Show file tree
Hide file tree
Showing 67 changed files with 14,469 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .eslintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"extends": "nodemailer"
}
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
node_modules
.DS_Store
npm-debug.log
package-lock.json
16 changes: 16 additions & 0 deletions Gruntfile.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
'use strict';

module.exports = function(grunt) {
// Project configuration.
grunt.initConfig({
eslint: {
all: ['lib/**/*.js', 'routes/**/*.js', 'app.js', 'server.js', 'Gruntfile.js']
}
});

// Load the plugin(s)
grunt.loadNpmTasks('grunt-eslint');

// Tasks
grunt.registerTask('default', ['eslint']);
};
22 changes: 22 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# WildDuck Mail Service

**What is this?**

This is an example web service that uses the [Wild Duck API](https://github.com/nodemailer/wildduck/wiki/API-Docs) to manage user settings and preview messages

## Usage

Assuming that you have Wild Duck mail server running

```
$ npm install --production
$ node server.js
```

You can also create an additional service specific configuration file that would be merged with the default config.

```
$ node server.js --config="/etc/wildduck/www.toml"
```

After you have started the server, head to http://localhost:3000/
166 changes: 166 additions & 0 deletions app.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
'use strict';

const config = require('wild-config');
const log = require('npmlog');
const express = require('express');
const bodyParser = require('body-parser');
const path = require('path');
const favicon = require('serve-favicon');
const logger = require('morgan');
const cookieParser = require('cookie-parser');
const session = require('express-session');
const RedisStore = require('connect-redis')(session);
const flash = require('connect-flash');
const compression = require('compression');
const passport = require('./lib/passport');

const routesIndex = require('./routes/index');
const routesAccount = require('./routes/account');
const routesWebmail = require('./routes/webmail');

const app = express();

// setup extra hbs tags
require('./lib/hbs-helpers');

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'hbs');

// Handle proxies. Needed to resolve client IP
if (config.www.proxy) {
app.set('trust proxy', config.www.proxy);
}

// Do not expose software used
app.disable('x-powered-by');

app.use(compression());
app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));

app.use(
logger(config.www.log, {
stream: {
write: message => {
message = (message || '').toString();
if (message) {
log.info('HTTP', message.replace('\n', '').trim());
}
}
}
})
);

app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));

app.use(
session({
name: 'webmail',
store: new RedisStore({
url: config.dbs.redis
}),
secret: config.www.secret,
saveUninitialized: false,
resave: false,
cookie: {
secure: !!config.www.secure
}
})
);

app.use(flash());

app.use(
bodyParser.urlencoded({
extended: true,
limit: config.www.postsize
})
);

app.use(
bodyParser.text({
limit: config.www.postsize
})
);

app.use(
bodyParser.json({
limit: config.www.postsize
})
);

passport.setup(app);

app.use((req, res, next) => {
// make sure flash messages are available
res.locals.flash = req.flash.bind(req);
res.locals.user = req.user;

res.locals.serviceName = config.name;
res.locals.serviceDomain = config.service.domain;

next();
});

// force 2fa prompt if user is logged in and 2fa is enabled
app.use((req, res, next) => {
if (req.user && req.session.require2fa && !['/account/2fa', '/account/logout'].includes(req.url)) {
return passport.csrf(req, res, err => {
if (err) {
return next(err);
}

return res.render('account/2fa', {
layout: 'layout-popup',
title: 'Two factor authentication',
csrfToken: req.csrfToken()
});
});
}
next();
});

// setup main routes
app.use('/', routesIndex);
app.use('/account', routesAccount);
app.use('/webmail', passport.checkLogin, routesWebmail);

// catch 404 and forward to error handler
app.use((req, res, next) => {
let err = new Error('Not Found');
err.status = 404;
next(err);
});

// error handlers

// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
app.use((err, req, res, next) => {
if (!err) {
return next();
}
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: err
});
});
}

// production error handler
// no stacktraces leaked to user
app.use((err, req, res, next) => {
if (!err) {
return next();
}
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: {}
});
});

module.exports = app;
47 changes: 47 additions & 0 deletions config/default.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
name="Wild Duck Mail"

title="wildduck-www"

[service]
# email domain for new users
domain="localhost"
# default quotas for new users
quota=1024
recipients=2000
forwards=2000

[api]
url="http://127.0.0.1:8080"
accessToken=""

[dbs]
# redis is only needed for Express.js sessions
redis="redis://127.0.0.1:6379/3"

[www]
host=false
port=3000
proxy=false
postsize="5MB"
log="dev"
secret="a cat"
baseurl="http://localhost" # link used in emails etc

[log]
level="silly"
mail=true

[setup]
# these values are shown in the configuration help page
[setup.imap]
hostname="localhost"
secure=true
port=9993
[setup.pop3]
hostname="localhost"
secure=true
port=9995
[setup.smtp]
hostname="localhost"
secure=false
port=2587
Loading

0 comments on commit 155b138

Please sign in to comment.