forked from apxtri/apxtri
turnaround issue brevo emailing
This commit is contained in:
parent
b240419705
commit
22333d7db9
@ -3,6 +3,7 @@ const path = require("path");
|
||||
const fs = require("fs-extra");
|
||||
const axios = require("axios");
|
||||
const dayjs = require("dayjs");
|
||||
const Mustache = require('mustache');
|
||||
const Checkjson = require(`./Checkjson.js`);
|
||||
//const smtp = require("smtp-client");
|
||||
const nodemailer = require("nodemailer");
|
||||
@ -212,18 +213,27 @@ Notifications.manageemail = (data, template, tribe) => {
|
||||
* data optionaly can contain Cc,Bcc as array of emails and attachments as array of filename (into the server)
|
||||
* Await the 1st email
|
||||
*/
|
||||
|
||||
//console.log(data)
|
||||
if (!data.emailsto || data.emailsto.length == 0) {
|
||||
return {
|
||||
status: 406,
|
||||
ref: "Notifications",
|
||||
msg: "emailsmissing",
|
||||
msg: "emailstomissing",
|
||||
data: data,
|
||||
};
|
||||
}
|
||||
if (typeof data.emailsto === "string") data.emailsto = [data.emailsto];
|
||||
|
||||
if (!fs.existsSync(path.resolve(template))){
|
||||
return {
|
||||
status: 404,
|
||||
ref: "Notification",
|
||||
msg: "templatenotfound",
|
||||
data: { template:path.resolve(template) },
|
||||
}
|
||||
}
|
||||
const tplemail = require(path.resolve(template));
|
||||
let sendit;
|
||||
let sendit={status:200,ref:"Notifications",msg:"successfullsend"};
|
||||
data.emailsto.forEach(async (e, i) => {
|
||||
if (Checkjson.testformat(e, "email")) {
|
||||
const dat = {};
|
||||
@ -233,16 +243,17 @@ Notifications.manageemail = (data, template, tribe) => {
|
||||
dat.text = Mustache.render(tplemail.text, data);
|
||||
dat.Cc = data.Cc ? tplemail.Cc.push(data.Cc) : tplemail.Cc;
|
||||
dat.Bcc = data.Bcc ? tplemail.Bcc.push(data.Bcc) : tplemail.Bcc;
|
||||
dat.attachments = tplemail.attachments.push(data.attachments);
|
||||
const sendit = Notifications.sendmail(data, tribe);
|
||||
if (data.attachments){
|
||||
data.attachments.forEach(a=>tplemail.attachments.push(a))
|
||||
}
|
||||
if (i == 0) {
|
||||
sendit = await Notifications.sendmail(data, tribe);
|
||||
if (sendit.status != 200) return sendit;
|
||||
sendit = await Notifications.sendmail(dat, tribe);
|
||||
if (sendit.status != 200) return {status:406,ref:"Notifications",msg:"emailnotsent"};
|
||||
} else {
|
||||
Notifications.sendmail(data, tribe);
|
||||
Notifications.sendmail(dat, tribe);
|
||||
}
|
||||
} else {
|
||||
// not a well formated email
|
||||
// not a well formated email @todo add a log file to follow it
|
||||
}
|
||||
});
|
||||
return sendit;
|
||||
@ -250,6 +261,17 @@ Notifications.manageemail = (data, template, tribe) => {
|
||||
|
||||
Notifications.sendmail = async (data, tribe) => {
|
||||
/**
|
||||
* * in conf global or in /itm/{tribe}.json must have valid parameter emailcontact must be authorized by the smtp
|
||||
* "emailcontact": "noreply@smatchit.io",
|
||||
* "smtp": {
|
||||
* "host": "smtp-relay.brevo.com",
|
||||
* "port": 587,
|
||||
* "secure": false,
|
||||
* "auth": {
|
||||
* "user": "xx",
|
||||
* "pass": "yy"
|
||||
* }
|
||||
* }
|
||||
* See https://nodemailer.com/message/ for available fields to add
|
||||
* @param {string} [data.from] an email authorized by smtp used priority from header xtribe
|
||||
* @param {string} data.to list of email separate by ,
|
||||
@ -265,7 +287,7 @@ Notifications.sendmail = async (data, tribe) => {
|
||||
* {filename:'img.png',path:"data:text/svg;base64.aGVsbG8gd29ybGQ="}
|
||||
*
|
||||
* @example data
|
||||
* {"to":"wall-ants.ndda.fr",
|
||||
* {"to":"wall-ants@ndda.fr",
|
||||
* "subject":"Test",
|
||||
* "html":"<h1>test welcome</h1>",
|
||||
* "text":"test welcome",
|
||||
@ -305,13 +327,18 @@ Notifications.sendmail = async (data, tribe) => {
|
||||
const conftribfile = `../../itm/${tribe}.json`;
|
||||
if (fs.existsSync(conftribfile)) {
|
||||
const conftrib = fs.readJSONSync(conftribfile);
|
||||
confsmtp = conftrib.smtp;
|
||||
if (!data.from) data.from = conftrib.emailcontact;
|
||||
if (!conftrib.emailcontact){
|
||||
return {
|
||||
status: 428,
|
||||
ref: "Notifications",
|
||||
msg: "missingemailcontactinconf",
|
||||
data: { tribe },
|
||||
};
|
||||
}
|
||||
confsmtp = conftrib.smtp;
|
||||
if (!data.from || data.from == conf.emailcontact) data.from = conftrib.emailcontact;
|
||||
}
|
||||
|
||||
//const client = smtp.connect(confsmtp);
|
||||
const transporter = await nodemailer.createTransport(confsmtp);
|
||||
//@todo add attachments management
|
||||
if (data.filelist) {
|
||||
data.attachments = [];
|
||||
let missingfile = [];
|
||||
@ -331,6 +358,7 @@ Notifications.sendmail = async (data, tribe) => {
|
||||
}
|
||||
//console.log("data:", data);
|
||||
const res = await transporter.sendMail(data);
|
||||
//console.log(res)
|
||||
if (
|
||||
res.accepted &&
|
||||
data.to.split(",").reduce((acc, m) => acc && res.accepted.includes(m), true)
|
||||
|
221
models/PagansPeter.js
Normal file
221
models/PagansPeter.js
Normal file
@ -0,0 +1,221 @@
|
||||
const glob = require("glob");
|
||||
const path = require("path");
|
||||
const dayjs = require("dayjs");
|
||||
const fs = require("fs-extra");
|
||||
const axios = require("axios");
|
||||
const Mustache = require("mustache");
|
||||
const openpgp = require("openpgp");
|
||||
const Notifications = require("./Notifications.js");
|
||||
const Odmdb = require("./Odmdb.js");
|
||||
|
||||
const conf = require(`../../../conf.json`);
|
||||
const currentmod = "Pagans";
|
||||
const log = conf.api.activelog.includes(currentmod);
|
||||
/**
|
||||
* Pagan Management numeric Identity and Person (Person = Pagan Id + tribe)
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
const Pagans = {};
|
||||
|
||||
Pagans.create=()=>{
|
||||
//from router.post("/", checkHeaders, isAuthenticated, async (req, res)
|
||||
}
|
||||
|
||||
Pagans.joinpersontotribe=()=>{
|
||||
// from router.post("/", checkHeaders, isAuthenticated, async (req, res)
|
||||
|
||||
}
|
||||
/**
|
||||
* Remove authentification token after a logout
|
||||
* @param {string} alias
|
||||
* @param {string} tribe
|
||||
* @param {integer} xdays
|
||||
* @param {string} xhash
|
||||
* @returns {status:200, ref:"Pagans",msg:"logout"}
|
||||
* tmpfs name file has to be on line with the tmpfs create by isAuthenticated
|
||||
* tmpfs contain profils name for a tribe/
|
||||
*/
|
||||
Pagans.logout = (alias, tribe, xdays, xhash) => {
|
||||
//console.log(alias, tribe, xdays, xhash);
|
||||
// inline with middleware isAuthenticated.js
|
||||
let tmpfs = `../../tmp/tokens/${alias}_${tribe}_${xdays}`;
|
||||
//max filename in ext4: 255 characters
|
||||
tmpfs += `_${xhash.substring(150, 150 + tmpfs.length - 249)}.json`;
|
||||
fs.remove(tmpfs);
|
||||
if (log) console.log(currentmod, "logout token", tmpfs);
|
||||
return { status: 200, ref: "Pagans", msg: "logout" };
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {string} alias a alias that exist or not
|
||||
* @return {object} { status: 200, ref:"pagans",msg:"aliasexist",data: { alias, publicKey } }
|
||||
* { status: 404, ref:"pagans",msg:"aliasdoesnotexist",data: { alias} }
|
||||
*
|
||||
**/
|
||||
Pagans.getalias = (alias) => {
|
||||
//bypass Odmdb cause all is public save ressources
|
||||
console.log(path.resolve(`../objects/pagans/itm/${alias}.json`));
|
||||
if (fs.existsSync(`../objects/pagans/itm/${alias}.json`)) {
|
||||
return {
|
||||
status: 200,
|
||||
ref: "Pagans",
|
||||
msg: "aliasexist",
|
||||
data: fs.readJSONSync(`../objects/pagans/itm/${alias}.json`),
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
status: 404,
|
||||
ref: "Pagans",
|
||||
msg: "aliasdoesnotexist",
|
||||
data: { alias },
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Send email with alias's keys to email or person alias person.recovery.email
|
||||
*
|
||||
* If email or pubkey is undefined then get data from tribe/person(alias)
|
||||
* Send email with keys
|
||||
* @param {object} data
|
||||
* @param {string} data.alias
|
||||
* @param {pgpPrivate} [data.privatekey]
|
||||
* @param {string} [data.passphrase]
|
||||
* @param {string} data.tribe
|
||||
* @param {pgpPublic} [data.publickey]
|
||||
* @param {string} [data.email]
|
||||
* @param {string} data.lg
|
||||
*/
|
||||
Pagans.sendmailkey = (data) => {
|
||||
if (log)
|
||||
console.log(
|
||||
currentmod,
|
||||
data.alias,
|
||||
"-",
|
||||
data.privatekey ? data.privatekey.substring(0, 10) : "",
|
||||
"-",
|
||||
data.tribe,
|
||||
"-",
|
||||
data.passphrase,
|
||||
"-",
|
||||
data.publickey ? data.publickey.substring(0, 10) : "",
|
||||
"-",
|
||||
data.email,
|
||||
"-",
|
||||
data.lg
|
||||
);
|
||||
const person = {
|
||||
alias: data.alias,
|
||||
privatekey: data.privatekey,
|
||||
tribe: data.tribe,
|
||||
};
|
||||
|
||||
if (!data.publickey || !data.email || !data.privatekey) {
|
||||
const personfile = `../../${data.tribe}/objects/persons/itm/${data.alias}.json`;
|
||||
if (!fs.existsSync(personfile)) {
|
||||
return {
|
||||
status: 404,
|
||||
ref: "Pagans",
|
||||
msg: "persondoesnotexist",
|
||||
data: { alias: data.alias, tribe: data.tribe },
|
||||
};
|
||||
}
|
||||
const persondata = fs.readJsonSync(personfile);
|
||||
if (!persondata.recoveryauth) {
|
||||
return {
|
||||
status: 404,
|
||||
ref: "Pagans",
|
||||
msg: "personhasnorecoveryauth",
|
||||
data: { alias: data.alias, tribe: data.tribe, email: data.email },
|
||||
};
|
||||
}
|
||||
person.email = persondata.recoveryauth.email;
|
||||
person.publickey = persondata.recoveryauth.publickey;
|
||||
person.privatekey = persondata.recoveryauth.privatekey;
|
||||
person.passphrase = persondata.recoveryauth.passphrase;
|
||||
} else {
|
||||
person.email = data.email;
|
||||
person.passphrase = data.passphrase;
|
||||
person.publickey = data.publickey;
|
||||
}
|
||||
person.avecpassphrase = person.passphrase != "";
|
||||
let tplfile = `../../${data.tribe}/template/createidentity_${data.lg}.js`;
|
||||
if (!fs.existsSync(tplfile)) {
|
||||
tplfile = `../template/createidentity_${data.lg}.js`;
|
||||
if (!fs.existsSync(tplfile)) {
|
||||
return {
|
||||
status: 406,
|
||||
ref: "Pagans",
|
||||
msg: "templatedoesnotexist",
|
||||
data: { tplfile },
|
||||
};
|
||||
}
|
||||
}
|
||||
const tplemail = require(path.resolve(tplfile));
|
||||
/*
|
||||
Remove from attachments for less user confusing
|
||||
{
|
||||
filename:`${person.alias}_publickey.txt`,
|
||||
content: person.publickey,
|
||||
contentType:"text/plain"
|
||||
},
|
||||
*/
|
||||
const maildata = {
|
||||
from: tplemail.sender,
|
||||
to: person.email,
|
||||
subject: Mustache.render(tplemail.subject, person),
|
||||
html: Mustache.render(tplemail.html, person),
|
||||
text: Mustache.render(tplemail.text, person),
|
||||
attachments: [
|
||||
{
|
||||
filename: `${person.alias}_privatekey.txt`,
|
||||
content: person.privatekey,
|
||||
contentType: "text/plain",
|
||||
},
|
||||
],
|
||||
};
|
||||
return Notifications.sendmail(maildata, data.tribe);
|
||||
};
|
||||
|
||||
Pagans.authenticatedetachedSignature = async (
|
||||
alias,
|
||||
pubK,
|
||||
detachedSignature,
|
||||
message
|
||||
) => {
|
||||
/**
|
||||
* Check that a message was signed with a privateKey from a publicKey
|
||||
* This is not necessary if isAuthenticated, but can be usefull to double check
|
||||
* @TODO finish it and implement it also in /apxpagan.js for browser
|
||||
* @alias {string} alias link to the publicKey
|
||||
* @pubK {string} publiKey text format
|
||||
* @detachedSignature {string} a detachedsignatured get from apx.detachedSignature
|
||||
* @message {string} the message signed
|
||||
* @return {boolean} true the message was signed by alias
|
||||
* false the message was not signed by alias
|
||||
*/
|
||||
const publicKey = await openpgp.readKey({ armoredKey: pubK });
|
||||
const msg = await openpgp.createMessage({ text: message });
|
||||
const signature = await openpgp.readSignature({
|
||||
armoredSignature: detachedSignature, // parse detached signature
|
||||
});
|
||||
const verificationResult = await openpgp.verify({
|
||||
msg, // Message object
|
||||
signature,
|
||||
verificationKeys: publicKey,
|
||||
});
|
||||
const { verified, keyID } = verificationResult.signatures[0];
|
||||
try {
|
||||
await verified; // throws on invalid signature
|
||||
if (log) console.log(currentmod, "Signed by key id " + keyID.toHex());
|
||||
return KeyId.toHex().alias == alias;
|
||||
} catch (e) {
|
||||
if (log)
|
||||
console.log(currentmod, "Signature could not be verified: " + e.message);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = Pagans;
|
@ -44,13 +44,24 @@ router.get("/messages/:alias/:tribeId", (req, res) => {
|
||||
/**
|
||||
* @api {POST} adminapi/notifications/sendmail/:tribe/:template -Send personnalize emails
|
||||
* @apiName Sendmail
|
||||
* @apiDescription Send personnalize email with data from template store in ../../{tribe}/template/{template}.json
|
||||
* @apiDescription Send personnalize email with data from template store in ../../{tribe}/template/{template}.json and smtp in conf global or in /itm/{tribe}.json that must have valid parameter emailcontact must be authorized by the smtp
|
||||
* "emailcontact": "noreply@smatchit.io",
|
||||
* "smtp": {
|
||||
* "host": "smtp-relay.brevo.com",
|
||||
* "port": 587,
|
||||
* "secure": false,
|
||||
* "auth": {
|
||||
* "user": "xx",
|
||||
* "pass": "yy"
|
||||
* }
|
||||
* }
|
||||
|
||||
* @apiGroup Notifications
|
||||
*
|
||||
* @apiParam {string} template
|
||||
* @apiParam {string} tribe
|
||||
* @apiBody {array} emails to send (array of valid email)
|
||||
* @apiBody {object} Data to personnalize template
|
||||
* @apiBody {object} data to personnalize template
|
||||
*
|
||||
* @apiSuccess {object} notif content
|
||||
* @apiSuccessExample {json} Success-Response:
|
||||
@ -59,24 +70,19 @@ router.get("/messages/:alias/:tribeId", (req, res) => {
|
||||
* bouture
|
||||
*/
|
||||
router.post(
|
||||
"/sendmail/:tribe/:template/:await",
|
||||
"/sendmail/:tribe/:template",
|
||||
checkHeaders,
|
||||
isAuthenticated,
|
||||
(req, res) => {
|
||||
const pathtpl = `../../${req.params.tribe}/${req.params.template}.js`;
|
||||
if (fs.existsSync(pathtpl)) {
|
||||
const sendemail = Notification.manageemail(req.body, pathtpl,req.params.tribe);
|
||||
async (req, res) => {
|
||||
const data = req.body.data;
|
||||
data.emailsto = req.body.emails;
|
||||
const pathtpl = `../../${req.params.tribe}/template/${req.params.template}_${req.session.header.xlang}.js`;
|
||||
const sendemail = await Notifications.manageemail(
|
||||
data,
|
||||
pathtpl,
|
||||
req.params.tribe
|
||||
);
|
||||
res.status(sendemail.status).send(sendemail);
|
||||
} else {
|
||||
res
|
||||
.status(404)
|
||||
.send({
|
||||
status: 404,
|
||||
ref: "Notification",
|
||||
msg: "templatenotfound",
|
||||
data: { pathtpl },
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
@ -99,9 +105,7 @@ router.post(
|
||||
router.post("/registeranonymous", checkHeaders, (req, res) => {
|
||||
//console.log("list registration ",req.body)
|
||||
if (!req.body.typekey || !["email", "telephone"].includes(req.body.typekey)) {
|
||||
return res
|
||||
.status(406)
|
||||
.json({
|
||||
return res.status(406).json({
|
||||
status: 406,
|
||||
ref: "Notifications",
|
||||
msg: "typekeyunknown",
|
||||
|
Loading…
x
Reference in New Issue
Block a user