使用Node.js通过电子邮件发送数据流

7

我正在尝试使用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);
    });

});

1
通常需要等待流的“完成”事件触发后才能继续下一项任务。因此,一旦完成事件触发,就可以发送电子邮件,显然可以使用 promises 或 callbacks。 - khan
@khan,我已经更新了我的问题。你能看一下吗?我仍然没有收到任何数据的通行证。 - user
@Hangindev 当我记录流时,我得到了[object Object],这是一个可读流吗? - user
你有examplePass.generate()的实现吗? - hangindev.com
让我们在聊天中继续这个讨论。@Hangindev - user
显示剩余6条评论
3个回答

5

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

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,但是除非我删除这行代码stream.setEncoding('utf8');,否则我的响应端无法识别PKPass。当我尝试从发送的电子邮件中下载PKPass时,无论是否包含encoding行,都会收到此消息:无法打开通行证“Event.pkass”。你有什么想法吗? - user
我更新了代码,使用缓冲区发送内容。请查看一下,也许会起作用。 - Rustam D9RS

3
你的问题在于你将流传送到了一个名为 "StreamReader" 的消费者 res,相反你只需要将其传递给nodeMailer即可,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);
  });
});

这是我如何流式传输电子邮件附件。

-1

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

`


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接