错误:在errnoException(net.js:770:11)处写入EPIPE

我有这个系统,试图发送批量写在NodeJS的电子邮件。

它使用2个模块:fs(构build到节点v0.8.18中)和nodemailer(来自NPM,v0.3.42)。

现在执行时, node newsletter.js有时会完成并完成,但有时会随机失败,出现以下错误:

 stream.js:81 throw er; // Unhandled stream error in pipe. ^ Error: write EPIPE at errnoException (net.js:770:11) at Object.afterWrite (net.js:594:19) 

据我了解EPIPE错误发生,因为连接的另一端下降,然后我们试图写入该连接。 所有现有的EPIPE错误错误报告都是在打开http连接或类似的情况下进行的。

在下面的两件事情中可能导致的错误是NewsletterEmail中的mailer.sendmailer.send中的mailer.send。 它更可能是错误将在mailer.send和nodemailer打开连接的地方。 然而,没有错误通过抛出或callback错误parameter passing回来,所以似乎没有办法看到是什么导致错误。

大多数人build议定义error handling程序。 然而,在nodemailer或fs模块中没有任何东西允许我定义一个error handling程序。 来自mailer.send调用的mailer.send中的callback函数在其callback函数中传递了一个错误参数,但是这个特定的错误并没有通过那里。

我已经尝试了以下的东西:

  • fs.readFileSync和nodemailer传输sendEmail调用周围添加try / catch。
  • 删除fs.readFileSync调用和内联html – 当我这样做的错误似乎并没有发生。 但是同样,节点文档没有指出在readFileSync上应该发生EPIPE错误,而且肯定没有办法添加error handling程序。

触发这个错误的代码如下:

 var nodemailer = require('nodemailer'); var fs = require('fs'); /** * Provides a way to build newsletters when given a folder containing * the relevant template and images in a standard format. This folder * must contain a newsletter.html file, a newsletter.txt file and a images * directory containing any images. * * @param {Object} settings The full folder path to the */ function NewsletterEmail(newsletterGroup, newsletterName) { var folder = '/var/newsletters/' + newsletterGroup + '/' + newsletterName; this._html = fs.readFileSync(folder + '/newsletter.html', 'utf-8'); this._text = fs.readFileSync(folder + '/newsletter.txt', 'utf-8'); } NewsletterEmail.prototype.getSubject = function() { return 'Testing'; } /** * Generates the HTML version of a newsletter. * * @return {String} */ NewsletterEmail.prototype.buildHTML = function(email) { var htmlPart = this._html; return htmlPart; } /** * Generates the text counterpart of a newsletter. * * @return {String} */ NewsletterEmail.prototype.buildText = function(email) { var textPart = this._text; return textPart; } /** * Creates a NewsletterEmail from the given folder. * * @param {String} folder The folder containing the html template, text template and images for a newsletter. * @return {NewsletterEmail} */ NewsletterEmail.create = function(newsleterGroup, newsletterName) { return new NewsletterEmail(newsleterGroup, newsletterName); } function NewsletterMailer(fromEmail) { this._from = fromEmail; this._transport = nodemailer.createTransport('sendmail'); } NewsletterMailer.prototype = { send: function(email, newsletterEmail, callback) { var mailOptions = { to: email, from: this._from, subject: newsletterEmail.getSubject(), html: newsletterEmail.buildHTML(email), text: newsletterEmail.buildText(email) }; this._transport.sendMail(mailOptions, callback); }, close: function() { this._transport.close(); } } function Newsletter() { this._id = 1; this.countSent = 0; this.emailsToSend = ['email1@example.com', 'email2@example.com', 'email3@example.com', 'email4@example.com', 'email5@example.com', 'email6@example.com']; } Newsletter.prototype.send = function() { var newsletter = this; var newsletterEmail = NewsletterEmail.create('company1', '2013-01-24-mynewsleter'); var mailer = new NewsletterMailer('company@example.com'); function sendEmail() { var email = newsletter.emailsToSend.pop(); mailer.send(email, newsletterEmail, function(mailerErr) { if (mailerErr) { console.log('Mailer error: ', mailerErr); } newsletter.countSent++; console.log('progress ' + newsletter.countSent); if (newsletter.emailsToSend.length > 0) { sendEmail(); } else { mailer.close(); console.log('complete'); } }); } sendEmail(); } var nl = new Newsletter(); nl.send(); 

