added status bar, dryrun, force, stacking( enables to add mails later on). Added uuid module for safe, enhanced mail file parser

This commit is contained in:
2020-10-02 21:36:31 +02:00
parent f57960a4a6
commit 89df06bc77
5 changed files with 192 additions and 60 deletions

1
.gitignore vendored
View File

@@ -3,3 +3,4 @@
/node_modules /node_modules
/config.json /config.json
/mails.txt /mails.txt
/out

View File

@@ -1,8 +1,9 @@
import * as fs from 'fs' import * as fs from 'fs'
import { generateToken } from './src/generate' import { generateToken } from './src/generate'
import { SecureVault } from './src/vault' import { SecureVault } from './src/vault'
import { exit } from 'process';
let configPath = "", action = -1, pubKey = "", privKey = "", safeFile = "", mails = "", html = ""; let configPath = "", action = -1, pubKey = "", privKey = "", safeFile = "", mails = "", html = "", dryrun = false, force = false;
// parse cli args // parse cli args
for (let i = 1; i < process.argv.length ; i++){ for (let i = 1; i < process.argv.length ; i++){
if (process.argv[i] === "--config"){ if (process.argv[i] === "--config"){
@@ -38,6 +39,8 @@ for (let i = 1; i < process.argv.length ; i++){
if (process.argv[i] === "--send"){ action = 1 } if (process.argv[i] === "--send"){ action = 1 }
if (process.argv[i] === "--decrypt"){ action = 2 } if (process.argv[i] === "--decrypt"){ action = 2 }
if (process.argv[i] === "--genkey"){ action = 3 } if (process.argv[i] === "--genkey"){ action = 3 }
if (process.argv[i] === "--dryrun"){ dryrun = true }
if (process.argv[i] === "--force"){ force = true }
} }
if ( action == -1){ throw new Error("No Action specified") } if ( action == -1){ throw new Error("No Action specified") }
if (!configPath && action == 1){ throw new Error("Config-Path not specified") } if (!configPath && action == 1){ throw new Error("Config-Path not specified") }
@@ -54,17 +57,39 @@ if (action == 1){
// load config // load config
const confRaw = fs.readFileSync(configPath, 'utf8') const confRaw = fs.readFileSync(configPath, 'utf8')
let config:any = {} let config:any = {}
try { let addition: boolean = false; // wenn nur weitere hinzugefügt werden
config = JSON.parse(confRaw) config = JSON.parse(confRaw)
// load safe if present
if (fs.existsSync(safeFile)){
dataSafe.loadData(safeFile);
config.usedTokens = dataSafe.getStorage(dataSafe.findStorage("usedTokens")[0].u);
config.usedMails = dataSafe.getStorage(dataSafe.findStorage("usedMails")[0].u);
addition = true;
}else{
config.usedTokens = [];
config.usedMails = [];
}
try {
config.inFileMail = mails; config.inFileMail = mails;
config.htmlPath = html; config.htmlPath = html;
config.dryrun = dryrun;
config.force = force;
} catch (error) { } catch (error) {
console.error("Cannote read config file!") console.error("Cannote read config file!")
process.exit(100); process.exit(100);
} }
generateToken(config,dataSafe).then(el => { generateToken(config,dataSafe).then(el => {
console.log(el) if (addition){
dataSafe.setStorage(dataSafe.findStorage("usedTokens")[0].u,el.codes)
dataSafe.setStorage(dataSafe.findStorage("usedMails")[0].u,el.mails)
dataSafe.saveData(safeFile); dataSafe.saveData(safeFile);
}else{
dataSafe.pushStorage('usedTokens',el.codes)
dataSafe.pushStorage('usedMails',el.mails)
dataSafe.saveData(safeFile);
}
}).catch(err => console.error("error", err)) }).catch(err => console.error("error", err))
}else if(action == 2){ }else if(action == 2){
let dataSafe: SecureVault = new SecureVault(pubKey,privKey); let dataSafe: SecureVault = new SecureVault(pubKey,privKey);

67
package-lock.json generated
View File

@@ -1,9 +1,17 @@
{ {
"name": "random", "name": "opentoken",
"version": "1.0.0", "version": "1.0.0",
"lockfileVersion": 1, "lockfileVersion": 1,
"requires": true, "requires": true,
"dependencies": { "dependencies": {
"@types/cli-progress": {
"version": "3.8.0",
"resolved": "https://registry.npmjs.org/@types/cli-progress/-/cli-progress-3.8.0.tgz",
"integrity": "sha512-2OV7ybuYQc6ju6Xlg8ncQcPA/vVbMTSGS0vygjszi9O7swC63S6f2oAnP4CE+4ppRo7eCQovlj268KySt1MaUQ==",
"requires": {
"@types/node": "*"
}
},
"@types/handlebars": { "@types/handlebars": {
"version": "4.1.0", "version": "4.1.0",
"resolved": "https://registry.npmjs.org/@types/handlebars/-/handlebars-4.1.0.tgz", "resolved": "https://registry.npmjs.org/@types/handlebars/-/handlebars-4.1.0.tgz",
@@ -25,11 +33,40 @@
"@types/node": "*" "@types/node": "*"
} }
}, },
"@types/uuid": {
"version": "8.3.0",
"resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-8.3.0.tgz",
"integrity": "sha512-eQ9qFW/fhfGJF8WKHGEHZEyVWfZxrT+6CLIJGBcZPfxUh/+BnEj+UCGYMlr9qZuX/2AltsvwrGqp0LhEW8D0zQ=="
},
"ansi-regex": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz",
"integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg=="
},
"cli-progress": {
"version": "3.8.2",
"resolved": "https://registry.npmjs.org/cli-progress/-/cli-progress-3.8.2.tgz",
"integrity": "sha512-qRwBxLldMSfxB+YGFgNRaj5vyyHe1yMpVeDL79c+7puGujdKJHQHydgqXDcrkvQgJ5U/d3lpf6vffSoVVUftVQ==",
"requires": {
"colors": "^1.1.2",
"string-width": "^4.2.0"
}
},
"colors": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz",
"integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA=="
},
"crypto": { "crypto": {
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/crypto/-/crypto-1.0.1.tgz", "resolved": "https://registry.npmjs.org/crypto/-/crypto-1.0.1.tgz",
"integrity": "sha512-VxBKmeNcqQdiUQUW2Tzq0t377b54N2bMtXO/qiLa+6eRRmmC4qT3D4OnTGoT/U6O9aklQ/jTwbOtRMTTY8G0Ig==" "integrity": "sha512-VxBKmeNcqQdiUQUW2Tzq0t377b54N2bMtXO/qiLa+6eRRmmC4qT3D4OnTGoT/U6O9aklQ/jTwbOtRMTTY8G0Ig=="
}, },
"emoji-regex": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
},
"handlebars": { "handlebars": {
"version": "4.7.6", "version": "4.7.6",
"resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.6.tgz", "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.6.tgz",
@@ -42,6 +79,11 @@
"wordwrap": "^1.0.0" "wordwrap": "^1.0.0"
} }
}, },
"is-fullwidth-code-point": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="
},
"minimist": { "minimist": {
"version": "1.2.5", "version": "1.2.5",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
@@ -62,12 +104,35 @@
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
}, },
"string-width": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz",
"integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==",
"requires": {
"emoji-regex": "^8.0.0",
"is-fullwidth-code-point": "^3.0.0",
"strip-ansi": "^6.0.0"
}
},
"strip-ansi": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz",
"integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==",
"requires": {
"ansi-regex": "^5.0.0"
}
},
"uglify-js": { "uglify-js": {
"version": "3.10.4", "version": "3.10.4",
"resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.10.4.tgz", "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.10.4.tgz",
"integrity": "sha512-kBFT3U4Dcj4/pJ52vfjCSfyLyvG9VYYuGYPmrPvAxRw/i7xHiT4VvCev+uiEMcEEiu6UNB6KgWmGtSUYIWScbw==", "integrity": "sha512-kBFT3U4Dcj4/pJ52vfjCSfyLyvG9VYYuGYPmrPvAxRw/i7xHiT4VvCev+uiEMcEEiu6UNB6KgWmGtSUYIWScbw==",
"optional": true "optional": true
}, },
"uuid": {
"version": "8.3.0",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.0.tgz",
"integrity": "sha512-fX6Z5o4m6XsXBdli9g7DtWgAx+osMsRRZFKma1mIUsLCz6vRvv+pz5VNbyu9UEDzpMWulZfvpgb/cmDXVulYFQ=="
},
"wordwrap": { "wordwrap": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz",

View File

@@ -10,12 +10,16 @@
"author": "", "author": "",
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"@types/cli-progress": "^3.8.0",
"@types/handlebars": "^4.1.0", "@types/handlebars": "^4.1.0",
"@types/node": "^14.11.1", "@types/node": "^14.11.1",
"@types/nodemailer": "^6.4.0", "@types/nodemailer": "^6.4.0",
"@types/uuid": "^8.3.0",
"cli-progress": "^3.8.2",
"crypto": "^1.0.1", "crypto": "^1.0.1",
"handlebars": "^4.7.6", "handlebars": "^4.7.6",
"nodemailer": "^6.4.11" "nodemailer": "^6.4.11",
"uuid": "^8.3.0"
}, },
"pkg": { "pkg": {
"scripts": "dist/**/*.js", "scripts": "dist/**/*.js",

View File

@@ -1,73 +1,76 @@
import * as fs from 'fs' import * as fs from 'fs'
import * as path from 'path'
import * as nodemailer from 'nodemailer'; import * as nodemailer from 'nodemailer';
import * as cliProgress from 'cli-progress'
import { shuffleArray } from './util/shuffle'; import { shuffleArray } from './util/shuffle';
import { mkstring } from './util/token'; import { mkstring } from './util/token';
import * as Handlebars from "handlebars"; import * as Handlebars from "handlebars";
import Mail from 'nodemailer/lib/mailer'; import Mail from 'nodemailer/lib/mailer';
import { SecureVault } from './vault'; import { SecureVault } from './vault';
import { parseMails } from './mailParser';
interface mail{ interface mail{
mail: string; mail: string;
name: string; name: string;
} }
export function generateToken(config: any,dataSafe: SecureVault): Promise<String[]>{ export interface genReturn{
let pr = new Promise<String[]>((resolve,error) => { codes: string[];
let mailArray: mail[] = []; mails: mail[];
}
// read and process mail list export function generateToken(config: any,dataSafe: SecureVault): Promise<genReturn>{
let readline = require('readline'), return new Promise<genReturn>((resolve,error) => {
instream = fs.createReadStream(config.inFileMail), parseMails(config).then(res => {
outstream = new (require('stream'))(), generateCodes(resolve,error,res,config,dataSafe);
rl = readline.createInterface(instream, outstream);
rl.on('line', function (line:string) {
console.log(line);
mailArray.push({
mail: line.substr(0,line.indexOf(";")),
name: line.substr(line.indexOf(";") + 1)
}) })
}); });
rl.on('close', function (line:string) {
// next step
generateCodes(resolve,error,mailArray,config,dataSafe);
});
});
return pr;
} }
// generate codes // generate codes
async function generateCodes(resolve: (value?: String[]) => void,error: (reason?: any) => void,mailArray: mail[],config: any,dataSafe: SecureVault){ async function generateCodes(resolve: (value?: genReturn) => void,error: (reason?: any) => void,mailArray: mail[],config: any,dataSafe: SecureVault){
console.log("\nGenerating codes")
const pbar = new cliProgress.SingleBar({}, cliProgress.Presets.shades_classic);
pbar.start(mailArray.length, 0,{
speed: "N/A"
});
let position = 0;
let codeArray: string[] = []; let codeArray: string[] = [];
let checkString: string = ''; let checkString: string = '';
let listString: string = ''; let listString: string = '';
for(let i = 0; i < mailArray.length; i++){ // as many codes as adresses for(let i = 0; i < mailArray.length; i++){ // as many codes as adresses
// check that codes are unique // check that codes are unique
let code = mkstring(4); let code = '';
while (codeArray.includes(code)){ do{
code = mkstring(4); code = mkstring(4);
} }while ( (config.force ? codeArray : [...codeArray, ...config.usedTokens]).includes(code))
codeArray.push(code); codeArray.push(code);
checkString = `${checkString}|${code}` checkString = `${checkString}|${code}`
listString = `${listString}\n${code}` listString = `${listString}\n${code}`
position ++;
pbar.update(position);
} }
checkString = checkString.substr(1); checkString = checkString.substr(1);
listString = listString.substr(1); listString = listString.substr(1);
pbar.stop();
//write code lists //write code lists
try { try {
if (!fs.existsSync(path.dirname(config.outFileMatch))){
fs.mkdirSync(path.dirname(config.outFileMatch));
}
fs.writeFileSync(config.outFileMatch, checkString); fs.writeFileSync(config.outFileMatch, checkString);
fs.writeFileSync(config.outFileCodes, listString); } catch (err) {
} catch (error) {
error(error); error(err);
} }
sendMails(resolve,error,mailArray,codeArray,config,dataSafe); sendMails(resolve,error,mailArray,codeArray,config,dataSafe);
} }
// randomize mails and tokens // randomize mails and tokens
async function sendMails(resolve: (value?: String[]) => void,error: (reason?: any) => void,mailArray: mail[],codeArray: string[],config: any,dataSafe: SecureVault){ async function sendMails(resolve: (value?: genReturn) => void,error: (reason?: any) => void,mailArray: mail[],codeArray: string[],config: any,dataSafe: SecureVault){
let mailserver = nodemailer.createTransport(config.mail); let mailserver = nodemailer.createTransport(config.mail);
// read mail template // read mail template
let template!: HandlebarsTemplateDelegate<any>; let template!: HandlebarsTemplateDelegate<any>;
@@ -79,21 +82,46 @@ async function sendMails(resolve: (value?: String[]) => void,error: (reason?: an
error(error); error(error);
} }
console.log("\nSending mails")
const pbar = new cliProgress.SingleBar({}, cliProgress.Presets.shades_classic);
pbar.start(mailArray.length, 0,{
speed: "N/A"
});
let position = 0;
shuffleArray(mailArray); shuffleArray(mailArray);
shuffleArray(codeArray); shuffleArray(codeArray);
if (config.force){dataSafe.clearVault();}
for(let i = 0; i < mailArray.length; i++){ for(let i = 0; i < mailArray.length; i++){
// send mail // send mail
if (!config.dryrun){
dataSafe.pushData({ dataSafe.pushData({
name: mailArray[i].name, name: mailArray[i].name,
mail: mailArray[i].mail, mail: mailArray[i].mail,
code: codeArray[i] code: codeArray[i]
}) })
await send(mailArray[i].name, mailArray[i].mail, codeArray[i],template,mailserver,config);
} }
resolve(codeArray); await send(mailArray[i].name, mailArray[i].mail, codeArray[i],template,mailserver,config);
position ++;
pbar.update(position);
}
pbar.stop();
shuffleArray(mailArray);
shuffleArray(codeArray);
shuffleArray(mailArray);
shuffleArray(codeArray);
resolve({
codes: config.force ? codeArray : (config.dryrun ? config.usedTokens : [...codeArray, ...config.usedTokens]),
mails: config.force ? mailArray : (config.dryrun ? config.usedMails : [...mailArray, ...config.usedMails])
});
} }
async function send(name: string, mail: string, code: string,template: HandlebarsTemplateDelegate<any>,mailserver: Mail,config: any){ async function send(name: string, mail: string, code: string,template: HandlebarsTemplateDelegate<any>,mailserver: Mail,config: any){
if (config.dryrun){
await delay(100);
console.log(`\n\x1b[36m -> dryrun: would send to ${mail}\x1b[0m`);
}else{
// fill template // fill template
let html = template({ let html = template({
"name": name, "name": name,
@@ -112,3 +140,12 @@ async function send(name: string, mail: string, code: string,template: Handlebar
console.log(`Error sendign mail to ${mail} : ${error}`) console.log(`Error sendign mail to ${mail} : ${error}`)
} }
} }
}
function delay(t: number, val?: number) {
return new Promise(function(resolve) {
setTimeout(function() {
resolve(val);
}, t);
});
}