Search code examples
node.jsimap

err_http_headers_sent]: cannot set headers after they are sent to the client in fetching email from server


I am trying to fetch email with attachment.I have used imap and MailListener2 library for that.i am facing following error as shown in image.i am getting all data fetched from email with attachment.can anyone tell what i have missed?this is my console image

this is my code which i have used for fetching email .please provide any solution for this error.

async function mailreply(req, res) {
    Employee.email_reply(req.params.email, function (err, employee) {
         
         var imapConfig = {
            user: '*****',
            password: '****',
            host: 'imap-mail.outlook.com',
            port: 993,
            tls: true,
            tlsOptions: {
                rejectUnauthorized: false
            }
        };

        var imap = new Imap(imapConfig);
        imap.once("ready", checkMail);
        imap.once("error", function (err) {
            console.log("Connection error: " + err.stack);
        });
        imap.connect();
        function checkMail() {
            imap.openBox("INBOX", false, function (err, mailBox) {
                if (err) {
                    console.error(err);
                    return;
                }
                imap.search(["UNSEEN", ["FROM", req.params.email]], function (err, results) {
                    if (!results || !results.length) {  
                        req.flash('error', 'No reply from selected user.')  
                        res.locals.message = req.flash();   
                        res.redirect(nodeSiteUrl+'/dashboard');  
                        imap.end(); return; }
                });
            });
        }
        
        
        
        
        var mailListener = new MailListener({
              username: "******",
              password: "******",
              host: "imap-mail.outlook.com",
              port: 993, // imap port
              tls: true,
              connTimeout: 10000, // Default by node-imap
              authTimeout: 5000, // Default by node-imap,
              tlsOptions: { rejectUnauthorized: false },
              mailbox: "INBOX", // mailbox to monitor
              searchFilter: [ 'UNSEEN', ['FROM', req.params.email] ], // the search filter being used after an IDLE notification has been retrieved , 
              markSeen: false, // all fetched email willbe marked as seen and not fetched next time
              fetchUnreadOnStart: true, // use it only if you want to get all unread email on lib start. Default is `false`,
              mailParserOptions: {streamAttachments: true}, // options to be passed to mailParser lib.
              attachments: true, // download attachments as they are encountered to the project directory
              attachmentOptions: { directory: "attachments/" } // specify a download directory for attachments
        });
            
        mailListener.start();
        
        mailListener.on("server:connected", function(){
          console.log("imapConnected");
        });
        
        mailListener.on("error", function(err){
          console.log('hello');
        });

        mailListener.on("mail", function(mail, seqno, attributes){
            console.log(seqno)
            let attachments = [];
            var attachment = mail.attachments;
            if(attachment) {
                for(var i = 0, len = attachment.length; i < len; ++i){
                    attachments.push(attachment[i].fileName);
                }
            }
            passDatatoPage(mail, attachments);
            mailListener.stop();
        }) 
       
        mailListener.on("attachment", function(attachment){
            let filepath = './public/attachment/receive/';
            let output = fs.createWriteStream(filepath + attachment.fileName);
            attachment.stream.pipe(output).on("end", function () {
                console.log("All the data in the file has been read");
            }).on("close", function (err) {
                console.log("Stream has been cloesd.");
            });  
        });
    
    
        function passDatatoPage(mail, attachments) {
            var sender = mail.to[0].address;
            var senderName = mail.from[0].name;
            var reciver = mail.from[0].address;
            const date = moment(mail.date).format('LL');
            var subject = mail.subject;
            var message = mail.text;
            //console.log(attachments);
            var result = attachments.map(function(val) {
                return val;
            }).join(',');
            var attachmentArr = result.split(',');
            console.log(attachmentArr)
            res.render('email-reply', { title: 'Email Reply', to: sender, senderName: senderName, from: reciver, date: date, subject: subject, msg: message, attachments: attachmentArr});
        }
        
    });
};
exports.mailreply = mailreply;

Solution

  • you need to do two things

    1. try to wrap up code with try catch block
    2. do not fetch all emails from sender fetch only thhose mail witch is needed For example fetch mail using message id as shown below get that message id and change search filter acording to below code (use below search filter to find message by id)
    var mailListener = new MailListener({
                  username: "******",
                  password: "*****",
                  host: "imap-mail.outlook.com",
                  port: 993, // imap port
                  tls: true,
                  connTimeout: 10000, // Default by node-imap
                  authTimeout: 5000, // Default by node-imap,
                  tlsOptions: { rejectUnauthorized: false },
                  mailbox: "INBOX", // mailbox to monitor
                  searchFilter: [ ['HEADER','IN-REPLY-TO',messageId] ], // the search filter being used after an IDLE notification has been retrieved , 
                  markSeen: false, // all fetched email willbe marked as seen and not fetched next time
                  fetchUnreadOnStart: true, // use it only if you want to get all unread email on lib start. Default is `false`,
                  mailParserOptions: {streamAttachments: true}, // options to be passed to mailParser lib.
                  attachments: true, // download attachments as they are encountered to the project directory
                  attachmentOptions: { directory: "attachments/" } // specify a download directory for attachments
            });