Динамическая отправка нескольких вложений с помощью nodemailer - PullRequest
0 голосов
/ 14 мая 2019

Я пытаюсь использовать nodemailer для отправки писем в nodejs. В настоящее время я настроил рули в качестве шаблона и использую nodemailer-express-handlebars в качестве механизма шаблонов. Я хотел динамически читать файлы, которые доступны в моей папке загрузки, и отправлять их как вложения. Но я не мог понять, как. Пожалуйста, помогите мне

import { FeedbackFileEntity } from 
 '../../shared/entities/feedback.file.entity';
import hbs = require('nodemailer-express-handlebars');

import fs = require('fs');
import { getConnection } from 'typeorm';
import { DaoException } from '../../shared/exceptionHandler/dao.exception';
import { AppEnvServiceInstance } from 
     '../../shared/services/app.env.service';
import nodemailer = require('nodemailer');
import * as path from 'path';
import { promisify } from 'util';

// This is the router to upload files to database
// this works fine
export const feedbackFileUploadDataLayer = async(fileMeta, fileBody) => {
    console.log('file buffer is', fileMeta);
    console.log('file meta path', fileMeta.path);


    fileEntity.$fileName = fileBody.fileName;
    const manager =  await getConnection('postgresConnection').manager;
    console.log('before triggering save');
    return new Promise((resolve, reject) => {
        manager.save(fileEntity).then(data => {
            console.log('Saved the data successfully', data);
            resolve('Saved the fileContent');
        }).catch(err => {
            console.log('error saving thge data', err);
            reject(new DaoException(481, 'Error in saving the file', 
           'DaoException'));
        });
    });

};

// this is the place where I will be implementing logic to generate new 
  files
// currently I am trying to read the files that was uploaded above from 
 ./uploads folder
export const generateFilesAndEmailDataLayer = async () => {

    console.log('inside data layer');
    // console.log("Preview URL: %s", 
    nodemailer.getTestMessageUrl(transportObject));
    const result = sendEmail();
    console.log('returned result', result);
    return result;
};

const sendEmail = () => {

    // create mail account -  in ethereal
    const accnt = {
        user: 'XXXX',
        pass: 'XXXXX'
    }

    // configure smptp
    const transport = nodemailer.createTransport({
        host: 'smtp.ethereal.email',
        port: 587,
        secure: false,
        auth: {
           user: accnt.user,
           pass: accnt.pass
        }
    });
    const emailTemplateOptions = {
        defaultLayout: 'email.default',
        layoutDir: 
  path.resolve(__dirname+'./../../../../views/email/layouts/'),
        partialsDir: 
   path.resolve(__dirname+'./../../../../views/email/partials/'),
        extName: 'hbs'
    }
    let options = {
        viewEngine: {

            extname: '.handlebars',
            layoutsDir: 
    path.resolve(__dirname+'./../../../../views/email/'),
            defaultLayout : 'template',
            partialsDir : 
    path.resolve(__dirname+'./../../../../views/email/partials/')
        },
        viewPath: path.resolve(__dirname+'./../../../../views/email/'),
        extName: '.handlebars'

    };




    transport.use('compile', hbs(options));
    var mail = {
        from: 'XXXX',
        to: 

   AppEnvServiceInstance.getConfigurationSettings().$SMTP_MAIL_RECEIPIENTS,
        subject: 'Feedback Generated Files',
        template: 'email.body',
        attachments: fileArrayFunction,
        context: {
            variable1 : 'value1',
            variable2 : 'value2',
            array1: ['JOhn', 'som', 'tet']
       }
     }
    console.log('evfore sending email', fileArrayFunction);

        transport.sendMail(mail, (err, info) => {
            if(!err) {
                console.log('info', info);
                return(info);
            }else {
                console.log('err', err);
                return(err);
            }
        });



    // e
}

const fileArrayFunction =  () => {
    const dirPath = path.join(__dirname+'./../../../../assests/uploads/');
    const filesArray = [];
    const rAsync = promisify(fs.readFile);
    const rAsyncDir = promisify(fs.readdir);
    // return new Promise((resolve, reject) => {
    //     rAsyncDir(dirPath).then(data => {
    //         console.log('durectory parth read', data);
    //         data.array.forEach(element => {
    //             console.log('each element is', element);
    //             rAsync(element).then(content => {
    //                 filesArray.push({fileName: element, 
    content:content});
    //             })
    //         });
    //         resolve(filesArray);
    //     }).catch(err => {
    //         console.log(err);
    //         reject(err);
    //     });
    // });
    fs.readdirSync(dirPath).forEach(item => {
        console.log('each item dur', item);
        const content = fs.readFileSync(dirPath+item);
        filesArray.push({filename: item, content:content});
    })

    return filesArray;
}

