Strange nodemailer behaviour - cannot send attachments

22 Views Asked by At

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 };
    }
};
0

There are 0 best solutions below