/* * @author: Andrew Van Tassel * @email: andrew@andrewvantassel.com * @website: http://Mailhops.com */ const MailHops = { msgURI: null, isLoaded: false, options: { version: 'MailHops Plugin 4.0.0', api_key: '', owm_key: '', lang: 'en', unit: 'mi', api_http: 'https://', api_host: 'api.Mailhops.com', debug: true, country_tag: false, travel_time_junk: false, country_filter: [] }, message: { id: null , map_url: '' , time: null , secure: [] , headers: [] , auth: [] , sender: { icon: '/images/refresh.png' , title: 'Loading...' , description: '' } }, response: {}, meta: {} }; MailHops.LOG = function(msg) { if(!MailHops.options.debug) return; console.log('MailHops', msg); }; MailHops.init = function(reload) { var getting = browser.storage.local.get(); getting.then(data => { if (data.api_key) { MailHops.options.api_key = data.api_key; } if (data.owm_key) { MailHops.options.owm_key = data.owm_key; } if (data.lang) { MailHops.options.lang = data.lang; } if (data.unit) { MailHops.options.unit = data.unit; } MailHops.LOG('load MailHops prefs'); }, error => { MailHops.LOG('Error loading MailHops prefs'); }); }; MailHops.getRoute = function () { // set loading icon browser.messageDisplayAction.setPopup({ popup: '' }); browser.messageDisplayAction.setIcon({ path: '/images/refresh.png' }); browser.messageDisplayAction.setTitle({ title: 'Loading...' }); if(browser.mailHopsUI) browser.mailHopsUI.insertBefore("", '/images/refresh.png', '', "countryIcon", "expandedHeaders2"); //IP regex var regexIp=/(1\d{0,2}|2(?:[0-4]\d{0,1}|[6789]|5[0-5]?)?|[3-9]\d?|0)\.(1\d{0,2}|2(?:[0-4]\d{0,1}|[6789]|5[0-5]?)?|[3-9]\d?|0)\.(1\d{0,2}|2(?:[0-4]\d{0,1}|[6789]|5[0-5]?)?|[3-9]\d?|0)\.(1\d{0,2}|2(?:[0-4]\d{0,1}|[6789]|5[0-5]?)?|[3-9]\d?|0)(\/(?:[012]\d?|3[012]?|[456789])){0,1}$/; var regexAllIp = /(1\d{0,2}|2(?:[0-4]\d{0,1}|[6789]|5[0-5]?)?|[3-9]\d?|0)\.(1\d{0,2}|2(?:[0-4]\d{0,1}|[6789]|5[0-5]?)?|[3-9]\d?|0)\.(1\d{0,2}|2(?:[0-4]\d{0,1}|[6789]|5[0-5]?)?|[3-9]\d?|0)\.(1\d{0,2}|2(?:[0-4]\d{0,1}|[6789]|5[0-5]?)?|[3-9]\d?|0)(\/(?:[012]\d?|3[012]?|[456789])){0,1}/g; var regexIPV6 = /s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:)))(%.+)?s*/g; var headReceived = MailHops.message.headers['received'] || []; var headDate = MailHops.message.headers['date'] ? MailHops.message.headers['date'][0] : ''; var headXReceived = MailHops.message.headers['x-received'] ? MailHops.message.headers['x-received'][0] : ''; var headXOrigIP = MailHops.message.headers['x-originating-ip'] ? MailHops.message.headers['x-originating-ip'][0] : ''; // auth box var headXMailer = MailHops.message.headers['x-mailer'] ? MailHops.message.headers['x-mailer'][0] : ''; var headUserAgent = MailHops.message.headers['user-agent'] ? MailHops.message.headers['user-agent'][0] : ''; var headXMimeOLE = MailHops.message.headers['x-mimeole'] ? MailHops.message.headers['x-mimeole'][0] : ''; var headReceivedSPF = MailHops.message.headers['received-spf'] ? MailHops.message.headers['received-spf'][0] : ''; var headAuth = MailHops.message.headers['authentication-results'] ? MailHops.message.headers['authentication-results'][0] : ''; var headListUnsubscribe = MailHops.message.headers['list-unsubscribe'] ? MailHops.message.headers['list-unsubscribe'][0] : ''; var all_ips = new Array(); var rline = '',firstDate=headDate,lastDate; //empty secure and time MailHops.message.secure = []; MailHops.message.time = null; MailHops.message.auth = MailHops.auth( headXMailer, headUserAgent, headXMimeOLE, headAuth, headReceivedSPF ); //loop through the received headers and parse for IP addresses if (Boolean(headReceived)){ var received_ips = new Array(); for( var h=0; h < headReceived.length; h++ ) { //build the received line by concat until semi-colon ; date/time rline += headReceived[h]; if(headReceived[h].indexOf(';') === -1) continue; // first and last dates are used to calculate time traveled if(rline.indexOf(';') !== -1){ if(!firstDate) firstDate = rline.substring(rline.indexOf(';')+1).trim(); if(!lastDate) lastDate = rline.substring(rline.indexOf(';')+1).trim(); } // IPV6 check rline = rline.replace(/\[IPv6\:/g,'['); if(rline.match(regexIPV6)){ all_ips.unshift( rline.match(regexIPV6)[0] ); //reset the line rline=''; continue; } // parse IPs out of Received line received_ips = rline.match(regexAllIp); //continue if no IPs found if(!received_ips){ //reset the line rline=''; continue; } //get unique IPs for each Received header received_ips = received_ips.filter(function(item, pos) { return received_ips.indexOf(item) === pos; }); for( var r=received_ips.length; r >= 0 ; r-- ){ if(regexIp.test(received_ips[r]) && MailHops.testIP(received_ips[r],rline)){ all_ips.unshift( received_ips[r] ); } } //reset the line rline=''; } } // parse dates if(firstDate && firstDate.indexOf('(') !==- 1) firstDate = firstDate.substring(0,firstDate.indexOf('(')).trim(); if(lastDate && lastDate.indexOf('(') !== -1) lastDate = lastDate.substring(0,lastDate.indexOf('(')).trim(); if(firstDate && lastDate){ try { firstDate = new Date(firstDate); lastDate = new Date(lastDate); MailHops.message.time = lastDate - firstDate; } catch(e){ MailHops.LOG('travel dates parse Error: '+JSON.stringify(e)); MailHops.message.time = null; } } else { MailHops.message.time = null; } //get the originating IP address if(Boolean(headXOrigIP)){ headXOrigIP = headXOrigIP.replace(/\[IPv6\:/g,'['); //IPV6 check if(headXOrigIP.match(regexIPV6)){ var ip = headXOrigIP.match(regexIPV6) if(Boolean(ip) && ip.length && all_ips.indexOf(ip[0])==-1) all_ips.unshift( ip[0] ); } else { var ip = headXOrigIP.match(regexAllIp); if(Boolean(ip) && ip.length && all_ips.indexOf(ip[0])==-1) all_ips.unshift( ip[0] ); } } if ( all_ips.length ){ MailHops.lookupRoute ( all_ips ) ; } else { MailHops.clear(); } }; //another ip check, dates will throw off the regex MailHops.testIP = function(ip,header){ var validIP = true; try { var firstchar = header.substring(header.indexOf(ip)-1); firstchar = firstchar.substring(0,1); var lastchar = header.substring((header.indexOf(ip)+ip.length)); lastchar = lastchar.substring(0,1); if(firstchar.match(/\.|\d|\-/) || lastchar.match(/\.|\d|\-/) || ( firstchar == '?' && lastchar == '?' ) || (firstchar == ':' || lastchar == ':') || lastchar == ';' || header.toLowerCase().indexOf(' id '+ip) !== -1 || parseInt(ip.substring(0,ip.indexOf('.'))) >= 240 //IANA-RESERVED ){ //only if there is one instance of this IP if(header.indexOf(ip) == header.lastIndexOf(ip)) validIP = false; } else if(header.indexOf('using SSL') !== -1 || header.indexOf('using TLS') !== -1 || header.indexOf('version=TLSv1/SSLv3') !== -1 ){ //check if this IP was part of a secure transmission MailHops.message.secure.push(ip); } } catch(e) { MailHops.LOG('testIP Error: '+JSON.stringify(e)); } return validIP; }; MailHops.clear = function () { MailHops.message.sender = { title: 'Local', countryCode: '', icon: '/images/local.png' }; browser.messageDisplayAction.setIcon({ path: MailHops.message.sender.icon }); browser.messageDisplayAction.setTitle({ title: MailHops.message.sender.title }); if (browser.mailHopsUI) browser.mailHopsUI.insertBefore("", MailHops.message.sender.icon, MailHops.message.sender.title, "countryIcon", "expandedHeaders2"); } MailHops.error = function(status, data){ MailHops.message.sender = { title: (data && data.error && data.error.message) ? data && data.error.message : 'Service Unavailable', countryCode: '', icon: '/images/auth/error.png' }; browser.messageDisplayAction.setIcon({ path: MailHops.message.sender.icon }); browser.messageDisplayAction.setTitle({ title: MailHops.message.sender.title }); if (browser.mailHopsUI) browser.mailHopsUI.insertBefore("", MailHops.message.sender.icon, MailHops.message.sender.title, "countryIcon", "expandedHeaders2"); } MailHops.auth = function (header_xmailer, header_useragent, header_xmimeole, header_auth, header_spf) { let auth = []; //SPF if(header_spf){ header_spf = header_spf.replace(/^\s+/, ""); auth.push({ type: 'SPF', icon: '/images/auth/' + headerSPFArr[0] + '.png', copy: header_spf + '\n' + mailHopsUtils.spf(headerSPFArr[0]) }); } //Authentication-Results //http://tools.ietf.org/html/rfc5451 if(header_auth){ var headerAuthArr=header_auth.split(';'); var dkim_result; var spf_result; for(var h=0;h 10000){ messenger.messages.update(MailHops.message.id, { 'junk': true }); MailHops.LOG( "Junk: Travel time match" ); } } catch(e){ MailHops.LOG("Error adding CountryCode tag: " + e); } }; MailHops.init();