I have this system that is trying to send bulk emails written in NodeJS.
It uses 2 modules: fs (built into node v0.8.18) and nodemailer (from NPM, v0.3.42).
Now, after executing with node newsletter.js sometimes it ends and ends, but sometimes it randomly breaks at a random point with the following error:
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)
As far as I understand, the EPIPE error occurs because the other end of the connection went down, and then we tried to record this connection. All existing reports of this EPIPE error error are in the context of opening an http connection or the like.
What I have below two factors that can cause an error is fs.readFileSync in NewsletterEmail or mailer.send in NewsleterMailer. Most likely, the error will be in mailer.send and nodemailer, a connection is opened somewhere. However, no error is returned back through the throw or callback error argument, so there seems to be no way to see what causes the error.
Most people suggest defining an error handler. However, there is nothing in the nodemailer or the fs module that would allow me to define an error handler. The callback to nodemailer from the call to mailer.send passes the error argument to its callback, however this particular error does not go through it.
I have tried the following things:
- adding try / catch in both
fs.readFileSync and sendEmail calls to send nodemailer. - Removing fs.readFileSync calls and turning on html - when I do this, an error does not occur. But then again, node documents have no indication that EPIPE read errors should occur in readFileSync, and of course there is no way to add an error handler.
The code that causes this error is below:
var nodemailer = require('nodemailer'); var fs = require('fs'); 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'; } NewsletterEmail.prototype.buildHTML = function(email) { var htmlPart = this._html; return htmlPart; } NewsletterEmail.prototype.buildText = function(email) { var textPart = this._text; return textPart; } 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();
Does anyone else encounter similar errors? You have some debugging tips or possible solutions.
With the stack trace given by im at a standstill with this now. The following is the output of strace. It always seems to die on this mimepart mail border:
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