Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for SMTP authentication and certificates for startTLS / SSL #30

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,4 @@ RUN npm i && npm run build
EXPOSE 1025
EXPOSE 1080

CMD ["node", "index.js"]
ENTRYPOINT ["node", "index.js"]
32 changes: 21 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,17 +91,27 @@ Usage:
fake-smtp-server [OPTIONS] [ARGS]

Options:
-s, --smtp-port [NUMBER] SMTP port to listen on (Default is 1025)
--smtp-ip [IP] IP Address to bind SMTP service to (Default is 0.0.0.0)
-h, --http-port [NUMBER] HTTP port to listen on (Default is 1080)
--http-ip [IP] IP Address to bind HTTP service to (Default is 0.0.0.0)
-w, --whitelist STRING Only accept e-mails from these adresses. Accepts
multiple e-mails comma-separated
-m, --max [NUMBER] Max number of e-mails to keep (Default is 100)
-a, --auth STRING Enable Authentication
--headers Enable headers in responses
-k, --no-color Omit color from output
--debug Show debug information
-s, --smtp-port [NUMBER] SMTP port to listen on (Default is 1025)
--smtp-ip [IP] IP Address to bind SMTP service to (Default is 0.0.0.0)
-h, --http-port [NUMBER] HTTP port to listen on (Default is 1080)
--http-ip [IP] IP Address to bind HTTP service to (Default is 0.0.0.0)
-w, --whitelist STRING Only accept e-mails from these adresses. Accepts
multiple e-mails comma-separated
-m, --max [NUMBER] Max number of e-mails to keep (Default is 100)
-a, --auth STRING Enable Authentication
--secure Enable Secure option (require SSL connection)
--keystore STRING Path to PKCS12 keystore used for Secure option or when
using STARTTLS
-p, --passphrase STRING Passphrase for PKCS12 private key
--smtpAuth STRING Enable SMTP authentication. Accepts a
comma-separated list of username:password pairs
that are permitted. Setting this makes
authentication required
--headers Enable headers in responses
-k, --no-color Omit color from output
--debug Show debug information
-c, --catch Catch unanticipated errors

```

## Configure fake-smtp-server to run as a service at startup
Expand Down
50 changes: 48 additions & 2 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ const path = require("path");
const _ = require("lodash");
const moment = require("moment");
const cli = require('cli').enable('catchall').enable('status');
const fs = require('fs');

const config = cli.parse({
'smtp-port': ['s', 'SMTP port to listen on', 'number', 1025],
Expand All @@ -16,6 +17,10 @@ const config = cli.parse({
whitelist: ['w', 'Only accept e-mails from these adresses. Accepts multiple e-mails comma-separated', 'string'],
max: ['m', 'Max number of e-mails to keep', 'number', 100],
auth: ['a', 'Enable Authentication', 'string'],
secure: [false, 'Enable Secure option (require SSL connection)'],
keystore: [false, 'Path to PKCS12 keystore used for Secure option or when using STARTTLS', 'string'],
passphrase: ['p', 'Passphrase for PKCS12 private key', 'string'],
smtpAuth: [false, 'Enable SMTP authentication. Accepts a comma-separated list of username:password pairs that are permitted. Setting this makes authentication required', 'string'],
headers: [false, 'Enable headers in responses']
});

Expand All @@ -32,9 +37,11 @@ if (config.auth) {
users[authConfig[0]] = authConfig[1];
}

const smtpUsers = config.smtpAuth ? config.smtpAuth.split(',').map(up => up.split(":")) : null;

const mails = [];

const server = new SMTPServer({
const serverOptions = {
authOptional: true,
maxAllowedUnauthenticatedCommands: 1000,
onMailFrom(address, session, cb) {
Expand Down Expand Up @@ -67,7 +74,46 @@ const server = new SMTPServer({
callback
);
}
});
};

if (smtpUsers) {
cli.info("Accepted SMTP users are " + smtpUsers);
serverOptions.onAuth = smtpAuthCallback;
serverOptions.authOptional = false;
}

if (config.secure) {
serverOptions.secure = true;
}

if (config.keystore) {
if (!fs.existsSync(config.keystore)) {
cli.error(`Keystore ${config.keystore} did not exists`);
console.log(process.exit(1));
}

serverOptions.pfx = fs.readFileSync(config.keystore);
if (config.passphrase)
serverOptions.passphrase = config.passphrase;
else
cli.warn('PFX option set without passphrase');
}

cli.info(`Options = ${JSON.stringify(serverOptions)}`);

const server = new SMTPServer(serverOptions);

function smtpAuthCallback(auth, session, callback) {
const username = auth.username;
const password = auth.password;

cli.info(`${username} is trying to login with password ${password}`);

if (smtpUsers.find(e => (e[0] === username && e[1] === password)))
callback(null, {user: username});
else
callback(new Error('Invalid username or password'));
}

function formatHeaders(headers) {
const result = {};
Expand Down
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.