forked from CITKParus/P8-ExchangeService
ЦИТК-441 - новое расширение "Рассылка E-Mail"
This commit is contained in:
parent
0146702e1c
commit
56e3cff024
@ -13,15 +13,7 @@ const express = require("express"); //WEB-сервер Express
|
|||||||
const cors = require("cors"); //Управление заголовками безопасности для WEB-сервера Express
|
const cors = require("cors"); //Управление заголовками безопасности для WEB-сервера Express
|
||||||
const bodyParser = require("body-parser"); //Модуль для Express (разбор тела входящего запроса)
|
const bodyParser = require("body-parser"); //Модуль для Express (разбор тела входящего запроса)
|
||||||
const { ServerError } = require("./server_errors"); //Типовая ошибка
|
const { ServerError } = require("./server_errors"); //Типовая ошибка
|
||||||
const {
|
const { makeErrorText, validateObject, buildURL, getAppSrvFunction, buildOptionsXML, parseOptionsXML, deepMerge } = require("./utils"); //Вспомогательные функции
|
||||||
makeErrorText,
|
|
||||||
validateObject,
|
|
||||||
buildURL,
|
|
||||||
getAppSrvFunction,
|
|
||||||
buildOptionsXML,
|
|
||||||
parseOptionsXML,
|
|
||||||
deepMerge
|
|
||||||
} = require("./utils"); //Вспомогательные функции
|
|
||||||
const { NINC_EXEC_CNT_YES, NIS_ORIGINAL_NO, NIS_ORIGINAL_YES } = require("../models/prms_db_connector"); //Схемы валидации параметров функций модуля взаимодействия с БД
|
const { NINC_EXEC_CNT_YES, NIS_ORIGINAL_NO, NIS_ORIGINAL_YES } = require("../models/prms_db_connector"); //Схемы валидации параметров функций модуля взаимодействия с БД
|
||||||
const objInQueueSchema = require("../models/obj_in_queue"); //Схема валидации сообщений обмена с бработчиком очереди входящих сообщений
|
const objInQueueSchema = require("../models/obj_in_queue"); //Схема валидации сообщений обмена с бработчиком очереди входящих сообщений
|
||||||
const objServiceSchema = require("../models/obj_service"); //Схемы валидации сервиса
|
const objServiceSchema = require("../models/obj_service"); //Схемы валидации сервиса
|
||||||
@ -96,11 +88,7 @@ class InQueue extends EventEmitter {
|
|||||||
//Обработка сообщения
|
//Обработка сообщения
|
||||||
async processMessage(prms) {
|
async processMessage(prms) {
|
||||||
//Проверяем структуру переданного объекта для обработки
|
//Проверяем структуру переданного объекта для обработки
|
||||||
let sCheckResult = validateObject(
|
let sCheckResult = validateObject(prms, prmsInQueueSchema.processMessage, "Параметры функции обработки входящего сообщения");
|
||||||
prms,
|
|
||||||
prmsInQueueSchema.processMessage,
|
|
||||||
"Параметры функции обработки входящего сообщения"
|
|
||||||
);
|
|
||||||
//Если структура объекта в норме
|
//Если структура объекта в норме
|
||||||
if (!sCheckResult) {
|
if (!sCheckResult) {
|
||||||
//Буфер для сообщения очереди
|
//Буфер для сообщения очереди
|
||||||
@ -135,9 +123,10 @@ class InQueue extends EventEmitter {
|
|||||||
});
|
});
|
||||||
//Скажем что пришло новое входящее сообщение
|
//Скажем что пришло новое входящее сообщение
|
||||||
await this.logger.info(
|
await this.logger.info(
|
||||||
`Новое входящее сообщение от ${prms.req.connection.address().address} для функции ${
|
`Новое входящее сообщение от ${prms.req.connection.address().address} для функции ${prms.function.sCode} (${buildURL({
|
||||||
prms.function.sCode
|
sSrvRoot: prms.service.sSrvRoot,
|
||||||
} (${buildURL({ sSrvRoot: prms.service.sSrvRoot, sFnURL: prms.function.sFnURL })})`,
|
sFnURL: prms.function.sFnURL
|
||||||
|
})})`,
|
||||||
{ nQueueId: q.nId }
|
{ nQueueId: q.nId }
|
||||||
);
|
);
|
||||||
//Выполняем обработчик "До" (если он есть)
|
//Выполняем обработчик "До" (если он есть)
|
||||||
@ -200,13 +189,11 @@ class InQueue extends EventEmitter {
|
|||||||
let sOptionsResp = buildOptionsXML({ options: optionsResp });
|
let sOptionsResp = buildOptionsXML({ options: optionsResp });
|
||||||
q = await this.dbConn.setQueueOptionsResp({ nQueueId: q.nId, sOptionsResp });
|
q = await this.dbConn.setQueueOptionsResp({ nQueueId: q.nId, sOptionsResp });
|
||||||
}
|
}
|
||||||
//Если пришел флаг ошибочной аутентификации и он положительный - то это ошибка, дальше ничего не делаем
|
//Фиксируем результат исполнения "До" - флаг ошибочной аутентификации - если он поднят, то это ошибка, дальше ничего не делаем
|
||||||
if (!_.isUndefined(resBefore.bUnAuth))
|
if (!_.isUndefined(resBefore.bUnAuth) && resBefore.bUnAuth === true)
|
||||||
if (resBefore.bUnAuth === true)
|
throw new ServerError(SERR_UNAUTH, "Нет аутентификации");
|
||||||
throw new ServerError(SERR_UNAUTH, "Нет аутентификации");
|
//Фиксируем результат исполнения "До" - флаг прекращения дальнейшей обработки сообщения - если он поднят, то дальше обработку сообщения прекращаем
|
||||||
//Если пришел флаг прекращения дальнейшей обработки сообщения - то дальше его обработку прекращаем
|
if (!_.isUndefined(resBefore.bStopPropagation) && resBefore.bStopPropagation === true) bStopPropagation = true;
|
||||||
if (!_.isUndefined(resBefore.bStopPropagation))
|
|
||||||
if (resBefore.bStopPropagation === true) bStopPropagation = true;
|
|
||||||
} else {
|
} else {
|
||||||
//Или расскажем об ошибке
|
//Или расскажем об ошибке
|
||||||
throw new ServerError(SERR_OBJECT_BAD_INTERFACE, sCheckResult);
|
throw new ServerError(SERR_OBJECT_BAD_INTERFACE, sCheckResult);
|
||||||
@ -223,8 +210,7 @@ class InQueue extends EventEmitter {
|
|||||||
//Вызов обработчика БД
|
//Вызов обработчика БД
|
||||||
let prcRes = await this.dbConn.execQueueDBPrc({ nQueueId: q.nId });
|
let prcRes = await this.dbConn.execQueueDBPrc({ nQueueId: q.nId });
|
||||||
//Если результат - ошибка пробрасываем её
|
//Если результат - ошибка пробрасываем её
|
||||||
if (prcRes.sResult == objQueueSchema.SPRC_RESP_RESULT_ERR)
|
if (prcRes.sResult == objQueueSchema.SPRC_RESP_RESULT_ERR) throw new ServerError(SERR_DB_SERVER, prcRes.sMsg);
|
||||||
throw new ServerError(SERR_DB_SERVER, prcRes.sMsg);
|
|
||||||
//Если результат - ошибка аутентификации, то и её пробрасываем, но с правильным кодом
|
//Если результат - ошибка аутентификации, то и её пробрасываем, но с правильным кодом
|
||||||
if (prcRes.sResult == objQueueSchema.SPRC_RESP_RESULT_UNAUTH)
|
if (prcRes.sResult == objQueueSchema.SPRC_RESP_RESULT_UNAUTH)
|
||||||
throw new ServerError(SERR_UNAUTH, prcRes.sMsg || "Нет аутентификации");
|
throw new ServerError(SERR_UNAUTH, prcRes.sMsg || "Нет аутентификации");
|
||||||
@ -339,10 +325,7 @@ class InQueue extends EventEmitter {
|
|||||||
nExecState: objQueueSchema.NQUEUE_EXEC_STATE_ERR
|
nExecState: objQueueSchema.NQUEUE_EXEC_STATE_ERR
|
||||||
});
|
});
|
||||||
//Фиксируем ошибку обработки сервером приложений - в протоколе работы сервиса
|
//Фиксируем ошибку обработки сервером приложений - в протоколе работы сервиса
|
||||||
await this.logger.error(
|
await this.logger.error(`Ошибка обработки входящего сообщения ${q.nId} сервером приложений: ${sMessage}`, { nQueueId: q.nId });
|
||||||
`Ошибка обработки входящего сообщения ${q.nId} сервером приложений: ${sMessage}`,
|
|
||||||
{ nQueueId: q.nId }
|
|
||||||
);
|
|
||||||
//Добавим чуть больше информации в тему сообщения
|
//Добавим чуть больше информации в тему сообщения
|
||||||
sSubject = `Ошибка обработки входящего сообщения ${q.nId} сервером приложений для функции "${prms.function.sCode}" сервиса "${prms.service.sCode}"`;
|
sSubject = `Ошибка обработки входящего сообщения ${q.nId} сервером приложений для функции "${prms.function.sCode}" сервиса "${prms.service.sCode}"`;
|
||||||
} else {
|
} else {
|
||||||
@ -371,11 +354,7 @@ class InQueue extends EventEmitter {
|
|||||||
//Запуск обработки очереди входящих сообщений
|
//Запуск обработки очереди входящих сообщений
|
||||||
startProcessing(prms) {
|
startProcessing(prms) {
|
||||||
//Проверяем структуру переданного объекта для старта
|
//Проверяем структуру переданного объекта для старта
|
||||||
let sCheckResult = validateObject(
|
let sCheckResult = validateObject(prms, prmsInQueueSchema.startProcessing, "Параметры функции запуска обработки очереди входящих сообщений");
|
||||||
prms,
|
|
||||||
prmsInQueueSchema.startProcessing,
|
|
||||||
"Параметры функции запуска обработки очереди входящих сообщений"
|
|
||||||
);
|
|
||||||
//Если структура объекта в норме
|
//Если структура объекта в норме
|
||||||
if (!sCheckResult) {
|
if (!sCheckResult) {
|
||||||
//Выставляем флаг работы
|
//Выставляем флаг работы
|
||||||
@ -431,18 +410,15 @@ class InQueue extends EventEmitter {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
//...и собственный обработчик ошибок
|
//...и собственный обработчик ошибок
|
||||||
this.webApp.use(
|
this.webApp.use(buildURL({ sSrvRoot: srvs.sSrvRoot, sFnURL: fn.sFnURL }), async (err, req, res, next) => {
|
||||||
buildURL({ sSrvRoot: srvs.sSrvRoot, sFnURL: fn.sFnURL }),
|
//Протоколируем в журнал работы сервера
|
||||||
async (err, req, res, next) => {
|
await this.logger.error(makeErrorText(new ServerError(SERR_WEB_SERVER, err.message)), {
|
||||||
//Протоколируем в журнал работы сервера
|
nServiceId: srvs.nId,
|
||||||
await this.logger.error(makeErrorText(new ServerError(SERR_WEB_SERVER, err.message)), {
|
nServiceFnId: fn.nId
|
||||||
nServiceId: srvs.nId,
|
});
|
||||||
nServiceFnId: fn.nId
|
//Отправим ошибку клиенту
|
||||||
});
|
res.status(500).send(makeErrorText(new ServerError(SERR_WEB_SERVER, err.message)));
|
||||||
//Отправим ошибку клиенту
|
});
|
||||||
res.status(500).send(makeErrorText(new ServerError(SERR_WEB_SERVER, err.message)));
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
@ -12,15 +12,7 @@ const _ = require("lodash"); //Работа с массивами и объек
|
|||||||
const rqp = require("request-promise"); //Работа с HTTP/HTTPS запросами
|
const rqp = require("request-promise"); //Работа с HTTP/HTTPS запросами
|
||||||
const lg = require("./logger"); //Протоколирование работы
|
const lg = require("./logger"); //Протоколирование работы
|
||||||
const db = require("./db_connector"); //Взаимодействие с БД
|
const db = require("./db_connector"); //Взаимодействие с БД
|
||||||
const {
|
const { makeErrorText, validateObject, getAppSrvFunction, buildURL, parseOptionsXML, buildOptionsXML, deepMerge } = require("./utils"); //Вспомогательные функции
|
||||||
makeErrorText,
|
|
||||||
validateObject,
|
|
||||||
getAppSrvFunction,
|
|
||||||
buildURL,
|
|
||||||
parseOptionsXML,
|
|
||||||
buildOptionsXML,
|
|
||||||
deepMerge
|
|
||||||
} = require("./utils"); //Вспомогательные функции
|
|
||||||
const { ServerError } = require("./server_errors"); //Типовая ошибка
|
const { ServerError } = require("./server_errors"); //Типовая ошибка
|
||||||
const objOutQueueProcessorSchema = require("../models/obj_out_queue_processor"); //Схема валидации сообщений обмена с бработчиком очереди исходящих сообщений
|
const objOutQueueProcessorSchema = require("../models/obj_out_queue_processor"); //Схема валидации сообщений обмена с бработчиком очереди исходящих сообщений
|
||||||
const prmsOutQueueProcessorSchema = require("../models/prms_out_queue_processor"); //Схема валидации параметров функций модуля
|
const prmsOutQueueProcessorSchema = require("../models/prms_out_queue_processor"); //Схема валидации параметров функций модуля
|
||||||
@ -35,12 +27,7 @@ const {
|
|||||||
SERR_WEB_SERVER,
|
SERR_WEB_SERVER,
|
||||||
SERR_UNAUTH
|
SERR_UNAUTH
|
||||||
} = require("./constants"); //Глобальные константы
|
} = require("./constants"); //Глобальные константы
|
||||||
const {
|
const { NINC_EXEC_CNT_YES, NINC_EXEC_CNT_NO, NIS_ORIGINAL_NO, NIS_ORIGINAL_YES } = require("../models/prms_db_connector"); //Схемы валидации параметров функций модуля взаимодействия с БД
|
||||||
NINC_EXEC_CNT_YES,
|
|
||||||
NINC_EXEC_CNT_NO,
|
|
||||||
NIS_ORIGINAL_NO,
|
|
||||||
NIS_ORIGINAL_YES
|
|
||||||
} = require("../models/prms_db_connector"); //Схемы валидации параметров функций модуля взаимодействия с БД
|
|
||||||
|
|
||||||
//--------------------------
|
//--------------------------
|
||||||
// Глобальные идентификаторы
|
// Глобальные идентификаторы
|
||||||
@ -112,8 +99,7 @@ const appProcess = async prms => {
|
|||||||
//Проверяем аутентификацию
|
//Проверяем аутентификацию
|
||||||
if (
|
if (
|
||||||
prms.function.nAuthOnly == objServiceFnSchema.NAUTH_ONLY_NO ||
|
prms.function.nAuthOnly == objServiceFnSchema.NAUTH_ONLY_NO ||
|
||||||
(prms.function.nAuthOnly == objServiceFnSchema.NAUTH_ONLY_YES &&
|
(prms.function.nAuthOnly == objServiceFnSchema.NAUTH_ONLY_YES && isServiceAuth == objServiceSchema.NIS_AUTH_YES)
|
||||||
isServiceAuth == objServiceSchema.NIS_AUTH_YES)
|
|
||||||
) {
|
) {
|
||||||
//Фиксируем начало исполнения сервером приложений - в статусе сообщения
|
//Фиксируем начало исполнения сервером приложений - в статусе сообщения
|
||||||
res = await dbConn.setQueueState({
|
res = await dbConn.setQueueState({
|
||||||
@ -122,9 +108,9 @@ const appProcess = async prms => {
|
|||||||
});
|
});
|
||||||
//Фиксируем начало исполнения сервером приложений - в протоколе работы сервиса
|
//Фиксируем начало исполнения сервером приложений - в протоколе работы сервиса
|
||||||
await logger.info(
|
await logger.info(
|
||||||
`Обрабатываю исходящее сообщение сервером приложений: ${prms.queue.nId}, ${prms.queue.sInDate}, ${
|
`Обрабатываю исходящее сообщение сервером приложений: ${prms.queue.nId}, ${prms.queue.sInDate}, ${prms.queue.sServiceFnCode}, ${
|
||||||
prms.queue.sServiceFnCode
|
prms.queue.sExecState
|
||||||
}, ${prms.queue.sExecState}, попытка исполнения - ${prms.queue.nExecCnt + 1}`,
|
}, попытка исполнения - ${prms.queue.nExecCnt + 1}`,
|
||||||
{ nQueueId: prms.queue.nId }
|
{ nQueueId: prms.queue.nId }
|
||||||
);
|
);
|
||||||
//Считаем тело сообщения
|
//Считаем тело сообщения
|
||||||
@ -141,6 +127,8 @@ const appProcess = async prms => {
|
|||||||
let options = { method: prms.function.sFnPrmsType, encoding: null };
|
let options = { method: prms.function.sFnPrmsType, encoding: null };
|
||||||
//Инициализируем параметры ответа сервера
|
//Инициализируем параметры ответа сервера
|
||||||
let optionsResp = {};
|
let optionsResp = {};
|
||||||
|
//Флаг прекращения обработки сообщения
|
||||||
|
let bStopPropagation = false;
|
||||||
//Определимся с URL и телом сообщения в зависимости от способа передачи параметров
|
//Определимся с URL и телом сообщения в зависимости от способа передачи параметров
|
||||||
if (prms.function.nFnPrmsType == objServiceFnSchema.NFN_PRMS_TYPE_POST) {
|
if (prms.function.nFnPrmsType == objServiceFnSchema.NFN_PRMS_TYPE_POST) {
|
||||||
options.url = buildURL({ sSrvRoot: prms.service.sSrvRoot, sFnURL: prms.function.sFnURL });
|
options.url = buildURL({ sSrvRoot: prms.service.sSrvRoot, sFnURL: prms.function.sFnURL });
|
||||||
@ -176,6 +164,7 @@ const appProcess = async prms => {
|
|||||||
try {
|
try {
|
||||||
let resBeforePrms = _.cloneDeep(prms);
|
let resBeforePrms = _.cloneDeep(prms);
|
||||||
resBeforePrms.options = _.cloneDeep(options);
|
resBeforePrms.options = _.cloneDeep(options);
|
||||||
|
resBeforePrms.dbConn = dbConn;
|
||||||
resBefore = await fnBefore(resBeforePrms);
|
resBefore = await fnBefore(resBeforePrms);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
throw new ServerError(SERR_APP_SERVER_BEFORE, e.message);
|
throw new ServerError(SERR_APP_SERVER_BEFORE, e.message);
|
||||||
@ -225,123 +214,123 @@ const appProcess = async prms => {
|
|||||||
});
|
});
|
||||||
bCtxIsSet = true;
|
bCtxIsSet = true;
|
||||||
}
|
}
|
||||||
|
//Применим ответ "До" - флаг прекращения дальнейшей обработки сообщения - если он поднят, то дальше обработку сообщения прекращаем
|
||||||
|
if (!_.isUndefined(resBefore.bStopPropagation) && resBefore.bStopPropagation === true) bStopPropagation = true;
|
||||||
} else {
|
} else {
|
||||||
//Или расскажем об ошибке в структуре ответа
|
//Или расскажем об ошибке в структуре ответа
|
||||||
throw new ServerError(SERR_OBJECT_BAD_INTERFACE, sCheckResult);
|
throw new ServerError(SERR_OBJECT_BAD_INTERFACE, sCheckResult);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//Фиксируем отправку сообщения в протоколе работы сервиса
|
//Если флаг прекращения обработки сообщения не установлен
|
||||||
await logger.info(`Отправляю исходящее сообщение ${prms.queue.nId} на URL: ${options.url}`, {
|
if (bStopPropagation === false) {
|
||||||
nQueueId: prms.queue.nId
|
//Фиксируем отправку сообщения в протоколе работы сервиса
|
||||||
});
|
await logger.info(`Отправляю исходящее сообщение ${prms.queue.nId} на URL: ${options.url}`, {
|
||||||
//Отправляем сообщение удалённому серверу
|
nQueueId: prms.queue.nId
|
||||||
try {
|
|
||||||
//Сохраняем параметры с которыми уходило сообщение
|
|
||||||
try {
|
|
||||||
let tmpOptions = _.cloneDeep(options);
|
|
||||||
delete tmpOptions.body;
|
|
||||||
let sOptions = buildOptionsXML({ options: tmpOptions });
|
|
||||||
await dbConn.setQueueOptions({ nQueueId: prms.queue.nId, sOptions });
|
|
||||||
} catch (e) {
|
|
||||||
await logger.warn(`Не удалось сохранить параметры отправки сообщения: ${makeErrorText(e)}`, {
|
|
||||||
nQueueId: prms.queue.nId
|
|
||||||
});
|
|
||||||
}
|
|
||||||
//Ждем ответ от удалённого сервера
|
|
||||||
options.resolveWithFullResponse = true;
|
|
||||||
let serverResp = await rqp(options);
|
|
||||||
//Сохраняем полученный ответ
|
|
||||||
prms.queue.blResp = Buffer.from(serverResp.body || "");
|
|
||||||
await dbConn.setQueueResp({
|
|
||||||
nQueueId: prms.queue.nId,
|
|
||||||
blResp: prms.queue.blResp,
|
|
||||||
nIsOriginal: NIS_ORIGINAL_YES
|
|
||||||
});
|
});
|
||||||
//Сохраняем заголовки ответа и HTTP-статус
|
//Отправляем сообщение удалённому серверу
|
||||||
optionsResp.headers = _.cloneDeep(serverResp.headers);
|
|
||||||
optionsResp.statusCode = serverResp.statusCode;
|
|
||||||
try {
|
try {
|
||||||
let sOptionsResp = buildOptionsXML({ options: optionsResp });
|
//Сохраняем параметры с которыми уходило сообщение
|
||||||
await dbConn.setQueueOptionsResp({ nQueueId: prms.queue.nId, sOptionsResp });
|
try {
|
||||||
|
let tmpOptions = _.cloneDeep(options);
|
||||||
|
delete tmpOptions.body;
|
||||||
|
let sOptions = buildOptionsXML({ options: tmpOptions });
|
||||||
|
await dbConn.setQueueOptions({ nQueueId: prms.queue.nId, sOptions });
|
||||||
|
} catch (e) {
|
||||||
|
await logger.warn(`Не удалось сохранить параметры отправки сообщения: ${makeErrorText(e)}`, {
|
||||||
|
nQueueId: prms.queue.nId
|
||||||
|
});
|
||||||
|
}
|
||||||
|
//Ждем ответ от удалённого сервера
|
||||||
|
options.resolveWithFullResponse = true;
|
||||||
|
let serverResp = await rqp(options);
|
||||||
|
//Сохраняем полученный ответ
|
||||||
|
prms.queue.blResp = Buffer.from(serverResp.body || "");
|
||||||
|
await dbConn.setQueueResp({
|
||||||
|
nQueueId: prms.queue.nId,
|
||||||
|
blResp: prms.queue.blResp,
|
||||||
|
nIsOriginal: NIS_ORIGINAL_YES
|
||||||
|
});
|
||||||
|
//Сохраняем заголовки ответа и HTTP-статус
|
||||||
|
optionsResp.headers = _.cloneDeep(serverResp.headers);
|
||||||
|
optionsResp.statusCode = serverResp.statusCode;
|
||||||
|
try {
|
||||||
|
let sOptionsResp = buildOptionsXML({ options: optionsResp });
|
||||||
|
await dbConn.setQueueOptionsResp({ nQueueId: prms.queue.nId, sOptionsResp });
|
||||||
|
} catch (e) {
|
||||||
|
await logger.warn(`Не удалось сохранить заголовок ответа удалённого сервера: ${makeErrorText(e)}`, {
|
||||||
|
nQueueId: prms.queue.nId
|
||||||
|
});
|
||||||
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
await logger.warn(
|
//Прекращаем исполнение если были ошибки
|
||||||
`Не удалось сохранить заголовок ответа удалённого сервера: ${makeErrorText(e)}`,
|
let sError = "Неожиданная ошибка удалённого сервиса";
|
||||||
{ nQueueId: prms.queue.nId }
|
if (e.error) {
|
||||||
);
|
let sSubError = e.error.code || e.error;
|
||||||
|
sError = `Ошибка передачи данных: ${sSubError}`;
|
||||||
|
}
|
||||||
|
if (e.response) sError = `${e.response.statusCode} - ${e.response.statusMessage}`;
|
||||||
|
throw new ServerError(SERR_WEB_SERVER, sError);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
//Выполняем обработчик "После" (если он есть)
|
||||||
//Прекращаем исполнение если были ошибки
|
if (prms.function.sAppSrvAfter) {
|
||||||
let sError = "Неожиданная ошибка удалённого сервиса";
|
const fnAfter = getAppSrvFunction(prms.function.sAppSrvAfter);
|
||||||
if (e.error) {
|
let resAfter = null;
|
||||||
let sSubError = e.error.code || e.error;
|
try {
|
||||||
sError = `Ошибка передачи данных: ${sSubError}`;
|
let resAfterPrms = _.cloneDeep(prms);
|
||||||
}
|
resAfterPrms.options = _.cloneDeep(options);
|
||||||
if (e.response) sError = `${e.response.statusCode} - ${e.response.statusMessage}`;
|
resAfterPrms.optionsResp = _.cloneDeep(optionsResp);
|
||||||
throw new ServerError(SERR_WEB_SERVER, sError);
|
resAfter = await fnAfter(resAfterPrms);
|
||||||
}
|
} catch (e) {
|
||||||
//Выполняем обработчик "После" (если он есть)
|
throw new ServerError(SERR_APP_SERVER_AFTER, e.message);
|
||||||
if (prms.function.sAppSrvAfter) {
|
}
|
||||||
const fnAfter = getAppSrvFunction(prms.function.sAppSrvAfter);
|
//Проверяем структуру ответа функции постобработки
|
||||||
let resAfter = null;
|
if (resAfter) {
|
||||||
try {
|
let sCheckResult = validateObject(
|
||||||
let resAfterPrms = _.cloneDeep(prms);
|
resAfter,
|
||||||
resAfterPrms.options = _.cloneDeep(options);
|
objOutQueueProcessorSchema.OutQueueProcessorFnAfter,
|
||||||
resAfterPrms.optionsResp = _.cloneDeep(optionsResp);
|
"Результат функции постобработки исходящего сообщения"
|
||||||
resAfter = await fnAfter(resAfterPrms);
|
);
|
||||||
} catch (e) {
|
//Если структура ответа в норме
|
||||||
throw new ServerError(SERR_APP_SERVER_AFTER, e.message);
|
if (!sCheckResult) {
|
||||||
}
|
//Применим ответ "После" - обработанный ответ удаленного сервиса
|
||||||
//Проверяем структуру ответа функции постобработки
|
if (!_.isUndefined(resAfter.blResp)) {
|
||||||
if (resAfter) {
|
prms.queue.blResp = resAfter.blResp;
|
||||||
let sCheckResult = validateObject(
|
await dbConn.setQueueResp({
|
||||||
resAfter,
|
nQueueId: prms.queue.nId,
|
||||||
objOutQueueProcessorSchema.OutQueueProcessorFnAfter,
|
blResp: prms.queue.blResp,
|
||||||
"Результат функции постобработки исходящего сообщения"
|
nIsOriginal: NIS_ORIGINAL_NO
|
||||||
);
|
|
||||||
//Если структура ответа в норме
|
|
||||||
if (!sCheckResult) {
|
|
||||||
//Применим ответ "После" - обработанный ответ удаленного сервиса
|
|
||||||
if (!_.isUndefined(resAfter.blResp)) {
|
|
||||||
prms.queue.blResp = resAfter.blResp;
|
|
||||||
await dbConn.setQueueResp({
|
|
||||||
nQueueId: prms.queue.nId,
|
|
||||||
blResp: prms.queue.blResp,
|
|
||||||
nIsOriginal: NIS_ORIGINAL_NO
|
|
||||||
});
|
|
||||||
}
|
|
||||||
//Применим ответ "После" - флаг утентификации сервиса
|
|
||||||
if (!_.isUndefined(resAfter.bUnAuth))
|
|
||||||
if (resAfter.bUnAuth === true) throw new ServerError(SERR_UNAUTH, "Нет аутентификации");
|
|
||||||
//Применим ответ "После" - контекст работы сервиса
|
|
||||||
if (!_.isUndefined(resAfter.sCtx))
|
|
||||||
if (prms.function.nFnType == objServiceFnSchema.NFN_TYPE_LOGIN) {
|
|
||||||
prms.service.sCtx = resAfter.sCtx;
|
|
||||||
prms.service.dCtxExp = resAfter.dCtxExp;
|
|
||||||
await dbConn.setServiceContext({
|
|
||||||
nServiceId: prms.service.nId,
|
|
||||||
sCtx: prms.service.sCtx,
|
|
||||||
dCtxExp: prms.service.dCtxExp
|
|
||||||
});
|
});
|
||||||
bCtxIsSet = true;
|
|
||||||
}
|
}
|
||||||
} else {
|
//Применим ответ "После" - флаг утентификации сервиса
|
||||||
//Или расскажем об ошибке в структуре ответа
|
if (!_.isUndefined(resAfter.bUnAuth))
|
||||||
throw new ServerError(SERR_OBJECT_BAD_INTERFACE, sCheckResult);
|
if (resAfter.bUnAuth === true) throw new ServerError(SERR_UNAUTH, "Нет аутентификации");
|
||||||
|
//Применим ответ "После" - контекст работы сервиса
|
||||||
|
if (!_.isUndefined(resAfter.sCtx))
|
||||||
|
if (prms.function.nFnType == objServiceFnSchema.NFN_TYPE_LOGIN) {
|
||||||
|
prms.service.sCtx = resAfter.sCtx;
|
||||||
|
prms.service.dCtxExp = resAfter.dCtxExp;
|
||||||
|
await dbConn.setServiceContext({
|
||||||
|
nServiceId: prms.service.nId,
|
||||||
|
sCtx: prms.service.sCtx,
|
||||||
|
dCtxExp: prms.service.dCtxExp
|
||||||
|
});
|
||||||
|
bCtxIsSet = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//Или расскажем об ошибке в структуре ответа
|
||||||
|
throw new ServerError(SERR_OBJECT_BAD_INTERFACE, sCheckResult);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
//Если это функция начала сеанса, и нет обработчика на стороне БД и контекст не был установлен до сих пор - то положим в него то, что нам ответил сервер
|
||||||
//Если это функция начала сеанса, и нет обработчика на стороне БД и контекст не был установлен до сих пор - то положим в него то, что нам ответил сервер
|
if (prms.function.nFnType == objServiceFnSchema.NFN_TYPE_LOGIN && !prms.function.sPrcResp && !bCtxIsSet) {
|
||||||
if (
|
await dbConn.setServiceContext({ nServiceId: prms.service.nId, sCtx: serverResp });
|
||||||
prms.function.nFnType == objServiceFnSchema.NFN_TYPE_LOGIN &&
|
}
|
||||||
!prms.function.sPrcResp &&
|
//Если это функция окончания сеанса, и нет обработчика на стороне БД - то сбросим контекст здесь
|
||||||
!bCtxIsSet
|
if (prms.function.nFnType == objServiceFnSchema.NFN_TYPE_LOGOUT && !prms.function.sPrcResp) {
|
||||||
) {
|
await dbConn.clearServiceContext({ nServiceId: prms.service.nId });
|
||||||
await dbConn.setServiceContext({ nServiceId: prms.service.nId, sCtx: serverResp });
|
}
|
||||||
}
|
|
||||||
//Если это функция окончания сеанса, и нет обработчика на стороне БД - то сбросим контекст здесь
|
|
||||||
if (prms.function.nFnType == objServiceFnSchema.NFN_TYPE_LOGOUT && !prms.function.sPrcResp) {
|
|
||||||
await dbConn.clearServiceContext({ nServiceId: prms.service.nId });
|
|
||||||
}
|
}
|
||||||
//Фиксируем успешное исполнение сервером приложений - в статусе сообщения
|
//Фиксируем успешное исполнение сервером приложений - в статусе сообщения
|
||||||
res = await dbConn.setQueueState({
|
res = await dbConn.setQueueState({
|
||||||
@ -383,10 +372,9 @@ const appProcess = async prms => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
//Фиксируем ошибку обработки сервером приложений - в протоколе работы сервиса
|
//Фиксируем ошибку обработки сервером приложений - в протоколе работы сервиса
|
||||||
await logger.error(
|
await logger.error(`Ошибка обработки исходящего сообщения ${prms.queue.nId} сервером приложений: ${makeErrorText(e)}`, {
|
||||||
`Ошибка обработки исходящего сообщения ${prms.queue.nId} сервером приложений: ${makeErrorText(e)}`,
|
nQueueId: prms.queue.nId
|
||||||
{ nQueueId: prms.queue.nId }
|
});
|
||||||
);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
//Фатальная ошибка обработки - некорректный объект параметров
|
//Фатальная ошибка обработки - некорректный объект параметров
|
||||||
@ -401,11 +389,7 @@ const dbProcess = async prms => {
|
|||||||
//Результат обработки - объект Queue (обработанное сообщение) или ServerError (ошибка обработки)
|
//Результат обработки - объект Queue (обработанное сообщение) или ServerError (ошибка обработки)
|
||||||
let res = null;
|
let res = null;
|
||||||
//Проверяем структуру переданного объекта для старта
|
//Проверяем структуру переданного объекта для старта
|
||||||
let sCheckResult = validateObject(
|
let sCheckResult = validateObject(prms, prmsOutQueueProcessorSchema.dbProcess, "Параметры функции запуска обработки ообщения сервером БД");
|
||||||
prms,
|
|
||||||
prmsOutQueueProcessorSchema.dbProcess,
|
|
||||||
"Параметры функции запуска обработки ообщения сервером БД"
|
|
||||||
);
|
|
||||||
//Если структура объекта в норме
|
//Если структура объекта в норме
|
||||||
if (!sCheckResult) {
|
if (!sCheckResult) {
|
||||||
//Обрабатываем
|
//Обрабатываем
|
||||||
@ -417,9 +401,9 @@ const dbProcess = async prms => {
|
|||||||
});
|
});
|
||||||
//Фиксируем начало исполнения сервером БД - в протоколе работы сервиса
|
//Фиксируем начало исполнения сервером БД - в протоколе работы сервиса
|
||||||
await logger.info(
|
await logger.info(
|
||||||
`Обрабатываю исходящее сообщение сервером БД: ${prms.queue.nId}, ${prms.queue.sInDate}, ${
|
`Обрабатываю исходящее сообщение сервером БД: ${prms.queue.nId}, ${prms.queue.sInDate}, ${prms.queue.sServiceFnCode}, ${
|
||||||
prms.queue.sServiceFnCode
|
prms.queue.sExecState
|
||||||
}, ${prms.queue.sExecState}, попытка исполнения - ${prms.queue.nExecCnt + 1}`,
|
}, попытка исполнения - ${prms.queue.nExecCnt + 1}`,
|
||||||
{ nQueueId: prms.queue.nId }
|
{ nQueueId: prms.queue.nId }
|
||||||
);
|
);
|
||||||
//Если обработчик со стороны БД указан
|
//Если обработчик со стороны БД указан
|
||||||
@ -427,11 +411,9 @@ const dbProcess = async prms => {
|
|||||||
//Вызываем его
|
//Вызываем его
|
||||||
let prcRes = await dbConn.execQueueDBPrc({ nQueueId: prms.queue.nId });
|
let prcRes = await dbConn.execQueueDBPrc({ nQueueId: prms.queue.nId });
|
||||||
//Если результат - ошибка пробрасываем её
|
//Если результат - ошибка пробрасываем её
|
||||||
if (prcRes.sResult == objQueueSchema.SPRC_RESP_RESULT_ERR)
|
if (prcRes.sResult == objQueueSchema.SPRC_RESP_RESULT_ERR) throw new ServerError(SERR_DB_SERVER, prcRes.sMsg);
|
||||||
throw new ServerError(SERR_DB_SERVER, prcRes.sMsg);
|
|
||||||
//Если результат - ошибка аутентификации, то и её пробрасываем, но с правильным кодом
|
//Если результат - ошибка аутентификации, то и её пробрасываем, но с правильным кодом
|
||||||
if (prcRes.sResult == objQueueSchema.SPRC_RESP_RESULT_UNAUTH)
|
if (prcRes.sResult == objQueueSchema.SPRC_RESP_RESULT_UNAUTH) throw new ServerError(SERR_UNAUTH, prcRes.sMsg || "Нет аутентификации");
|
||||||
throw new ServerError(SERR_UNAUTH, prcRes.sMsg || "Нет аутентификации");
|
|
||||||
}
|
}
|
||||||
//Фиксируем успешное исполнение (полное - дальше обработки нет) - в статусе сообщения
|
//Фиксируем успешное исполнение (полное - дальше обработки нет) - в статусе сообщения
|
||||||
res = await dbConn.setQueueState({
|
res = await dbConn.setQueueState({
|
||||||
@ -466,10 +448,9 @@ const dbProcess = async prms => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
//Фиксируем ошибку обработки сервером БД - в протоколе работы сервиса
|
//Фиксируем ошибку обработки сервером БД - в протоколе работы сервиса
|
||||||
await logger.error(
|
await logger.error(`Ошибка обработки исходящего сообщения ${prms.queue.nId} сервером БД: ${makeErrorText(e)}`, {
|
||||||
`Ошибка обработки исходящего сообщения ${prms.queue.nId} сервером БД: ${makeErrorText(e)}`,
|
nQueueId: prms.queue.nId
|
||||||
{ nQueueId: prms.queue.nId }
|
});
|
||||||
);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
//Фатальная ошибка обработки - некорректный объект параметров
|
//Фатальная ошибка обработки - некорректный объект параметров
|
||||||
@ -482,11 +463,7 @@ const dbProcess = async prms => {
|
|||||||
//Обработка задачи
|
//Обработка задачи
|
||||||
const processTask = async prms => {
|
const processTask = async prms => {
|
||||||
//Проверяем параметры
|
//Проверяем параметры
|
||||||
let sCheckResult = validateObject(
|
let sCheckResult = validateObject(prms, prmsOutQueueProcessorSchema.processTask, "Параметры функции обработки задачи");
|
||||||
prms,
|
|
||||||
prmsOutQueueProcessorSchema.processTask,
|
|
||||||
"Параметры функции обработки задачи"
|
|
||||||
);
|
|
||||||
//Если параметры в норме
|
//Если параметры в норме
|
||||||
if (!sCheckResult) {
|
if (!sCheckResult) {
|
||||||
let q = null;
|
let q = null;
|
||||||
@ -629,11 +606,7 @@ process.on("uncaughtException", e => {
|
|||||||
//Приём сообщений
|
//Приём сообщений
|
||||||
process.on("message", task => {
|
process.on("message", task => {
|
||||||
//Проверяем структуру переданного сообщения
|
//Проверяем структуру переданного сообщения
|
||||||
let sCheckResult = validateObject(
|
let sCheckResult = validateObject(task, objOutQueueProcessorSchema.OutQueueProcessorTask, "Задача обработчика очереди исходящих сообщений");
|
||||||
task,
|
|
||||||
objOutQueueProcessorSchema.OutQueueProcessorTask,
|
|
||||||
"Задача обработчика очереди исходящих сообщений"
|
|
||||||
);
|
|
||||||
//Если структура объекта в норме
|
//Если структура объекта в норме
|
||||||
if (!sCheckResult) {
|
if (!sCheckResult) {
|
||||||
//Запускаем обработку
|
//Запускаем обработку
|
||||||
|
@ -197,7 +197,9 @@ const sendMail = prms => {
|
|||||||
from: prms.mail.sFrom,
|
from: prms.mail.sFrom,
|
||||||
to: prms.sTo,
|
to: prms.sTo,
|
||||||
subject: prms.sSubject,
|
subject: prms.sSubject,
|
||||||
text: prms.sMessage
|
text: prms.sMessage,
|
||||||
|
html: prms.sHTML,
|
||||||
|
attachments: prms.attachments
|
||||||
};
|
};
|
||||||
//Отправляем сообщение
|
//Отправляем сообщение
|
||||||
transporter.sendMail(mailOptions, (error, info) => {
|
transporter.sendMail(mailOptions, (error, info) => {
|
||||||
|
@ -145,6 +145,16 @@ exports.OutQueueProcessorFnBefore = new Schema({
|
|||||||
type: path => `Дата истечения контекста (${path}) имеет некорректный тип данных (ожидалось - Date)`,
|
type: path => `Дата истечения контекста (${path}) имеет некорректный тип данных (ожидалось - Date)`,
|
||||||
required: path => `Не указана дата истечения контекста (${path})`
|
required: path => `Не указана дата истечения контекста (${path})`
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
//Флаг прекращения дальнейшей обработки сообщения
|
||||||
|
bStopPropagation: {
|
||||||
|
type: Boolean,
|
||||||
|
required: false,
|
||||||
|
message: {
|
||||||
|
type: path =>
|
||||||
|
`Флаг прекращения дальнейшей обработки сообщения (${path}) имеет некорректный тип данных (ожидалось - Boolean)`,
|
||||||
|
required: path => `Не указан флаг прекращения дальнейшей обработки сообщения (${path})`
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -40,8 +40,7 @@ exports.sendMail = new Schema({
|
|||||||
required: true,
|
required: true,
|
||||||
use: { validateTo },
|
use: { validateTo },
|
||||||
message: {
|
message: {
|
||||||
type: path =>
|
type: path => `Список адресов E-Mail для отправки уведомления (${path}) имеет некорректный тип данных (ожидалось - String)`,
|
||||||
`Список адресов E-Mail для отправки уведомления (${path}) имеет некорректный тип данных (ожидалось - String)`,
|
|
||||||
required: path => `Не указан cписок адресов E-Mail для отправки уведомления (${path})`,
|
required: path => `Не указан cписок адресов E-Mail для отправки уведомления (${path})`,
|
||||||
validateTo: path =>
|
validateTo: path =>
|
||||||
`Неверный формат списка адресов E-Mail для отправки уведомления (${path}), для указания нескольких адресов следует использовать запятую в качестве разделителя (без пробелов)`
|
`Неверный формат списка адресов E-Mail для отправки уведомления (${path}), для указания нескольких адресов следует использовать запятую в качестве разделителя (без пробелов)`
|
||||||
@ -50,7 +49,7 @@ exports.sendMail = new Schema({
|
|||||||
//Заголовок сообщения
|
//Заголовок сообщения
|
||||||
sSubject: {
|
sSubject: {
|
||||||
type: String,
|
type: String,
|
||||||
required: true,
|
required: false,
|
||||||
message: {
|
message: {
|
||||||
type: path => `Заголовок сообщения (${path}) имеет некорректный тип данных (ожидалось - String)`,
|
type: path => `Заголовок сообщения (${path}) имеет некорректный тип данных (ожидалось - String)`,
|
||||||
required: path => `Не указан заголовок сообщения (${path})`
|
required: path => `Не указан заголовок сообщения (${path})`
|
||||||
@ -59,11 +58,29 @@ exports.sendMail = new Schema({
|
|||||||
//Текст уведомления
|
//Текст уведомления
|
||||||
sMessage: {
|
sMessage: {
|
||||||
type: String,
|
type: String,
|
||||||
required: true,
|
required: false,
|
||||||
message: {
|
message: {
|
||||||
type: path => `Текст уведомления (${path}) имеет некорректный тип данных (ожидалось - String)`,
|
type: path => `Текст уведомления (${path}) имеет некорректный тип данных (ожидалось - String)`,
|
||||||
required: path => `Не указан текст уведомления (${path})`
|
required: path => `Не указан текст уведомления (${path})`
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
//HTML текст сообщения
|
||||||
|
sHTML: {
|
||||||
|
type: String,
|
||||||
|
required: false,
|
||||||
|
message: {
|
||||||
|
type: path => `HTML текст сообщения (${path}) имеет некорректный тип данных (ожидалось - String)`,
|
||||||
|
required: path => `Не указан HTML текст сообщения (${path})`
|
||||||
|
}
|
||||||
|
},
|
||||||
|
//Вложения сообщения
|
||||||
|
attachments: {
|
||||||
|
type: Array,
|
||||||
|
required: false,
|
||||||
|
message: {
|
||||||
|
type: path => `Список вложений сообщения (${path}) имеет некорректный тип данных (ожидалось - Array)`,
|
||||||
|
required: path => `Не указан список вложений сообщения (${path})`
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -141,8 +158,7 @@ exports.buildOptionsXML = new Schema({
|
|||||||
type: Object,
|
type: Object,
|
||||||
required: true,
|
required: true,
|
||||||
message: {
|
message: {
|
||||||
type: path =>
|
type: path => `Объект параметров сообщения/ответа (${path}) имеет некорректный тип данных (ожидалось - Object)`,
|
||||||
`Объект параметров сообщения/ответа (${path}) имеет некорректный тип данных (ожидалось - Object)`,
|
|
||||||
required: path => `Не указан объект параметров сообщения/ответа (${path})`
|
required: path => `Не указан объект параметров сообщения/ответа (${path})`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
175
modules/send_mail.js
Normal file
175
modules/send_mail.js
Normal file
@ -0,0 +1,175 @@
|
|||||||
|
/*
|
||||||
|
Сервис интеграции ПП Парус 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)}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//Если имеется рег. номер записи очереди отправки E-mail - обновляем информацию о текущем сообщении
|
||||||
|
if (parseRes.mail.nExsextmailId) {
|
||||||
|
if (res === "OK") {
|
||||||
|
await setSendMsg({ connection: prms.dbConn.connection, nRn: parseRes.mail.nExsextmailId, sErrMsg: "", nStatus: NSTATUS_DONE });
|
||||||
|
} else {
|
||||||
|
await setSendMsg({ connection: prms.dbConn.connection, nRn: parseRes.mail.nExsextmailId, sErrMsg: res, nStatus: NSTATUS_ERR });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//Возвращаем результат и флаг того, что дальше отрабатывать это сообщение не надо
|
||||||
|
return {
|
||||||
|
blMsg: Buffer.from(JSON.stringify({ message: parseRes, state: res })),
|
||||||
|
bStopPropagation: true
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
//-----------------
|
||||||
|
// Интерфейс модуля
|
||||||
|
//-----------------
|
||||||
|
|
||||||
|
exports.before = before;
|
Loading…
x
Reference in New Issue
Block a user