Skip to content

Instantly share code, notes, and snippets.

@snewell92
Last active October 4, 2017 17:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save snewell92/3097c1af27f09b829e7a311a18085f55 to your computer and use it in GitHub Desktop.
Save snewell92/3097c1af27f09b829e7a311a18085f55 to your computer and use it in GitHub Desktop.
Micro Dev hangs
import { createTransport, SendMailOptions } from 'nodemailer';
import { IncomingMessage, ServerResponse } from 'http'
import { json, send } from 'micro';
type MicroFunction = (req: IncomingMessage, res: ServerResponse) => string | void | Promise<any>;
type DorianMailData = {
dest: string,
body: string,
subject?: string,
from?: string
};
type CleanMailData = {
dest: string,
body: string,
subject: string,
from: string
};
type DataCleaner = (md: DorianMailData) => CleanMailData;
type SendErrorMsg = (res: ServerResponse, msg: string) => void | Promise<void>;
const defaultSubject = '';
const defaultFrom = 'Dorian Bot <do-not-reply@dorianbusiness.com>';
const mailer = createTransport({
host: process.env.MAILER_HOST,
secure: false,
port: 25,
auth: {
user: process.env.MAILER_USER,
pass: process.env.MAILER_PASS
}
});
const fillDefaults: DataCleaner = md =>
Object.assign({}, md, { from: md.from || defaultFrom, subject: md.subject || defaultSubject });
const sendMail = async (md: CleanMailData) => await mailer
.sendMail({
from: md.from,
subject: md.subject,
text: md.body,
to: md.dest,
headers: {
'Return-Path': md.from,
'ReturnPath': md.from
}
});
const send400Err: SendErrorMsg = async (res, msg) => send(res, 400, { error: msg });
// TODO instead of console.error, use winston or another logging library.
const waitForEmail: MicroFunction = async (req, res) => {
// VERIFY (do we need to do this?)
try {
await mailer.verify();
} catch(er) {
console.error('MAILER NOT VERIFIED');
return await send400Err(res, 'Could not establish initial connection to mail server.');
}
console.log('Verified');
// PARSE
let data: { to?: string, body?: string, subject?: string, from?: string } = null;
try {
console.log('Grabbing json...');
data = await json(req);
console.log('JSON got!');
} catch(err) {
console.error('Request didn\'t have data');
return await send400Err(res, 'No json data in the request body was found.');
}
// VALIDATE data
if(!data.to || !data.body) {
console.error('Request data invalid. Need to and body fields');
return await send400Err(res, 'Invalid data; Need "to" and "body" fields.');
}
let mailData: DorianMailData = {
dest: data.to,
body: data.body
}
if(data.subject) {
mailData.subject = data.subject;
}
if(data.from) {
mailData.from = data.from;
}
// SEND
try {
// TODO we could use functional techniques to make this code way more maintainable...
// we need to use composition and Maybe's, perhaps use rambda? Or a fantasy-land
// compliant library
await sendMail(fillDefaults(mailData));
} catch(err) {
console.error(err);
console.error('Mail failure');
return await send400Err(res, 'Mail failure; sendMail function erroredout:\nMessage: ' + err.message);
}
// when returning a value, micro sends 200 status
return 'Successfully sent your mail';
}
export default waitForEmail
{
"name": "dorian-mailer",
"version": "1.0.0",
"description": "",
"engines": {
"node": ">= 8.0.0"
},
"main": "dist/index.js",
"scripts": {
"start": "micro-dev -p ${MICRO_EMAIL_PORT:-3256}",
"start:prod": "micro -p ${MICRO_EMAIL_PORT:-3256}",
"build": "tsc",
"dev": "run-p -c \"build -- -w\" start"
},
"keywords": [],
"author": "Sean Newell",
"license": "UNLICENSED",
"dependencies": {
"micro": "9.0.0",
"nodemailer": "4.1.1"
},
"devDependencies": {
"@types/micro": "^7.3.1",
"@types/nodemailer": "^3.1.3",
"micro-dev": "^1.2.3",
"npm-run-all": "^4.1.1",
"typescript": "^2.5.3"
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment