feat: create duplicate template functionality
feat: add support of csv and xlsx for bulk contacts import
feat: add info text for forms and dashboard button
feat: implement functionality to delete a PDF page while editing the document
feat: show completed documents in which signers included but not owner in completed reports
feat: add delete folder button in opensign drive
feat: introduce Bcc email support for sending completed documents
feat: allow merging multiple pdf while drafting document and template
feat: add 'My Initials' tab for auto-signing in request-sign flow
feat: add support for redirect URL to navigate after document completion
feat: introduce privacy policy and digital signature terms before signing documents.
feat: add feature to allow adding new pages to existing document
feat: add save signature, initials, stamp functionality in sign pad for logged in user
feat: add preferences menu
feat: add save custom email template, notifyonsignature, set timezone, allow signature types in preferences
feat: secure local url
feat: implement Italian language translation
feat: implement German language translation
feat: update menu name from report to documents and shift contactbook in main menu
feat: provide edit contact functionality

fix: unable to delete folder when all its documents are deleted
fix: fields.push is not function
fix: document loading issue in opensign drive
fix: adjust the guest signature flow to display the document in full screen, eliminating any blank space which is displayed below the place holder in mobile view
fix: resolve issue of instance of pdfdict or pdfstream but got undefined

build(deps): update dependencies

