ToolJet/plugins/packages/smtp/lib/index.ts
Midhun G S 78b140ba22
fix: update SMTP plugin to support new nodemailer version and improve type definitions (#15592)
* fix: automated security fixes for frontend dependencies

* chore: update jspdf and related dependencies; fix autoTable reference in generate-file.js

* chore: upgrade jspdf-autotable to version 5.0.7 and adjust related code references

* fix: update SMTP plugin to support new nodemailer version and improve type definitions

- Updated nodemailer dependency from version 6.9.1 to 8.0.2.
- Enhanced type definitions for attachments in QueryOptions.
- Specified Transporter type for nodemailer connections.
- Improved attachment handling by defining a more specific type for filesData function.

* chore: update nodemailer and its types, adjust AppHistoryModule providers and controllers based on import context

* Implement feature X to enhance user experience and fix bug Y in module Z

* chore: update nodemailer to version 8.0.3 and remove @types/nodemailer from dependencies

* chore: update version to 3.20.125-lts across all components

---------

Co-authored-by: adishM98 <adishM98@users.noreply.github.com>
Co-authored-by: johnsoncherian <johnsonc.dev@gmail.com>
2026-03-18 22:20:22 +05:30

82 lines
2.4 KiB
TypeScript

import { QueryError, QueryResult, QueryService, ConnectionTestResult } from '@tooljet-plugins/common';
import { SourceOptions, QueryOptions } from './types';
import nodemailer, { Transporter } from 'nodemailer';
import type { Attachment } from 'nodemailer/lib/mailer';
export default class Smtp implements QueryService {
async run(sourceOptions: SourceOptions, queryOptions: QueryOptions, dataSourceId: string): Promise<QueryResult> {
const nodemailerTransport: Transporter = await this.getConnection(sourceOptions);
const { from, to, cc, bcc, from_name, subject, textContent, htmlContent } = queryOptions;
const attachments: { name: string; dataURL: string }[] | undefined =
queryOptions['attachment_array'] && typeof queryOptions['attachment_array'] === 'string'
? JSON.parse(queryOptions['attachment_array'])
: queryOptions['attachment_array'];
const filesData = (array: { name: string; dataURL: string }[]): Attachment[] => {
const newFiles = array.map((x) => {
return { filename: x.name, content: Buffer.from(x.dataURL, 'base64') };
});
return newFiles;
};
const mailOptions = {
from: {
name: from_name,
address: from,
},
to,
cc,
bcc,
subject,
text: textContent,
html: htmlContent,
attachments: attachments && filesData(attachments),
};
try {
await nodemailerTransport.sendMail(mailOptions);
} catch (error) {
throw new QueryError('Query could not be completed', error.message, {});
}
return {
status: 'ok',
data: {},
};
}
async testConnection(sourceOptions: SourceOptions): Promise<ConnectionTestResult> {
const transporter: Transporter = await this.getConnection(sourceOptions);
if (!transporter) {
throw new Error('Invalid credentials');
}
try {
await transporter.verify();
} catch (err) {
throw new Error('Invalid credentials');
}
return {
status: 'ok',
};
}
async getConnection(sourceOptions: SourceOptions, _options?: object): Promise<Transporter> {
const { host, user, password } = sourceOptions;
const port = Number(sourceOptions.port);
const transport: Transporter = nodemailer.createTransport({
port,
host,
secure: port === 465,
auth: {
user,
pass: password,
},
});
return transport;
}
}