diff --git a/CHANGELOG.md b/CHANGELOG.md index 6edc4aa..fb5f422 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,24 +1,38 @@ # Change Log -## [1.0.8] - 2016-5-25 +## 2.0.0 - 2016-9-10 + +### Added +- MailHops API v2 +- MailHops API key for v2 +- Security section in preferences +- Tag and mark as junk by CountryCode +- Time Traveled, total time it took for the email to reach you + +### Fixed +- Bug if multiple IPs exist in one Received header +- Check for API response HTTP status code + + +## 1.0.8 - 2016-5-25 ### Added - Styles Updates - SSL Default -## [1.0.7] - 2015-11-13 +## 1.0.7 - 2015-11-13 ### Fixed - Check that IP address starts with digit less than 240 (IANA-RESERVED) -## [1.0.6] - 2015-11-12 +## 1.0.6 - 2015-11-12 ### Fixed - Missing try/catch around JSON.parse -## [1.0.3] - 2015-09-18 +## 1.0.3 - 2015-09-18 ### Added - Map provider in preferences @@ -28,7 +42,7 @@ - Display if only city in response -## [1.0.1] - 2015-06-10 +## 1.0.1 - 2015-06-10 ### Added - Context.IO sponsored message, build something awesome with their API! @@ -37,7 +51,7 @@ - Secure message parsing -## [1.0.0] - 2015-05-31 +## 1.0.0 - 2015-05-31 ### Changed - Combined Thunderbird and Postbox code into one plugin @@ -45,7 +59,7 @@ - Fix mismatch IP from Microsoft SMTP id in received header -## [0.9.0] - 2015-05-30 +## 0.9.0 - 2015-05-30 ### Changed - Update map style and size - Update logo @@ -57,4 +71,4 @@ - Forecast.IO, gets the weather from the sender, API key needs to be added in preferences ### Fixed -- Fix mismatch IP from Microsoft SMTP id in received header +- Fix mismatch IP from Microsoft SMTP id in Received header diff --git a/README.md b/README.md index 5a95923..b5f090b 100644 --- a/README.md +++ b/README.md @@ -3,26 +3,26 @@ MailHops logo -MailHops is an email route API. It does two things: +MailHops is an email route API. It does a few things: 1. Returns a route an email took based on the Received header IP addresses -2. Returns a map an email took based on the Received header IP addresses +1. Returns a map an email took based on the Received header IP addresses +1. Shows the weather of the sender when you provide a Forecastio API key +1. Will tag and mark messages as Junk if from a Country you don't like +1. Performs DNSBL check on messages -The route will contain DNSBL lookup results, hostname lookup results and What3Words geo locations. - -1. Edit files -2. Run [build.sh](build.sh) script -3. Open Postbox and goto Tools->Add-ons and "Install Add-on From File..." -4. Choose mailhops.xpi from build script +### Editing the code +1. After you make changes you can run the [build.sh](build.sh) script +1. Open Postbox or Thunderbird and goto Tools->Add-ons and "Install Add-on From File..." +1. Choose mailhops.xpi from build script ```sh $ chmod +x build.sh $ ./build.sh ``` -## API -Host your own API -- [API](https://github.com/avantassel/mailhops-api) +### MailHops API +- [https://github.com/mailhops](https://github.com/mailhops) -## Plugins -- [Download](https://addons.mozilla.org/en-US/thunderbird/addon/mailhops/) +### Download +- [Download this plugin from Mozilla](https://addons.mozilla.org/en-US/thunderbird/addon/mailhops/) diff --git a/chrome/content/mailhops.js b/chrome/content/mailhops.js index 91c8863..b0eddcd 100644 --- a/chrome/content/mailhops.js +++ b/chrome/content/mailhops.js @@ -20,6 +20,7 @@ var mailHops = }, message: { secure:[] + ,time: 0 } }; @@ -160,8 +161,9 @@ mailHops.getRoute = function(){ // http://regexlib.com/REDetails.aspx?regexp_id=2919 var regexIPV6 = /(::|(([a-fA-F0-9]{1,4}):){7}(([a-fA-F0-9]{1,4}))|(:(:([a-fA-F0-9]{1,4})){1,6})|((([a-fA-F0-9]{1,4}):){1,6}:)|((([a-fA-F0-9]{1,4}):)(:([a-fA-F0-9]{1,4})){1,6})|((([a-fA-F0-9]{1,4}):){2}(:([a-fA-F0-9]{1,4})){1,5})|((([a-fA-F0-9]{1,4}):){3}(:([a-fA-F0-9]{1,4})){1,4})|((([a-fA-F0-9]{1,4}):){4}(:([a-fA-F0-9]{1,4})){1,3})|((([a-fA-F0-9]{1,4}):){5}(:([a-fA-F0-9]{1,4})){1,2}))/; - var headReceived = mailHops.headers.extractHeader ( "Received" , true ) ; - var headXOrigIP = mailHops.headers.extractHeader ( "X-Originating-IP" , false ) ; + var headReceived = mailHops.headers.extractHeader ( "Received" , true ); + var headXReceived = mailHops.headers.extractHeader ( "X-Received" , false ); + var headXOrigIP = mailHops.headers.extractHeader ( "X-Originating-IP" , false ); //auth box var headXMailer = (mailHops.options.show_auth && mailHops.options.show_mailer) ? mailHops.headers.extractHeader ( "X-Mailer" , false ) : null; var headUserAgent = (mailHops.options.show_auth && mailHops.options.show_mailer) ? mailHops.headers.extractHeader ( "User-Agent" , false ) : null; @@ -172,9 +174,10 @@ mailHops.getRoute = function(){ var headListUnsubscribe = mailHops.options.show_lists ? mailHops.headers.extractHeader ( "List-Unsubscribe" , false ) : null; var all_ips = new Array(); - var rline = ''; - //empty secure + var rline = '',firstDate,lastDate; + //empty secure and time mailHops.message.secure = []; + mailHops.message.time = 0; if(mailHops.options.show_lists){ mailHopsDisplay.lists( headListUnsubscribe ); @@ -193,6 +196,15 @@ mailHops.getRoute = function(){ rline += headReceivedArr[h]; if(headReceivedArr[h].indexOf(';')==-1) continue; + + // first and last dates are used to calculate time Traveled + if(rline.indexOf(';')!==-1){ + if(!lastDate) + lastDate = rline.substring(rline.indexOf(';')+1).trim(); + firstDate = rline.substring(rline.indexOf(';')+1).trim(); + } + + // parse IPs out of Received line received_ips = rline.match(regexAllIp); //continue if no IPs found if(!received_ips) @@ -211,6 +223,20 @@ mailHops.getRoute = function(){ } } + // parse dates + if(firstDate.indexOf('(')!==-1) + firstDate = firstDate.substring(0,firstDate.indexOf('(')).trim(); + if(lastDate.indexOf('(')!==-1) + lastDate = lastDate.substring(0,lastDate.indexOf('(')).trim(); + + try { + firstDate = new Date(firstDate); + lastDate = new Date(lastDate); + mailHops.message.time = lastDate-firstDate; + } catch(e){ + mailHops.LOG('parse time traveled dates Error: '+JSON.stringify(e)); + } + //get the originating IP address if(!!headXOrigIP){ //remove brackets @@ -333,7 +359,9 @@ mailHops.lookupRoute = function(header_route){ if(mailHops.options.fkey != '') lookupURL += '&fkey='+mailHops.options.fkey; - + if(mailHops.message.time > 0) + lookupURL += '&t='+mailHops.message.time; + //check for cache var cached_results = mailHops.getResults(); diff --git a/chrome/content/pb-overlay.js b/chrome/content/pb-overlay.js index caafdaa..fe382ba 100644 --- a/chrome/content/pb-overlay.js +++ b/chrome/content/pb-overlay.js @@ -430,14 +430,24 @@ var mailHopsDisplay = if(response.distance){ if(this.options.unit=='km' && response.distance.kilometers > 0) - distanceText =' ( '+mailHopsUtils.addCommas(Math.round(response.distance.kilometers))+' km traveled )'; + distanceText = mailHopsUtils.addCommas(Math.round(response.distance.kilometers))+' km traveled'; else if(response.distance.miles > 0) - distanceText =' ( '+mailHopsUtils.addCommas(Math.round(response.distance.miles))+' mi traveled )'; + distanceText = mailHopsUtils.addCommas(Math.round(response.distance.miles))+' mi traveled'; } else if(displayText=='') displayText = ' Local message.'; } + if(message.time>0){ + message.time = message.time/1000; + if(message.time<60) + distanceText += ' in '+message.time+' sec.'; + else if(message.time<3600) //something is wrong if it takes this long + distanceText += ' in '+Math.round(message.time/60)+' min.'; + else //something is wrong if it takes this long + distanceText += ' in '+Math.round(message.time/60/60)+' hrs.'; + } + if(header_route) this.resultMapLink.setAttribute("data-route", header_route); else @@ -445,12 +455,10 @@ var mailHopsDisplay = this.resultTextDataPane.style.backgroundImage = 'url('+image+')'; this.resultTextDataPane.value = displayText; - this.resultTextDataPane.setAttribute('tooltiptext',displayText+' '+distanceText); - + if(distanceText){ - this.resultTextDataPane2.style.display = 'block'; - this.resultTextDataPane2.value = distanceText; - this.resultTextDataPane2.setAttribute('tooltiptext',displayText+' '+distanceText); + this.resultTextDataPane2.style.display = 'block'; + this.resultTextDataPane2.value = ' ( '+distanceText+' )'; } else { this.resultTextDataPane2.style.display = 'none'; } diff --git a/chrome/content/tb-overlay.js b/chrome/content/tb-overlay.js index e2ce590..b4572c3 100644 --- a/chrome/content/tb-overlay.js +++ b/chrome/content/tb-overlay.js @@ -16,17 +16,17 @@ var mailHopsDisplay = this.options = options; - this.container = document.getElementById ( "mailhopsBox" ) ; - this.resultBox = document.getElementById ( "mailhopsResult" ) ; - this.resultText = document.getElementById ( "mailhopsResultText" ) ; - this.mailhopsResultWeather = document.getElementById ( "mailhopsResultWeather" ) ; - this.resultDetails = document.getElementById ( "mailhopsDataPaneDetails"); - this.mapLink = document.getElementById ( "mailhopsMapLink"); + this.container = document.getElementById("mailhopsBox"); + this.resultBox = document.getElementById("mailhopsResult"); + this.resultText = document.getElementById("mailhopsResultText"); + this.mailhopsResultWeather = document.getElementById("mailhopsResultWeather"); + this.resultDetails = document.getElementById("mailhopsDataPaneDetails"); + this.mapLink = document.getElementById("mailhopsMapLink"); //auth - this.mailhopsDataPaneSPF = document.getElementById ( "mailhopsDataPaneSPF"); - this.mailhopsDataPaneDKIM = document.getElementById ( "mailhopsDataPaneDKIM"); - this.mailhopsDataPaneMailer = document.getElementById ( "mailhopsDataPaneMailer"); - this.mailhopsDataPaneDNSBL = document.getElementById ( "mailhopsDataPaneDNSBL"); + this.mailhopsDataPaneSPF = document.getElementById("mailhopsDataPaneSPF"); + this.mailhopsDataPaneDKIM = document.getElementById("mailhopsDataPaneDKIM"); + this.mailhopsDataPaneMailer = document.getElementById("mailhopsDataPaneMailer"); + this.mailhopsDataPaneDNSBL = document.getElementById("mailhopsDataPaneDNSBL"); //event listner for route click to launch map this.mailhopsDataPaneDNSBL.addEventListener("click", function () { @@ -272,41 +272,51 @@ var mailHopsDisplay = } //set weather of sender - if(weather){ - this.mailhopsResultWeather.style.display = 'block'; - this.mailhopsResultWeather.setAttribute('tooltiptext',new Date(weather.time*1000)); - this.mailhopsResultWeather.value = weather.summary+' '+Math.round(weather.temp)+'\u00B0'; - this.mailhopsResultWeather.style.backgroundImage = 'url('+mailHopsUtils.getWeatherIcon(weather.icon)+')'; - } - - if(image.indexOf('local')!=-1) { - displayText = ' Local message.'; - } else { - - if(!!first){ - if(!!first.city && !!first.state) - displayText = first.city+', '+first.state; - else if(!!first.city) - displayText = first.city+', '+first.countryCode; - else if(!!first.countryName) - displayText = first.countryName; + if(weather){ + this.mailhopsResultWeather.style.display = 'block'; + this.mailhopsResultWeather.setAttribute('tooltiptext',new Date(weather.time*1000)); + this.mailhopsResultWeather.value = weather.summary+' '+Math.round(weather.temp)+'\u00B0'; + this.mailhopsResultWeather.style.backgroundImage = 'url('+mailHopsUtils.getWeatherIcon(weather.icon)+')'; } - if(response.distance){ - if(this.options.unit=='km' && response.distance.kilometers > 0) - distanceText =' ( '+mailHopsUtils.addCommas(Math.round(response.distance.kilometers))+' km traveled )'; - else if(response.distance.miles > 0) - distanceText =' ( '+mailHopsUtils.addCommas(Math.round(response.distance.miles))+' mi traveled )'; - } else if(displayText=='') + if(image.indexOf('local')!=-1) { displayText = ' Local message.'; - } + } else { - if(header_route) + if(!!first){ + if(!!first.city && !!first.state) + displayText = first.city+', '+first.state; + else if(!!first.city) + displayText = first.city+', '+first.countryCode; + else if(!!first.countryName) + displayText = first.countryName; + } + + if(response.distance){ + if(this.options.unit=='km' && response.distance.kilometers > 0) + distanceText = mailHopsUtils.addCommas(Math.round(response.distance.kilometers))+' km traveled'; + else if(response.distance.miles > 0) + distanceText = mailHopsUtils.addCommas(Math.round(response.distance.miles))+' mi traveled'; + } else if(displayText=='') + displayText = ' Local message.'; + } + + if(message.time>0){ + message.time = message.time/1000; + if(message.time<60) + distanceText += ' in '+message.time+' sec.'; + else if(message.time<3600) //something is wrong if it takes this long + distanceText += ' in '+Math.round(message.time/60)+' min.'; + else //something is wrong if it takes this long + distanceText += ' in '+Math.round(message.time/60/60)+' hrs.'; + } + + if(header_route) this.mapLink.setAttribute("data-route", header_route); else - this.mapLink.removeAttribute("data-route"); + this.mapLink.removeAttribute("data-route"); - this.resultText.setAttribute('value', displayText+' '+distanceText); + this.resultText.setAttribute('value', displayText+' ( '+distanceText+' )'); this.resultText.style.backgroundImage = 'url('+image+')'; }//end route }; diff --git a/chrome/content/tb-overlay.xul b/chrome/content/tb-overlay.xul index da232fc..f969862 100644 --- a/chrome/content/tb-overlay.xul +++ b/chrome/content/tb-overlay.xul @@ -16,7 +16,7 @@ - +