195 lines
7.2 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
Сервис интеграции ПП Парус 8 с WEB API
Дополнительный модуль: Рассылка E-Mail (MAIL)
*/
//------------------------------
// Подключение внешних библиотек
//------------------------------
const xml2js = require("xml2js"); //Конвертация XML в JSON и JSON в XML
const cfg = require("./../config"); //Настройки сервера приложений
const { makeErrorText, sendMail } = require("./../core/utils"); //Вспомогательные функции
const oracledb = require("oracledb"); //Работа с СУБД Oracle
//---------------------
// Глобальные константы
//---------------------
//Статусы отправки
const NSTATUS_ERR = 2;
const NSTATUS_DONE = 3;
//------------
// Тело модуля
//------------
//Чтение данных из курсора
const readCursorData = cursor => {
return new Promise((resolve, reject) => {
let queryStream = cursor.toQueryStream();
let rows = [];
queryStream.on("data", row => {
rows.push(row);
});
queryStream.on("error", err => {
reject(new Error(err.message));
});
queryStream.on("close", () => {
resolve(rows);
});
});
};
//Установка статуса отправки
const setSendMsg = async prms => {
let pooledConnection;
try {
pooledConnection = await prms.connection.getConnection();
await pooledConnection.execute(
"begin PKG_EXS_EXT_MAIL.EXSEXTMAIL_SET_STATUS(NRN => :NRN, SERR_TEXT => :SERR_TEXT, NSTATUS => :NSTATUS); end;",
{ NRN: prms.nRn, SERR_TEXT: prms.sErrMsg, NSTATUS: prms.nStatus },
{ autoCommit: true }
);
} catch (e) {
throw new Error(e.message);
} finally {
if (pooledConnection) {
try {
await pooledConnection.close();
} catch (e) {
throw new Error(e.message);
}
}
}
};
//Считывание записей прикладываемых документов
const getMailAttach = async prms => {
let pooledConnection;
try {
pooledConnection = await prms.connection.getConnection();
let res = await pooledConnection.execute(
"begin PKG_EXS_EXT_MAIL.GET_ATTACH(NIDENT => :NIDENT, RCDOCUMENTS => :RCDOCUMENTS); end;",
{
NIDENT: prms.nIdent,
RCDOCUMENTS: { type: oracledb.CURSOR, dir: oracledb.BIND_OUT }
},
{ outFormat: oracledb.OBJECT, autoCommit: true }
);
let rows = await readCursorData(res.outBinds.RCDOCUMENTS);
let rowsRes = [];
//Если результат запроса не пустой
if (rows.length !== 0) {
//Переводим BLOB в BUFFER и формируем формат аттача
for (let i = 0; i < rows.length; i++) {
let rowContent = await rows[i].BDATA.getData();
rowsRes.push({
filename: rows[i].FILENAME,
content: rowContent
});
}
}
return rowsRes;
} catch (e) {
throw new Error(e.message);
} finally {
if (pooledConnection) {
try {
await pooledConnection.close();
} catch (e) {
throw new Error(e.message);
}
}
}
};
//Разбор XML
const parseXML = xmlDoc => {
return new Promise((resolve, reject) => {
xml2js.parseString(xmlDoc, { explicitArray: false, mergeAttrs: true }, (err, result) => {
if (err) reject(err);
else resolve(result);
});
});
};
//Обработчик "До" для исходящего сообщения
const before = async prms => {
//Инициализируем переменные
let res = "OK";
let parseRes = null;
//Разбираем параметры отправки
try {
//Формируем объект на основании XML
parseRes = await parseXML(prms.queue.blMsg.toString());
//Если есть присоединенные файлы - добавляем их
if (parseRes.mail.ident) {
parseRes.mail.attachments = await getMailAttach({ connection: prms.dbConn.connection, nIdent: parseRes.mail.ident });
}
//Если указан текст в обычном формате
if (parseRes.mail.text) {
parseRes.mail.text = Buffer.from(parseRes.mail.text, "base64").toString("utf-8");
}
//Если указан текст в формате HTML
if (parseRes.mail.html) {
parseRes.mail.html = Buffer.from(parseRes.mail.html, "base64").toString("utf-8");
}
} catch (e) {
parseRes = prms.queue.blMsg.toString();
res = `Ошибка разбора параметров отправки: ${makeErrorText(e)}`;
}
if (res === "OK") {
try {
await sendMail({
mail: cfg.mail,
sTo: parseRes.mail.to,
sSubject: parseRes.mail.title,
sMessage: parseRes.mail.text,
sHTML: parseRes.mail.html,
attachments: parseRes.mail.attachments
});
} catch (e) {
res = `Ошибка отправки E-Mail сообщения: ${makeErrorText(e)}`;
}
}
//Если сообщение отправилось
if (res === "OK") {
//Если имеется рег. номер записи очереди отправки E-mail - обновляем информацию о текущем сообщении
if (parseRes.mail.nExsextmailId) {
await setSendMsg({
connection: prms.dbConn.connection,
nRn: parseRes.mail.nExsextmailId,
sErrMsg: "",
nStatus: NSTATUS_DONE
});
}
} else {
//Если количество попыток не указано или это последняя попытка
if (prms.queue.nRetryAttempts === 0 || (prms.queue.nRetryAttempts !== 0 && prms.queue.nExecCnt + 1 === prms.queue.nRetryAttempts)) {
//Если имеется рег. номер записи очереди отправки E-mail - обновляем информацию о текущем сообщении
if (parseRes.mail.nExsextmailId) {
await setSendMsg({
connection: prms.dbConn.connection,
nRn: parseRes.mail.nExsextmailId,
sErrMsg: res,
nStatus: NSTATUS_ERR
});
}
}
//Выдаем ошибку
throw new Error(res);
}
//Возвращаем результат и флаг того, что дальше отрабатывать это сообщение не надо
return {
blMsg: Buffer.from(JSON.stringify({ message: parseRes, state: res })),
bStopPropagation: true
};
};
//-----------------
// Интерфейс модуля
//-----------------
exports.before = before;