2013-02-27 3 views
4

NodeJS로 작성된 대량 전자 메일을 보내려고하는이 시스템이 있습니다.오류 : errnoException (net.js : 770 : 11)에 EPIPE를 작성하십시오.

fs (노드 v0.8.18 빌드) 및 nodemailer (NPM, v0.3.42)의 두 모듈을 사용합니다. node newsletter.js와 실행시에 이제

가끔 완료되어 완료되지만, 때로는 무작위로 다음과 같은 오류와 임의의 지점에서 실패합니다 : 지금까지 내가 EPIPE 오류가 다른 때문에 발생하는 이해

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 오류 버그의 모든 기존 보고서는 http 연결 또는 유사한 열기와 관련됩니다.

아래에 나와있는 내용은 NewsletterEmail의 fs.readFileSync 또는 NewsleterMailer의 mailer.send입니다. 오류가 mailer.send와 nodemailer에있을 가능성이 높기 때문에 어딘가에서 연결을 열 수 있습니다. 그러나 throw 또는 콜백 오류 인수를 통해 오류가 다시 전달되지 않으므로 오류를 일으키는 원인을 알 수있는 방법이없는 것으로 보입니다.

대부분의 사람들은 오류 처리기 정의를 제안합니다. 그러나 nodemailer 또는 fs 모듈에는 오류 처리기를 정의 할 수있는 것이 없습니다. mailer.send 호출에서 nodemailer의 콜백은 콜백에 오류 인수를 전달하지만이 특정 오류는 거기를 통해 전달되지 않습니다.

나는 다음과 같은 일을 시도 :

  • 이 시도/모두 fs.readFileSync 주위 캐치 nodemailer 전송 sendEmail 호출을 추가.
  • fs.readFileSync 호출을 제거하고 html을 인라이닝 할 때 오류가 발생하지 않습니다. 그러나 노드 문서에는 EPIPE 오류가 readFileSync에서 발생해야한다는 표시가없고 오류 처리기를 추가 할 수있는 방법이 없습니다.

이 오류를 트리거 코드 은 다음과 같습니다 :

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 = ['[email protected]', '[email protected]', '[email protected]', '[email protected]', '[email protected]', '[email protected]']; 
} 

Newsletter.prototype.send = function() { 
    var newsletter = this; 

    var newsletterEmail = NewsletterEmail.create('company1', '2013-01-24-mynewsleter'); 
    var mailer = new NewsletterMailer('[email protected]'); 

    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(); 

은 다른 사람이 유사한 오류가 건너 했습니까? 디버깅을위한 조언이나 가능한 해결책이 있습니까?

스택 추적을 사용하여 현재 막 다른 부분에 약간의 im이 있습니다. 아래는 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 
+0

'Socket.write' (net.js)에서 오류가 발생하므로 nodemailer의 문제라고 생각합니다. Linux를 실행중인 경우 strace를 사용하여 Node를 실행 해보십시오. MTA가 어떤 이유로 든 연결을 끊는 것일 수 있습니다. – robertklep

+0

strace 팁 주셔서 감사합니다. 그게 실제로 무엇을 볼 수 있습니다. strace의 출력으로 게시물을 업데이트했습니다. 얼마나 정직하라고 나에게 정말로 알려주는지 잘 모르겠다. nodemailer가 MTA와 같은 것을 처리하고 콜백의 오류 인수를 통해 다시보고하여 문제를 처리 할 수 ​​있다고 생각했을 것입니다. – rikkiloades

+0

체크 아웃 http://stackoverflow.com/a/12267735/893780 (sendmail에 대한 의견이 있습니다) – robertklep

답변

5

이 75 자에서 nodemailer 모듈 포장 라인에 의해 발생했다. 한 줄의 길이는 정확히 76 자이고 마지막에 점이 표시됩니다. 이 점은 자체 선으로 감싸였습니다.

SMTP 서버의 경우 한 줄에 점은 메시지의 끝을 의미하며 연결이 닫힙니다. 이로 인해 연결이 조기에 닫히고 EPIPE 오류로 인해 쓰기가 실패했습니다.

nodemailer 관리자의 도움을 받아 sendmail에 hte -i 플래그를 추가하여 sendmail이 한 점이있는 줄을 허용하도록 수정하여 문제 0.3.43에서 수정되었습니다.

자세한 내용은 https://github.com/andris9/Nodemailer/issues/141입니다.

+0

공유 주셔서 감사합니다, 그것은 얼마 동안 저를 괴롭 히고있었습니다. – galchen