refactor: change note text from add contact form
This commit is contained in:
prafull-opensignlabs
2025-02-10 14:41:16 +00:00
parent b55aff20d3
commit e299891174
260 changed files with 22438 additions and 25112 deletions
@@ -1,11 +1,10 @@
import fs from 'node:fs';
import https from 'https';
import http from 'http';
import formData from 'form-data';
import Mailgun from 'mailgun.js';
import { smtpenable, smtpsecure, updateMailCount, useLocal } from '../../Utils.js';
import sendMailGmailProvider from './sendMailGmailProvider.js';
import { smtpenable, smtpsecure, updateMailCount } from '../../Utils.js';
import { createTransport } from 'nodemailer';
import axios from 'axios';
async function sendMailProvider(req, plan, monthchange) {
const mailgunApiKey = process.env.MAILGUN_API_KEY;
try {
@@ -36,18 +35,29 @@ async function sendMailProvider(req, plan, monthchange) {
const isSecure =
new URL(req.params.url)?.protocol === 'https:' &&
new URL(req.params.url)?.hostname !== 'localhost';
if (useLocal !== 'true' || isSecure) {
https.get(req.params.url, async function (response) {
response.pipe(Pdf);
response.on('end', () => resolve('success'));
});
if (isSecure) {
https
.get(req.params.url, async function (response) {
response.pipe(Pdf);
response.on('end', () => resolve('success'));
})
.on('error', e => {
console.error(`error: ${e.message}`);
resolve('error');
});
} else {
const path = new URL(req.params.url)?.pathname;
const localurl = 'http://localhost:8080' + path;
http.get(localurl, async function (response) {
response.pipe(Pdf);
response.on('end', () => resolve('success'));
});
const httpsAgent = new https.Agent({ rejectUnauthorized: false }); // Disable SSL validation
axios
.get(req.params.url, { responseType: 'stream', httpsAgent })
.then(response => {
response.data.pipe(Pdf);
Pdf.on('finish', () => resolve('success'));
Pdf.on('error', () => resolve('error'));
})
.catch(e => {
console.log('error', e.message);
resolve('error');
});
}
});
};
@@ -65,14 +75,15 @@ async function sendMailProvider(req, plan, monthchange) {
// `PdfBuffer` used to create buffer from pdf file
let PdfBuffer = await readTolocal();
const pdfName = req.params.pdfName && `${req.params.pdfName}.pdf`;
const filename = req.params.filename;
const file = {
filename: pdfName || 'exported.pdf',
filename: filename || pdfName || 'exported.pdf',
content: smtpenable ? PdfBuffer : undefined,
data: smtpenable ? undefined : PdfBuffer,
};
let attachment;
const certificatePath = './exports/certificate.pdf';
const certificatePath = req.params.certificatePath || `./exports/certificate.pdf`;
if (fs.existsSync(certificatePath)) {
try {
// `certificateBuffer` used to create buffer from pdf file
@@ -92,7 +103,7 @@ async function sendMailProvider(req, plan, monthchange) {
}
const from = req.params.from || '';
const mailsender = smtpenable ? process.env.SMTP_USER_EMAIL : process.env.MAILGUN_SENDER;
const replyto = req.params?.replyto || '';
const messageParams = {
from: from + ' <' + mailsender + '>',
to: req.params.recipient,
@@ -101,6 +112,8 @@ async function sendMailProvider(req, plan, monthchange) {
html: req.params.html || '',
attachments: smtpenable ? attachment : undefined,
attachment: smtpenable ? undefined : attachment,
bcc: req.params.bcc ? req.params.bcc : undefined,
replyTo: replyto ? replyto : undefined,
};
if (transporterSMTP) {
const res = await transporterSMTP.sendMail(messageParams);
@@ -150,13 +163,15 @@ async function sendMailProvider(req, plan, monthchange) {
} else {
const from = req.params.from || '';
const mailsender = smtpenable ? process.env.SMTP_USER_EMAIL : process.env.MAILGUN_SENDER;
const replyto = req.params?.replyto || '';
const messageParams = {
from: from + ' <' + mailsender + '>',
to: req.params.recipient,
subject: req.params.subject,
text: req.params.text || 'mail',
html: req.params.html || '',
bcc: req.params.bcc ? req.params.bcc : undefined,
replyTo: replyto ? replyto : undefined,
};
if (transporterSMTP) {
@@ -190,189 +205,10 @@ async function sendMailProvider(req, plan, monthchange) {
}
}
}
async function sendcustomsmtp(extRes, req) {
const smtpsecure = extRes.SmtpConfig.port !== '465' ? false : true;
const transporterSMTP = createTransport({
host: extRes.SmtpConfig.host,
port: extRes.SmtpConfig.port,
secure: smtpsecure,
auth: { user: extRes.SmtpConfig.username, pass: extRes.SmtpConfig.password },
});
if (req.params.url) {
let Pdf = fs.createWriteStream('test.pdf');
const writeToLocalDisk = () => {
return new Promise((resolve, reject) => {
const isSecure =
new URL(req.params.url)?.protocol === 'https:' &&
new URL(req.params.url)?.hostname !== 'localhost';
if (useLocal !== 'true' || isSecure) {
https.get(req.params.url, async function (response) {
response.pipe(Pdf);
response.on('end', () => resolve('success'));
});
} else {
const path = new URL(req.params.url)?.pathname;
const localurl = 'http://localhost:8080' + path;
http.get(localurl, async function (response) {
response.pipe(Pdf);
response.on('end', () => resolve('success'));
});
}
});
};
// `writeToLocalDisk` is used to create pdf file from doc url
const ress = await writeToLocalDisk();
if (ress) {
function readTolocal() {
return new Promise((resolve, reject) => {
setTimeout(() => {
let PdfBuffer = fs.readFileSync(Pdf.path);
resolve(PdfBuffer);
}, 100);
});
}
// `PdfBuffer` used to create buffer from pdf file
let PdfBuffer = await readTolocal();
const pdfName = req.params.pdfName ? `${req.params.pdfName}.pdf` : 'exported.pdf';
const file = { filename: pdfName, content: PdfBuffer };
let attachment;
const certificatePath = './exports/certificate.pdf';
if (fs.existsSync(certificatePath)) {
try {
// `certificateBuffer` used to create buffer from pdf file
const certificateBuffer = fs.readFileSync(certificatePath);
const certificate = { filename: 'certificate.pdf', content: certificateBuffer };
attachment = [file, certificate];
} catch (err) {
attachment = [file];
console.log('Err in read certificate sendmailv3', err);
}
} else {
attachment = [file];
}
const from = req.params.from || '';
const mailsender = extRes.SmtpConfig.username;
const messageParams = {
from: from + ' <' + mailsender + '>',
to: req.params.recipient,
subject: req.params.subject,
text: req.params.text || 'mail',
html: req.params.html || '',
attachments: attachment,
};
const res = await transporterSMTP.sendMail(messageParams);
console.log('custom smtp transporter res: ', res?.response);
if (!res.err) {
if (req.params?.extUserId) {
await updateMailCount(req.params.extUserId); //, plan, monthchange
}
if (fs.existsSync(certificatePath)) {
try {
fs.unlinkSync(certificatePath);
} catch (err) {
console.log('Err in unlink certificate sendmailv3');
}
}
return { status: 'success', code: 200 };
}
}
} else {
const from = req.params.from || '';
const mailsender = extRes.SmtpConfig.username;
const messageParams = {
from: from + ' <' + mailsender + '>',
to: req.params.recipient,
subject: req.params.subject,
text: req.params.text || 'mail',
html: req.params.html || '',
};
const res = await transporterSMTP.sendMail(messageParams);
console.log('custom smtp transporter res: ', res?.response);
if (!res.err) {
if (req.params?.extUserId) {
await updateMailCount(req.params.extUserId); //, plan, monthchange
}
return { status: 'success', code: 200 };
}
}
}
async function sendmailv3(req) {
const mailProvider = req.params.mailProvider || 'default';
if (mailProvider) {
try {
const Plan = req.params.plan;
const extUserId = req.params.extUserId || '';
const pdfName = req.params.pdfName || '';
const template = {
sender: req.params.from || '',
receiver: req.params.recipient,
subject: req.params.subject,
html: req.params.html || '',
url: req.params.url ? req.params.url : '',
pdfName: pdfName,
};
const extUserQuery = new Parse.Query('contracts_Users');
const extRes = await extUserQuery.get(extUserId, { useMasterKey: true });
if (extRes) {
const _extRes = JSON.parse(JSON.stringify(extRes));
if (
_extRes.active_mail_adapter === 'google' &&
_extRes.google_refresh_token &&
mailProvider === 'google'
) {
const res = await sendMailGmailProvider(_extRes, template);
if (res.code === 200) {
await updateMailCount(req.params.extUserId);
return { status: 'success' };
} else {
return { status: 'error' };
}
} else if (_extRes.active_mail_adapter === 'smtp' && mailProvider === 'smtp') {
const res = await sendcustomsmtp(_extRes, req);
if (res.code === 200) {
await updateMailCount(req.params.extUserId);
return { status: 'success' };
} else {
return { status: 'error' };
}
} else {
if (Plan && Plan === 'freeplan') {
let MonthlyFreeEmails = _extRes?.MonthlyFreeEmails || 0;
if (_extRes?.LastEmailCountReset?.iso) {
const lastDate = new Date(_extRes?.LastEmailCountReset?.iso);
const newDate = new Date();
const isMonthChange = newDate.getMonth() > lastDate.getMonth();
if (isMonthChange) {
const nonCustomMail = await sendMailProvider(req, Plan, true);
return nonCustomMail;
} else {
if (MonthlyFreeEmails >= 15) {
return { status: 'quota-reached' };
} else {
const nonCustomMail = await sendMailProvider(req, Plan);
return nonCustomMail;
}
}
} else {
const nonCustomMail = await sendMailProvider(req, Plan);
return nonCustomMail;
}
} else {
const nonCustomMail = await sendMailProvider(req, '');
return nonCustomMail;
}
}
}
} catch (err) {
console.log('err in send custom mail', err);
return { status: 'error' };
}
} else {
const nonCustomMail = await sendMailProvider(req);
return nonCustomMail;
}
}
export default sendmailv3;