Commit 86492e6c authored by Vadym Gidulian's avatar Vadym Gidulian

Initial commit

parents
.env
/templates/
# Dependency directories
node_modules/
# Logs
logs/
*.log
npm-debug.log*
# Optional npm cache directory
.npm/
# Optional REPL history
.node_repl_history/
services:
- docker:dind
variables:
IMAGE_SNAPSHOT: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
IMAGE: $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_NAME
IMAGE_LATEST: $CI_REGISTRY_IMAGE:latest
stages:
- build
- release
before_script:
- docker version
- docker info
- docker login -u gitlab-ci-token -p $CI_JOB_TOKEN $CI_REGISTRY
build:
stage: build
script:
- docker build --pull -t $IMAGE_SNAPSHOT .
- docker push $IMAGE_SNAPSHOT
tags:
- dind
release:
stage: release
variables:
GIT_STRATEGY: none
script:
- docker pull $IMAGE_SNAPSHOT
- docker tag $IMAGE_SNAPSHOT $IMAGE
- docker push $IMAGE
tags:
- dind
release:latest:
stage: release
variables:
GIT_STRATEGY: none
script:
- docker pull $IMAGE_SNAPSHOT
- docker tag $IMAGE_SNAPSHOT $IMAGE_LATEST
- docker push $IMAGE_LATEST
when: manual
tags:
- dind
only:
- master
FROM node:10-alpine
MAINTAINER Vadym Gidulian <vadym.gidulian@gvia.group>
COPY package.json yarn.lock /app/
COPY src/ /app/src/
VOLUME /app/templates
WORKDIR /app
RUN yarn install --production &&\
yarn cache clean
CMD ["node", "src"]
EXPOSE 80
version: '3'
services:
server:
build: .
volumes:
- .:/app
- ./templates:/app/templates
entrypoint: sh
command: -c "yarn && npx nodemon src"
environment:
CORS_ALLOW_ORIGIN: $CORS_ALLOW_ORIGIN
SMTP_HOST: $SMTP_HOST
SMTP_PORT: $SMTP_PORT
SMTP_SECURE: $SMTP_SECURE
SMTP_USER: $SMTP_USER
SMTP_PASSWORD: $SMTP_PASSWORD
{
"name": "@gviagroup/service-mailer",
"version": "0.1.0",
"dependencies": {
"express": "^4.16.3",
"nodemailer": "^4.6.8",
"@gviagroup/jsvv": "~0.6.0"
},
"devDependencies": {
"nodemon": "^1.18.4"
}
}
'use strict';
const express = require('express');
const jsvv = require('@gviagroup/jsvv');
const mailerModel = require('./models/mailer');
const requestSchema = require('./schemas/request');
const templateNameSchema = require('./schemas/template-name');
const CORS_ALLOW_ORIGIN = process.env.CORS_ALLOW_ORIGIN || '*';
const app = express();
app.use(express.json({
limit: '1mb'
}));
app.use((req, res, next) => {
res.header('Access-Control-Allow-Origin', CORS_ALLOW_ORIGIN);
res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');
res.header('Access-Control-Allow-Methods', 'OPTIONS, POST');
next();
});
app.post('/:template', async (req, res) => {
try {
req.params.template = jsvv(req.params.template, templateNameSchema);
req.body = jsvv(req.body, requestSchema);
} catch (e) {
return res.status(400).send(e.message);
}
try {
res.status(200).send(await mailerModel.sendMessage(req.params.template, req.body));
} catch (e) {
console.error(e);
res.status(500).send();
}
});
app.listen(80, () => {
console.log('Server is started.');
});
'use strict';
['SMTP_HOST', 'SMTP_PORT', 'SMTP_USER', 'SMTP_PASSWORD'].forEach(varname => {
if (!process.env[varname]) {
console.error(`Environment variable ${varname} is not defined!`);
process.exit(1);
}
});
const {promisify} = require('util');
const nodemailer = require('nodemailer');
const templatesModel = require('./templates');
const SMTP_HOST = process.env.SMTP_HOST;
const SMTP_PORT = process.env.SMTP_PORT;
const SMTP_SECURE = process.env.SMTP_SECURE || false;
const SMTP_USER = process.env.SMTP_USER;
const SMTP_PASSWORD = process.env.SMTP_PASSWORD;
const SMTP_SENDER = process.env.SMTP_SENDER || SMTP_USER;
templatesModel.prepareTemplates();
const transporter = nodemailer.createTransport({
host: SMTP_HOST,
port: SMTP_PORT,
secure: SMTP_SECURE,
auth: {
user: SMTP_USER,
pass: SMTP_PASSWORD
},
pool: true
});
transporter.verify((err) => {
if (err) {
console.error(err);
process.exit(1);
}
console.log('SMTP server is ready.');
});
const sendMail = promisify(transporter.sendMail).bind(transporter);
module.exports = {
async sendMessage(template, request) {
const message = templatesModel.getTemplate(template).replace(/{{(.+?)}}/g, (match, name) => request.vars && request.vars[name] || '');
const mailer = {
from: SMTP_SENDER,
to: request.to,
subject: request.subject,
html: message
};
const {messageId, accepted, rejected} = await sendMail(mailer);
return {messageId, accepted, rejected};
}
};
'use strict';
const fs = require('fs');
const TEMPLATES_DIR = '/app/templates';
const templates = {};
module.exports = {
prepareTemplates() {
try {
if (fs.statSync(TEMPLATES_DIR)) {
const filenames = fs.readdirSync(TEMPLATES_DIR);
filenames.forEach(filename => {
templates[filename] = fs.readFileSync(`${TEMPLATES_DIR}/${filename}`, {encoding: 'utf-8'});
});
}
console.log(`Loaded templates: ${Object.keys(templates).map(name => `"${name}"`).join(', ')}`);
} catch (e) {
console.error(e);
process.exit(1);
}
},
getTemplate(name) {
return templates[name] || '';
}
};
'use strict';
module.exports = {
type: String,
required: true,
minLength: 1,
transforms: [String.prototype.trim]
};
'use strict';
const stringRequiredSchema = require('./primitives/string-required');
module.exports = {
type: Object,
required: true,
properties: {
to: stringRequiredSchema,
subject: stringRequiredSchema,
vars: {
type: Object
}
}
};
'use strict';
const stringRequiredSchema = require('./primitives/string-required');
module.exports = stringRequiredSchema;
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment