【问题标题】:Nodejs send stream via emailNodejs 通过电子邮件发送流
【发布时间】:2020-10-01 16:22:28
【问题描述】:

我正在尝试使用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: 'email4@gmail.com',
            pass: 'password',
        },
    });

    let mailOptions = {
        from: 'email4@gmail.com',
        to: 'emailTo1@gmail.com',
        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);
    });

});

【问题讨论】:

  • 通常需要等待流的“完成”事件触发,然后才能执行下一个任务。因此,一旦完成事件触发,您就可以发送电子邮件,显然可以使用承诺或回调。
  • @khan 我已经更新了我的问题。你能看看我仍然没有收到任何数据的通行证。
  • 我不是流专家,但如果examplePass.generate() 返回一个可读流。我相信你可以设置content: stream。我在编辑之前阅读了您的问题,您可能已经尝试过,如果是这样,那么这不是解决方案。这是一个reference,关于如何使用nodemailer 添加附件。
  • @Hangindev 我尝试设置content: stream,但它仍然不起作用。我已经阅读了nodemailer 文档,但无法让它与流附件一起使用。
  • @Hangindev 当我记录流时我得到[object Object] 这是一个可读流吗?

标签: node.js nodemailer


【解决方案1】:

似乎在这种情况下,发送文件的唯一方法是读取整个流并将其作为字符串或缓冲区发送:

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: 'email4@gmail.com',
            pass: 'password',
        },
    });

    const mailOptions = {
        from: 'email4@gmail.com',
        to: 'emailTo1@gmail.com',
        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);
    });

});

但是!如果文件很大,您需要小心这种方法,因为它已完全加载到 RAM 中。

【讨论】:

  • 该文件现在在 300 KB 附近,但 PKPass 在我的响应端无效,除非我删除此行 stream.setEncoding('utf8'); 并且当我尝试打开PKPass 从发送的电子邮件中下载后,无论有无encoding 行。 The pass "Event.pkass" could not be opened 知道为什么会这样吗?
  • 我更新了代码,使其使用缓冲区来发送内容。请检查一下。也许它会起作用。
【解决方案2】:

您的问题是您将流通过管道传输到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: 'email4@gmail.com',
      pass: 'password',
    },
  });

  let mailOptions = {
    from: 'email4@gmail.com',
    to: 'emailTo1@gmail.com',
    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);
  });
});

这就是我传输电子邮件附件的方式。

【讨论】:

    【解决方案3】:

    嗨,我有这个问题吗? `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)
    

    `

    【讨论】:

      猜你喜欢
      • 2018-06-16
      • 1970-01-01
      • 1970-01-01
      • 2012-01-07
      • 2012-04-27
      • 2016-07-04
      • 2018-09-19
      • 2021-03-23
      相关资源
      最近更新 更多