Nodejs отправляет поток по электронной почте

Я пытаюсь отправить данные своего потока по электронной почте с помощью Nodemailer, но по какой-то причине приходит вложение вверх как 0 kb, когда я его загружаю и просматриваю информацию. Как правильно отправить поток и его данные в виде вложения? Поток должен содержать PKPass. Это лучший вариант - отправить ответ в виде вложения? Я использую passkit-generator для создания PKPass

const stream = examplePass.generate();

res.set({
    'Content-Type': 'application/vnd.apple.pkpass',
    'Content-disposition': `attachment; filename=${passName}.pkpass`,
});

stream.pipe(res);

//Send the receipt email

stream.on('finish', (attach) => {

    let transporter = nodemailer.createTransport({
        host: 'smtp.gmail.com',
        port: 587,
        secure: false,
        requireTLS: true,
        auth: {
            user: '[email protected]',
            pass: 'password',
        },
    });

    let mailOptions = {
        from: '[email protected]',
        to: '[email protected]',
        subject: 'You\'re on your way to ',
        html: '<h1>Reciept email</h1>',
        attachments: [
            {
                filename: 'Event.pkpass',
                contentType: 'application/vnd.apple.pkpass',
                content: stream,
            },
        ],
    };

    transporter.sendMail(mailOptions, (error, info) => {
        if (error) {
            return console.log(error.message);
        }
        console.log('success ' + info);
    });

});

person user    schedule 11.06.2020    source источник
comment
Обычно нужно дождаться срабатывания события «finish» потока, прежде чем переходить к следующей задаче. Итак, как только сработает событие завершения, вы можете отправить электронное письмо, очевидно, можно использовать обещания или обратные вызовы.   -  person khan    schedule 12.06.2020
comment
@khan Я обновил свой вопрос. Вы можете взглянуть, я все еще не получаю пропуск с какими-либо данными.   -  person user    schedule 15.06.2020
comment
Я не специалист по потокам, но если examplePass.generate() возвращает читаемый поток. Я полагаю, вы могли бы просто установить content: stream. Я прочитал ваш вопрос перед редактированием, вы уже можете попробовать это, если это так, то это не решение. Вот справочник о том, как добавлять вложения с помощью nodemailer.   -  person Hangindev    schedule 15.06.2020
comment
@Hangindev Я пытался установить content: stream, но это все равно не сработало. Я прочитал nodemailer документацию, но не могу заставить ее работать с вложением потока.   -  person user    schedule 15.06.2020
comment
@Hangindev, когда я регистрирую поток, я получаю [object Object], это читаемый поток?   -  person user    schedule 15.06.2020
comment
У вас есть реализация examplePass.generate()?   -  person Hangindev    schedule 15.06.2020
comment
Да, я так думаю, const stream = examplePass.generate(); в моем коде - это реализация. Верно? @Hangindev   -  person user    schedule 15.06.2020
comment
Я имел ввиду код внутри функции generate.   -  person Hangindev    schedule 15.06.2020
comment
Позвольте нам продолжить это обсуждение в чате. @Hangindev   -  person user    schedule 15.06.2020
comment
Вы можете увидеть, если что-то произойдет с событием data? Я спрашиваю, потому что с обычными потоками, созданными с использованием fs.createReadStream, ваш код работает нормально.   -  person Rustam D9RS    schedule 15.06.2020
comment
@ RustamD9RS Когда я вызываю эту функцию stream.pipe(res), ответ на стороне клиента имеет прикрепленный PKPass, как и ожидалось. Это то, что вы имеете в виду?   -  person user    schedule 15.06.2020


Ответы (3)


Кажется, что в этом случае единственный способ отправить файл - это прочитать весь поток и отправить его в виде строки или буфера:

const stream = examplePass.generate();

res.set({
    'Content-Type': 'application/vnd.apple.pkpass',
    'Content-disposition': `attachment; filename=${passName}.pkpass`,
});

stream.pipe(res);

const chunks = [];

stream.on('data', chunk => {
    chunks.push(chunk);
});

stream.on('end', () => {
    const content = Buffer.concat(chunks);

    const transporter = nodemailer.createTransport({
        host: 'smtp.gmail.com',
        port: 587,
        secure: false,
        requireTLS: true,
        auth: {
            user: '[email protected]',
            pass: 'password',
        },
    });

    const mailOptions = {
        from: '[email protected]',
        to: '[email protected]',
        subject: 'You\'re on your way to ',
        html: '<h1>Reciept email</h1>',
        attachments: [
            {
                filename: 'Event.pkpass',
                contentType: 'application/vnd.apple.pkpass',
                content
            },
        ],
    };

    transporter.sendMail(mailOptions, (error, info) => {
        if (error) {
            return console.log(error.message);
        }
        console.log('success:', info);
    });

});

НО! Вам нужно быть осторожным с этим подходом, если файл большой, так как он полностью загружен в ОЗУ.

person Rustam D9RS    schedule 15.06.2020
comment
Файл сейчас находится около 300 KB, но PKPass недействителен в конце моего ответа, если я не удалю эту строку stream.setEncoding('utf8');, и я получаю это сообщение, когда пытаюсь открыть PKPass после загрузки его из отправленного электронного письма со строкой encoding и без нее. . The pass "Event.pkass" could not be opened есть идеи, почему это могло быть? - person user; 16.06.2020
comment
Я обновил код, чтобы он использовал буфер для отправки содержимого. Зацените, пожалуйста. Может получится. - person Rustam D9RS; 16.06.2020

Ваша проблема в том, что вы направили поток в res, который является «StreamReader» или потребителем, вместо этого вам нужно просто передать его в nodeMailer, который сам по себе является StreamReader.

const stream = examplePass.generate();

// res.set({
//   'Content-Type': 'application/vnd.apple.pkpass',
//   'Content-disposition': `attachment; filename=${passName}.pkpass`,
// });

// stream.pipe(res); <- remove this

//Send the receipt email

stream.on('finish', (attach) => {
  let transporter = nodemailer.createTransport({
    host: 'smtp.gmail.com',
    port: 587,
    secure: false,
    requireTLS: true,
    auth: {
      user: '[email protected]',
      pass: 'password',
    },
  });

  let mailOptions = {
    from: '[email protected]',
    to: '[email protected]',
    subject: "You're on your way to ",
    html: '<h1>Reciept email</h1>',
    attachments: [
      {
        filename: 'Event.pkpass',
        contentType: 'application/vnd.apple.pkpass',
        content: stream,
      },
    ],
  };

  transporter.sendMail(mailOptions, (error, info) => {
    if (error) {
      return console.log(error.message);
    }
    console.log('success ' + info);
  });
});

Вот как я транслирую вложения электронной почты.

person felixmosh    schedule 20.06.2020

привет, у меня есть эти проблемы? `file: ///home/racal/JavaScript/Node/Web-Env/webpack.config.dev.js: 10 path.resolve (__ dirname, 'src / index') ^

ReferenceError: __dirname is not defined
at file:///home/racal/JavaScript/Node/Web-Env/webpack.config.dev.js:10:18
at ModuleJob.run (internal/modules/esm/module_job.js:138:23)
at async Loader.import (internal/modules/esm/loader.js:178:24)

`

person Racal    schedule 22.06.2020