updates to email node to better handle

different mail types. Still not great - but does the basics…  To close
#210 for now
This commit is contained in:
Dave Conway-Jones 2016-06-07 15:57:40 +01:00
parent b6f45ef8d4
commit f91b7c4630
2 changed files with 113 additions and 61 deletions

View File

@ -191,26 +191,69 @@ module.exports = function(RED) {
// in the message flow. The parameter called `msg` is the template message we // in the message flow. The parameter called `msg` is the template message we
// start with while `mailMessage` is an object returned from `mailparser` that // start with while `mailMessage` is an object returned from `mailparser` that
// will be used to populate the email. // will be used to populate the email.
// DCJ NOTE: - heirachical multipart mime parsers seem to not exist - this one is barely functional.
function processNewMessage(msg, mailMessage) { function processNewMessage(msg, mailMessage) {
msg = JSON.parse(JSON.stringify(msg)); // Clone the message msg = JSON.parse(JSON.stringify(msg)); // Clone the message
// Populate the msg fields from the content of the email message // Populate the msg fields from the content of the email message
// that we have just parsed. // that we have just parsed.
msg.html = mailMessage.html; if ((mailMessage.text) && (mailMessage.text.indexOf("--=_") !== -1)) {
msg.payload = mailMessage.text; //processNewMessage(msg,mailMessage.text);
if (mailMessage.attachments) { var parts = mailMessage.text.split("--=_");
msg.attachments = mailMessage.attachments; msg.payload = parts[0].trim();
} else { for (var p = 0; p < parts.length; p++) {
msg.attachments = []; //console.log("\n\nP***",p+"\n"+JSON.stringify(parts[p]),"\n***P\n\n");
if (parts[p].indexOf("text/plain") >= 0) {
msg.payload = parts[p].split("\n\n",2)[1].trim();
}
if (parts[p].indexOf("text/html") >= 0) {
msg.html = parts[p].split("\n\n",2)[1].trim();
}
if (parts[p].indexOf("=--\n\n") >= 0) {
//msg.header = "text: "+msg.payload+"\n\n"+parts[p].split("\n\n",2)[1].trim();
var mailparser = new MailParser();
mailparser.on("end", function(mailMessage) {
//console.log("DONG",mailMessage);
msg.header = mailMessage.headers;
msg.topic = mailMessage.subject;
msg.date = mailMessage.date;
if (mailMessage.from && mailMessage.from.length > 0) {
msg.from = mailMessage.from[0].address;
}
if (mailMessage.attachments) {
msg.attachments = mailMessage.attachments;
} else {
msg.attachments = [];
}
node.send(msg); // Propagate the message down the flow
});
mailparser.write(parts[p].split("\n\n",2)[1].trim());
mailparser.end();
}
}
} }
msg.topic = mailMessage.subject; else {
msg.header = mailMessage.headers; if (!mailMessage.text) {
msg.date = mailMessage.date; msg.payload = mailMessage.headers.text;
if (mailMessage.from && mailMessage.from.length > 0) { msg.topic = mailMessage.subject;
msg.from = mailMessage.from[0].address; msg.header = mailMessage.headers;
msg.date = mailMessage.date;
}
else {
msg.payload = mailMessage.text;
}
if (mailMessage.html) {
msg.html = mailMessage.html;
}
if (mailMessage.from && mailMessage.from.length > 0) {
msg.from = mailMessage.from[0].address;
}
if (mailMessage.attachments) {
msg.attachments = mailMessage.attachments;
} else {
msg.attachments = [];
}
node.send(msg); // Propagate the message down the flow
} }
node.send(msg); // Propagate the message down the flow
} // End of processNewMessage } // End of processNewMessage
// Check the POP3 email mailbox for any new messages. For any that are found, // Check the POP3 email mailbox for any new messages. For any that are found,
@ -313,59 +356,63 @@ module.exports = function(RED) {
// //
// Check the email sever using the IMAP protocol for new messages. // Check the email sever using the IMAP protocol for new messages.
function checkIMAP(msg) { function checkIMAP(msg) {
node.log("Checkimg IMAP for new messages"); node.log("Checking IMAP for new messages");
// We get back a 'ready' event once we have connected to imap // We get back a 'ready' event once we have connected to imap
imap.once("ready", function() { imap.once("ready", function() {
node.status({fill:"blue", shape:"dot", text:"email.status.fetching"}); node.status({fill:"blue", shape:"dot", text:"email.status.fetching"});
console.log("> ready"); //console.log("> ready");
// Open the inbox folder // Open the inbox folder
imap.openBox('INBOX', // Mailbox name imap.openBox('INBOX', // Mailbox name
false, // Open readonly? false, // Open readonly?
function(err, box) { function(err, box) {
console.log("> Inbox open: %j", box); //console.log("> Inbox open: %j", box);
imap.search([ 'UNSEEN' ], function(err, results) { imap.search([ 'UNSEEN' ], function(err, results) {
if (err) { if (err) {
node.status({fill:"red", shape:"ring", text:"email.status.foldererror"}); node.status({fill:"red", shape:"ring", text:"email.status.foldererror"});
node.error(RED._("email.errors.fetchfail", {folder:node.box}),err); node.error(RED._("email.errors.fetchfail", {folder:node.box}),err);
imap.end();
return; return;
} }
console.log("> search - err=%j, results=%j", err, results); //console.log("> search - err=%j, results=%j", err, results);
if (results.length === 0) { if (results.length === 0) {
console.log(" [X] - Nothing to fetch"); //console.log(" [X] - Nothing to fetch");
node.status({});
imap.end();
return; return;
} }
// We have the search results that contain the list of unseen messages and can now fetch those messages. // We have the search results that contain the list of unseen messages and can now fetch those messages.
var fetch = imap.fetch(results, { var fetch = imap.fetch(results, {
bodies : ["HEADER", "TEXT"], //bodies : ['HEADER.FIELDS (FROM SUBJECT DATE)','TEXT'],
bodies : ['HEADER','TEXT'],
markSeen : true markSeen : true
}); });
// For each fetched message returned ... // For each fetched message returned ...
fetch.on('message', function(imapMessage, seqno) { fetch.on('message', function(imapMessage, seqno) {
node.log(RED._("email.status.message",{number:seqno})); //node.log(RED._("email.status.message",{number:seqno}));
var messageText = ""; var messageText = "text: ";
console.log("> Fetch message - msg=%j, seqno=%d", imapMessage, seqno); //console.log("> Fetch message - msg=%j, seqno=%d", imapMessage, seqno);
imapMessage.on('body', function(stream, info) { imapMessage.on('body', function(stream, info) {
console.log("> message - body - stream=?, info=%j", info); //console.log("> message - body - stream=?, info=%j", info);
// Info defined which part of the message this is ... for example // Info defined which part of the message this is ... for example
// 'TEXT' or 'HEADER' // 'TEXT' or 'HEADER'
stream.on('data', function(chunk) { stream.on('data', function(chunk) {
console.log("> stream - data - chunk=??"); //console.log("> stream - data - chunk=??");
messageText += chunk.toString('utf8'); messageText += chunk.toString('utf8');
}); });
stream.once('end', function() {
if (info.which !== 'TEXT') {
var mailparser = new MailParser();
mailparser.on("end", function(mailMessage) {
//console.log("mailparser: on(end): %j", mailMessage);
processNewMessage(msg, mailMessage);
});
mailparser.write(messageText);
mailparser.end();
}
}); // End of msg->end
}); // End of msg->body }); // End of msg->body
// When the `end` event is raised on the message
imapMessage.once('end', function() {
console.log("> msg - end : %j", messageText);
var mailparser = new MailParser();
mailparser.on("end", function(mailMessage) {
//console.log("mailparser: on(end): %j", mailMessage);
processNewMessage(msg, mailMessage);
});
mailparser.write(messageText);
mailparser.end();
}); // End of msg->end
}); // End of fetch->message }); // End of fetch->message
// When we have fetched all the messages, we don't need the imap connection any more. // When we have fetched all the messages, we don't need the imap connection any more.
@ -416,7 +463,7 @@ module.exports = function(RED) {
}); });
imap.on('error', function(err) { imap.on('error', function(err) {
node.log(err); node.log(err);
node.status({fill:"red",shape:"ring",text:"email.status.connecterror"}); //node.status({fill:"red",shape:"ring",text:"email.status.connecterror"});
}); });
} }

View File

@ -1,27 +1,32 @@
{ {
"name" : "node-red-node-email", "name": "node-red-node-email",
"version" : "0.1.7", "version": "0.1.8",
"description" : "Node-RED nodes to send and receive simple emails", "description": "Node-RED nodes to send and receive simple emails",
"dependencies": { "dependencies": {
"nodemailer": "^1.11.0", "nodemailer": "^1.11.0",
"poplib": "^0.1.7", "poplib": "^0.1.7",
"mailparser": "^0.5.3", "mailparser": "^0.6.0",
"imap": "^0.8.17" "imap": "^0.8.17"
}, },
"repository": { "repository": {
"type": "git", "type": "git",
"url":"https://github.com/node-red/node-red-nodes/tree/master/social/email" "url": "https://github.com/node-red/node-red-nodes/tree/master/social/email"
}, },
"license": "Apache-2.0", "license": "Apache-2.0",
"keywords": [ "node-red", "email", "gmail", "imap" ], "keywords": [
"node-red": { "node-red",
"nodes": { "email",
"email": "61-email.js" "gmail",
} "imap"
}, ],
"author": { "node-red": {
"name": "Dave Conway-Jones", "nodes": {
"email": "ceejay@vnet.ibm.com", "email": "61-email.js"
"url": "http://nodered.org"
} }
},
"author": {
"name": "Dave Conway-Jones",
"email": "ceejay@vnet.ibm.com",
"url": "http://nodered.org"
}
} }