Каталог partials, все настройки по умолчанию работают нормально. Они очень простые. Вот основной шаблон электронной почты email.body.handlebars

<h4>Main Body Here</h4>
{{variable1}} <br/>
{{variable2}}

Я мог бы отправлять электронную почту без вложений, но если вы добавите этот файл, вы увидите, что произошла ошибка времени компиляции, утверждающая, что transport.sendEmail () не может использовать константу mail , поскольку она содержит вложения как функция, а не константный массив. Пожалуйста помоги мне с этим. Я хотел бы читать файлы по мере их роста и отправлять их динамически

1 Ответ

0 голосов
/ 27 мая 2019

Я нашел ответ на это.

Итак, я пишу утилиту, подобную этой:

retrieveMailConstants(data) {
        this.mailConstants = {
            from: 'a634885.fmr.com',
            to: AppEnvServiceInstance.getConfigurationSettings().$SMTP_MAIL_RECEIPIENTS,
            subject: 'Test files - Feedback Generated Files',
            template: 'email.body',
            attachments: data,
            context: {
                variable1 : 'value1',
                variable2 : 'value2',
                array1: ['JOhn', 'som', 'tet']
           }
         }

         return this.mailConstants;
    }

Теперь данные в свойстве attachments должны быть разрешенными данными, либо разрешенными Promise, либо наблюдаемым разрешенным массивом данных.Я решил использовать наблюдаемые.Теперь мой вариант использования заключается в том, что мне нужно сгенерировать много файлов на основе информации о конфигурации из БД и сохранить эти сгенерированные файлы либо в БД, либо на отдельном сервере.На данный момент я решил сохранить их на локальном диске.Затем я читаю все файлы из этого местоположения, сохраняю их в массив и, наконец, помещаю этот массив в тему поведения

(обратите внимание, что я написал их в ts, вы можете легко преобразовать это в файл js илипередайте их)

import * as path from 'path';
import { Attachment } from 'nodemailer/lib/mailer';
import * as fs from 'fs';
import * as _ from 'lodash';
import { NodemailerAttachmentModel } from '../models/nodemailer.attachment.model';
import { BehaviorSubject, Observable, of, ConnectableObservable } from 'rxjs';
import {tap, map, filter, switchMap, share, publish, refCount, last, shareReplay} 
 from 'rxjs/operators';

let fileAttachmentSubject = new BehaviorSubject<Attachment[]>([]);

export const readFilesAndCreateAttachments = () => {
    console.log('ibside create attachments');
    console.log('dirname', __dirname);
    const dirPath = path.join(__dirname+'./../../../../assests/uploads/');
    console.log('dirparh is', dirPath);
    const filesArray =  new Array<Attachment>();
    const fileList = fs.readdirSync(dirPath);
    console.log('filelist is', fileList);
    _.each(fileList, (filePath, i) => {
        console.log('filepath in each is', filePath, 'index is', i, 'filelist each index', fileList[i]);
        if(i+1 >= fileList.length){
            // then it reached the end, time to call the observable list
            console.log('before sending', filesArray);
            setBehaviorSubject(filesArray);
        } else {
            console.log('path to read file is', dirPath+fileList[i]);
            fs.readFile(dirPath+fileList[i], (err, data) => {
                if(!err){
                    const fileInDir = new NodemailerAttachmentModel;
                    fileInDir.$content = data;
                    fileInDir.$filename = filePath;
                    filesArray.push(fileInDir);
                    console.log('inside else', filesArray.length, i, 
               fileList.length);
                }
            });

        }
    });
};

export const setBehaviorSubject = (filesArray: Attachment[]) => {
 //fileAttachmentObs = from(filesArray).;
 fileAttachmentSubject.next(filesArray);
 console.log('subject is set', filesArray.length);
}

export const getBehaviorSubject = () => {
    console.log('call to get subject');
    return fileAttachmentSubject.asObservable();
}

Теперь я использую параметры почты, сконфигурированные для транспорта, для отправки электронной почты.Транспортная конфигурация здесь не показана.Это базовая информация о конфигурации, которую можно получить на сайте nodemailer

getBehaviorSubject().subscribe(data => {
            console.log('data subscribed from subject', data);
            console.log('only then going to mail');
            let mailOptions  = nodemailerConstantInstance.retrieveMailConstants(data);

            console.log('before sending email');
            transport.sendMail(mailOptions, (err, info) => {
            if(!err) {
                console.log('info', info);
                resolve(info);
            }else {
                console.log('err', err);
                reject(err);
            }
        });

Надеюсь, это кому-то полезно.

...