有没有其他人遇到类似的错误? 你有任何提示debugging或可能的解决scheme。

随着堆栈跟踪给予即时通讯现在有点死胡同。 以下是strace的输出。 似乎总是死在那封邮件mimepart边界上:

 futex(0x7f039c0008c8, FUTEX_WAKE_PRIVATE, 1) = 1 write(8, "------Nodemailer-0.3.42-?=_1-136"..., 131) = -1 EPIPE (Broken pipe) --- SIGPIPE {si_signo=SIGPIPE, si_code=SI_USER, si_pid=13813, si_uid=0} --- --- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=13818, si_status=0, si_utime=0, si_stime=0} --- write(4, "\1\0\0\0\0\0\0\0", 8) = 8 rt_sigreturn() = -1 EPIPE (Broken pipe) futex(0x7f039c0008c8, FUTEX_WAKE_PRIVATE, 1) = 1 write(8, "<!DOCTYPE HTML PUBLIC =22-//W3C/"..., 18098) = -1 EPIPE (Broken pipe) --- SIGPIPE {si_signo=SIGPIPE, si_code=SI_USER, si_pid=13813, si_uid=0} --- futex(0x7f039c0008c8, FUTEX_WAKE_PRIVATE, 1) = 1 close(8) = 0 epoll_wait(3, {{EPOLLIN|EPOLLHUP, {u32=9, u64=4294967305}}, {EPOLLIN|EPOLLHUP, {u32=11, u64=4294967307}}, {EPOLLIN, {u32=4, u64=4294967300}}}, 64, 0) = 3 epoll_ctl(3, EPOLL_CTL_MOD, 9, {EPOLLIN, {u32=9, u64=4294967305}}) = 0 epoll_ctl(3, EPOLL_CTL_MOD, 11, {EPOLLIN, {u32=11, u64=4294967307}}) = 0 read(4, "\1\0\0\0\0\0\0\0", 8) = 8 wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], WNOHANG|WSTOPPED|WCONTINUED, NULL) = 13818 ioctl(1, SNDCTL_TMR_TIMEBASE or SNDRV_TIMER_IOCTL_NEXT_DEVICE or TCGETS, 0x7fff2d6f4340) = -1 EINVAL (Invalid argument) fstat(1, {st_mode=S_IFIFO|0600, st_size=0, ...}) = 0 write(1, "progress 1\n", 11progress 1 ) = 11 socketpair(PF_FILE, SOCK_STREAM|SOCK_CLOEXEC, 0, [7, 8]) = 0 socketpair(PF_FILE, SOCK_STREAM|SOCK_CLOEXEC, 0, [10, 12]) = 0 socketpair(PF_FILE, SOCK_STREAM|SOCK_CLOEXEC, 0, [13, 14]) = 0 pipe2([15, 16], O_NONBLOCK|O_CLOEXEC) = 0 clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f03a4b35a10) = 13820 close(16) = 0 poll([{fd=15, events=POLLIN|POLLHUP}], 1, -1) = 1 ([{fd=15, revents=POLLHUP}]) close(15) = 0 close(7) = 0 ioctl(8, FIONBIO, [1]) = 0 close(12) = 0 ioctl(10, FIONBIO, [1]) = 0 close(14) = 0 ioctl(13, FIONBIO, [1]) = 0 wait4(-1, 0x7fff2d6f529c, WNOHANG|WSTOPPED|WCONTINUED, NULL) = 0 futex(0x7f039c0008c8, FUTEX_WAKE_PRIVATE, 1) = 1 brk(0x932000) = 0x932000 read(11, "", 65536) = 0 close(11) = 0 read(9, "", 65536) = 0 futex(0x7f039c0008c8, FUTEX_WAKE_PRIVATE, 1) = 1 close(9) = 0 write(2, "\n", 1 ) = 1 write(2, "events.js:71\n", 13events.js:71 

这是由nodemailer模块包装75个字符的行引起的。 一行是76个字符,最后一个点。 这个点被包装在自己的线上。

对于SMTP服务器,线上的一个点本身表示消息的结束,并且连接已closures。 这导致连接过早closures,随后的写入失败,出现EPIPE错误。

在nodemailer维护者的帮助下,现在已经通过在sendmail调用中添加hte -i标志来修复问题0.3.43,它告诉sendmail允许使用单个点的行。

更多细节可在这里: https : //github.com/andris9/Nodemailer/issues/141 。