i am currently trying to send attachments via nodemailer for this i have created an extra project for the mailer itself and a few other things which i have called my_nodetools! But when i use the mailer in another one, i can only send mails without attachments as soon as i want to send mails with attachments, i get the message that it supposedly worked but the mail doesn't end up in my inbox!
INDEX MY_NODETOOLS
const Logger = require('./Logger');
const Debugger = require('./Debugger');
const FileSystemManager = require('./FileSystem');
const My_Mailer = require('./My_Mailer');
module.exports = {
My_Mailer: My_Mailer ,
Debugger: Debugger,
FileSystemManager: FileSystemManager,
Logger: Logger,
}
Mailer Class:
const nodemailer = require('nodemailer');
const pug = require('pug');
const path = require('path');
/**
* Class representing an email sender using Nodemailer and Pug templates.
*/
class My_Mailer {
/**
* Create a mailer instance.
* @param {Object} options - SMTP configuration for Nodemailer.
*/
constructor(options) {
/**
* Nodemailer transporter instance.
* @type {Object}
* @private
*/
this.transporter = nodemailer.createTransport(options);
}
/**
* Compile a Pug file into a render function.
* @param {string} file - Path to the Pug file.
* @returns {Function} - Compiled Pug template function.
*/
compileFile(file) {
return pug.compileFile(file);
}
/**
* Send an email using the configured transporter.
* @param {Object} options - Options for sending the email.
* @param {string} options.from - Sender's email address.
* @param {string} options.to - Recipient's email address.
* @param {string} options.subject - Email subject.
* @param {string} [options.cc] - CC email address (optional).
* @param {string} [options.text] - Plain text version of the email.
* @param {string} [options.html] - HTML version of the email.
* @param {Array} [options.attachments] - An array of attachments.
* @returns {Promise} - A promise that resolves when the email is sent.
*/
sendMail(options) {
const thisInstance = this;
return new Promise(function (resolve, reject) {
const mailOptions = {
from: options.from,
to: options.to,
subject: options.subject,
};
if (options.cc) {
mailOptions.cc = options.cc;
}
if (options.text) {
mailOptions.text = options.text;
}
if (options.html) {
mailOptions.html = options.html;
}
console.log('wtf')
if (options.attachments && options.attachments.length > 0) {
mailOptions.attachments = options.attachments.map(function (attachment) {
return {
filename: attachment.filename,
path: path.resolve(attachment.path), // Resolve absolute path
}
});
}
console.log('??? ... ', mailOptions.attachments);
/**
* OUTPUT RETURNS correct attachments
* wtf
??? ... [
{
filename: 'somePdf1.pdf',
path: '/home/admin/desk/repos/other_project/_temp/somePdf1.pdf'
},
{
filename: 'somePdf2.pdf',
path: '/home/admin/desk/repos/other_project/_temp/somePdf2.pdf'
},
{
filename: 'somePdf3.pdf',
path: '/home/admin/desk/repos/other_project/_temp/somePdf3.pdf'
},
{
filename: 'somePdf4.pdf',
path: '/home/admin/desk/repos/other_project/_temp/somePdf4.pdf'
}
]
*/
/**
thisInstance.transporter.sendMail(mailOptions) Logs looks correctly:
Message sent: <**************@somemail.de>
{
accepted: [ '*****@somemail.de' ],
rejected: [],
ehlo: [
'SIZE 157286400',
'PIPELINING',
'DSN',
'ENHANCEDSTATUSCODES',
'AUTH LOGIN XOAUTH2',
'8BITMIME',
'BINARYMIME',
'CHUNKING',
'SMTPUTF8'
],
envelopeTime: 129,
messageTime: 4081,
messageSize: 15747178,
response: '250 2.0.0 OK <*****@somemail.de> [Hostname=DB6PR07MB3366.eurprd07.prod.outlook.com]',
envelope: { from: '[email protected]', to: [ '[email protected]' ] },
messageId: '<**************@somemail.de>'
}
2024-03-07T07:35:44.966Z|LOG| Message sent: <**************@somemail.de>
*/
thisInstance.transporter.sendMail(mailOptions)
.then(function (info) {
console.log('Message sent: %s', info.messageId);
console.log(info);
resolve(info);
})
.catch(function (err) {
console.error('Error sending email:', err);
reject(err);
});
});
}
}
module.exports = My_Mailer;
in my other project i tried this
const path = require('path');
const sendMail = require('./helper/sendMail');
const Tools = require('../my_nodetools');
const Logger = new Tools.Logger();
async function main() {
const temp_dir = path.join(__dirname, '_temp');
const mailTemplatesPath = path.join(__dirname, 'mailTemplates');
const someMailTemplate = path.join(mailTemplatesPath, '****.pug');
const fsm = new Tools.FileSystemManager;
const dirFiles = await fsm.loadedModules.readDir(temp_dir);
// console.log('dirFiles', dirFiles);
const filesAttachments = dirFiles.map(function (file) {
return {
'filename': file,
'path': path.join(temp_dir, file)
}
});
const resultsData = filesAttachments.map(function (entry) {
return entry.filename;
});
const templateDataResults = {
results: resultsData,
product: 'res'
}
const mailOptions = {
'subject': 'MY PDF Applications',
};
await sendMail({
tools: Tools,
mailOptions: mailOptions,
templateFile: someMailTemplate,
templateFileData: templateDataResults,
attachments: filesAttachments,
})
}
main();
send Mail Function:
const path = require('path');
const util = require('util');
const dotenv = require('dotenv');
/**
* Send an email using Nodemailer.
*
* @param {Object} options - Email sending options.
* @param {Object} options.tools - Custom tools object containing Logger and My_Mailer.
* @param {string} options.templateFile - Path to the email template file.
* @param {Object} [options.templateFileData={}] - Data to be used in the email template.
* @param {Array} [options.attachments=[]] - Array of attachments for the email.
* @param {Object} [options.mailOptions={}] - Custom Nodemailer mail options.
* @param {Object} [options.logger] - Custom logger, defaults to tools.Logger if not provided.
* @returns {Promise<boolean|Object>} - A promise resolving to true if the email is sent successfully,
* false if there is an issue, or an object with an error property.
*/
module.exports = async function sendMail(options) {
try {
const envFilePath = path.join(__dirname, '..', '.env');
dotenv.config({ path: envFilePath });
const {
tools,
templateFile,
templateFileData = {},
} = options;
const privateMail = false;
const attachments = options.attachments || [];
const customMailOptions = options.mailOptions || {};
customMailOptions.from = options.mailOptions.from || process.env.SMTP_FROM_EMAIL;
customMailOptions.to = options.mailOptions.to || process.env.SMTP_TO_EMAIL_DEV;
if (privateMail) {
customMailOptions.to = '*****@googlemail.com';
}
//console.log(attachments)
/** @type {Logger} */
const logger = options.logger || new tools.Logger();
const smtpConfig = {
host: 'smtp.office365.com',
port: 587,
secure: false, // use TLS
auth: {
user: process.env.SMTP_USER,
pass: process.env.SMTP_PASSWORD,
},
};
const myMailer = new tools.My_Mailer(smtpConfig);
const template = myMailer.compileFile(templateFile);
const htmlContent = template({
data: templateFileData,
// Add other variables as needed
});
/**
* Nodemailer mail options.
* @type {Object}
* @property {string} html - HTML content of the email.
* @property {Array} [attachments] - Array of attachments for the email.
*/
const mailOptions = {
...customMailOptions,
html: htmlContent,
};
/* TODO NOT WORKING */
/**
* if(attachments && attachments.length > 0) {
mailOptions.attachments = attachments;
}
*/
mailOptions.attachments = attachments;
logger.log('Ready to send mail!');
const info = await myMailer.sendMail(mailOptions);
if (info.messageId) {
logger.log(`Message sent: ${info.messageId}`);
return true;
} else {
logger.log('Message not sent');
return false;
}
} catch (error) {
/**
* Error object.
* @type {Object}
* @property {string} error - Formatted error message.
*/
const formattedError = util.inspect(error);
options.logger?.error(formattedError);
return { error: formattedError };
}
};