├── .gitignore ├── images ├── send-page-16.png ├── send-page-48.png ├── send-page-128.png └── send-page.svg ├── .project ├── manifest.json ├── LICENSE ├── options.js ├── options.html ├── TermsOfUse.md ├── README.md └── sendpage.js /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | -------------------------------------------------------------------------------- /images/send-page-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stadler/SendPage/HEAD/images/send-page-16.png -------------------------------------------------------------------------------- /images/send-page-48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stadler/SendPage/HEAD/images/send-page-48.png -------------------------------------------------------------------------------- /images/send-page-128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stadler/SendPage/HEAD/images/send-page-128.png -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | SendPage 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Send Page", 3 | "description": "Allows you to easily send the url of a page, link, image or video per mail.", 4 | "version": "3.0", 5 | "manifest_version": 3, 6 | "author": "Jacques Stadler", 7 | "homepage_url": "https://github.com/stadler/SendPage", 8 | 9 | "icons": { 10 | "16": "images/send-page-16.png", 11 | "48": "images/send-page-48.png", 12 | "128": "images/send-page-128.png" 13 | }, 14 | 15 | "options_ui": { 16 | "page": "options.html" 17 | }, 18 | 19 | "background": { 20 | "service_worker": "sendpage.js" 21 | }, 22 | "permissions": ["contextMenus", "storage"] 23 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | Copyright (c) 2012 Jacques Stadler 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 5 | 6 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 7 | 8 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /options.js: -------------------------------------------------------------------------------- 1 | function save_options() { 2 | chrome.storage.sync.set( 3 | { 4 | mailClientType: document.getElementById('mailClientType').value, 5 | bodyPrefix: document.getElementById('bodyPrefix').value, 6 | bodyPostfix: document.getElementById('bodyPostfix').value, 7 | }, 8 | updateStatus); 9 | } 10 | 11 | function updateStatus() { 12 | var status = document.getElementById('status'); 13 | var popupTimeInMs = 750; 14 | status.textContent = 'Options saved.'; 15 | setTimeout(function() { 16 | status.textContent = ''; 17 | }, popupTimeInMs); 18 | } 19 | 20 | function restore_options() { 21 | chrome.storage.sync.get( 22 | { 23 | // defaults 24 | mailClientType: 'web', 25 | bodyPrefix: '', 26 | bodyPostfix: '' 27 | }, 28 | function(items) { 29 | document.getElementById('mailClientType').value = items.mailClientType; 30 | document.getElementById('bodyPrefix').value = items.bodyPrefix; 31 | document.getElementById('bodyPostfix').value = items.bodyPostfix; 32 | }); 33 | } 34 | document.addEventListener('DOMContentLoaded', restore_options); 35 | document.getElementById('save').addEventListener('click', save_options); -------------------------------------------------------------------------------- /options.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Send Page Options 5 | 12 | 13 | 14 | 15 |
16 |

Mail Client Type

17 | What type of mail client do you use?
18 | If you are using a web mail client the tab will be kept open for the web mail client.
19 | If you are using a local mail client, which is registered to handle mailto links, a new tab will quickly appear 20 | and disappear again after having opened the mail client. 21 |

22 | 28 |

29 |
30 | 31 |
32 |

Message Body Template

33 | By default the generated Mail will only contain the page title as subject and the url to send as text. 34 | But if you want you may define text that will appear before and after the URL. 35 |

36 | Text before URL:
37 |
38 | Text after URL:
39 | 40 |

41 |
42 | 43 |
44 | 45 |
46 | 47 |
48 | 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /TermsOfUse.md: -------------------------------------------------------------------------------- 1 | # Datenschutzerklärung 2 | ## Allgemeines / Einleitung 3 | Gestützt auf Artikel 13 der Schweizerischen Bundesverfassung und die datenschutzrechtlichen Bestimmungen des Bundes (Datenschutzgesetz, DSG) hat jede Person Anspruch auf Schutz ihrer Privatsphäre sowie auf Schutz vor Missbrauch ihrer persönlichen Daten. Die Betreiber dieser Extension nehmen den Schutz Ihrer persönlichen Daten sehr ernst. Wir behandeln Ihre personenbezogenen Daten vertraulich und entsprechend der gesetzlichen Datenschutzvorschriften sowie dieser Datenschutzerklärung. 4 | 5 | Wir weisen darauf hin, dass die Datenübertragung im Internet (z.B. bei der Kommunikation per E-Mail) Sicherheitslücken aufweisen kann. Ein lückenloser Schutz der Daten vor dem Zugriff durch Dritte ist nicht möglich. 6 | 7 | ## Haftungsausschluss 8 | Alle Angaben in dieser Extension wurden sorgfältig geprüft. Wir sind bemüht, dafür Sorge zu tragen, dass die von uns bereitgestellten Informationen aktuell, richtig und vollständig sind. Dennoch ist das Auftreten von Fehlern nicht völlig auszuschliessen, so dass wir für die Vollständigkeit, Richtigkeit und Aktualität der Informationen keine Gewähr übernehmen können. Haftungsansprüche, die sich auf Schäden materieller oder ideeller Art beziehen, welche durch die Nutzung oder Nichtnutzung der dargebotenen Informationen bzw. durch die Nutzung fehlerhafter und unvollständiger Informationen verursacht wurden, sind grundsätzlich ausgeschlossen. 9 | Der Herausgeber kann Texte nach eigenem Ermessen und ohne vorherige Ankündigung ändern oder löschen und ist nicht dazu verpflichtet, die Inhalte dieser Extension zu aktualisieren. Die Nutzung dieser Extension bzw. der Zugang zu ihr erfolgt auf eigenes Risiko des Nutzers. Der Herausgeber, seine Kunden oder Partner sind nicht verantwortlich für Schäden, wie z.B. direkte, indirekte, zufällige oder Folgeschäden, die angeblich durch den Besuch dieser Extension verursacht wurden und übernehmen folglich keine Haftung für solche Schäden. 10 | Der Herausgeber übernimmt auch keine Verantwortung oder Haftung für den Inhalt und die Verfügbarkeit von Websites Dritter, die über externe Links von dieser Extension aus erreicht werden können. Für den Inhalt der verlinkten Seiten sind ausschliesslich deren Betreiber verantwortlich. Der Herausgeber distanziert sich daher ausdrücklich von allen fremden Inhalten, die möglicherweise straf- oder haftungsrechtlich relevant sind oder gegen die guten Sitten verstossen. 11 | 12 | ## Änderungen 13 | Wir können diese Datenschutzrichtlinie jederzeit ohne vorherige Ankündigung ändern. Es gilt die jeweils aktuelle, auf unserer Extension veröffentlichte Fassung. 14 | 15 | ## Haftungsausschluss 16 | Der Autor übernimmt keine Gewähr für die Richtigkeit, Genauigkeit, Aktualität, Zuverlässigkeit und Vollständigkeit der Informationen. 17 | Haftungsansprüche gegen den Autor wegen Schäden materieller oder immaterieller Art, die aus dem Zugriff oder der Nutzung bzw. Nichtnutzung der veröffentlichten Informationen, durch Missbrauch der Verbindung oder durch technische Störungen entstanden sind, werden ausgeschlossen. 18 | 19 | Alle Angebote sind freibleibend. Der Autor behält es sich ausdrücklich vor, Teile der Extension oder das gesamte Angebot ohne gesonderte Ankündigung zu verändern, zu ergänzen, zu löschen oder die Veröffentlichung zeitweise oder endgültig einzustellen. 20 | 21 | Quelle: BrainBox Solutions -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | SendPage 2 | ======== 3 | 4 | SendPage is a simple chromium extension to send a page to a E-Mail recipient 5 | with your default local or web mail client. 6 | 7 | It will actually just open a mailto URI so you need to have a (local or web) E-Mail client registered to handle mailto URIs. 8 | 9 | Binaries 10 | -------- 11 | Download Binaries from Chrome Web Store (also for Brave, and other Chromium based Browsers): 12 | https://chrome.google.com/webstore/detail/higemadklcnjhjpgcbnnbpgeeippjjcp 13 | 14 | Or the Microsoft Edge-Add-Ons Store: 15 | https://microsoftedge.microsoft.com/addons/detail/send-page/akohgmamjjpdagmohoecbmgiejkplkfb 16 | 17 | Sources 18 | ------- 19 | Download Sources from GitHub: 20 | https://github.com/stadler/SendPage 21 | 22 | Bugs 23 | ---- 24 | Did you find a bug? Please report them here: 25 | https://github.com/stadler/SendPage/issues 26 | 27 | Support 28 | -------- 29 | Do you like this Extension? 30 | Please give this Project a Star on GitHub if you like it. 31 | 32 | Changelog 33 | --------- 34 | 35 | * 3.0 36 | * Upgrade to manifest version 3 37 | * Add terms of use 38 | * Make it clear that also Brave and other Chromium based browsers are supported. 39 | * 2.3 40 | * Fixed #15: URI is is undefined when using button beside url 41 | * Provide better log output for debugging 42 | * 2.2 43 | * Fixed #14: email end text appended to URI 44 | * Fixed type error 45 | * 2.1 46 | * Remove unused 'tabs' permission 47 | * Make sure that we never have undefined appear in the message body 48 | * Open the options page after install 49 | * If sending a link, use the text of the link as subject instead of the title of the page that is containing the link. 50 | * 2.0 51 | * Replace usage of tab.update by tab.create as tabs cannot be properly updated anymore. 52 | * Reintroduced options page 53 | * Allow to define Mail text 54 | * 1.8 - Replaced word encoding by default encodeURIComponent and use document encoding for subject line 55 | * 1.7 56 | * Fix encoding issue in mail subject 57 | * Allow to send the url of links, images and videos 58 | * Removed options page 59 | * 1.6 - Show the correct URL for PDFs that are opened in the built in pdf viewer 60 | * 1.5 - Added option to disable word encoding of subject for low quality mail clients that don't support it (e.g. outlook) 61 | * 1.4 - Made sure that the subject has the correct encoding 62 | * 1.3 - Make SendPage 'manifest_version' 2 compatible and proper title escaping 63 | * 1.2 - Support for Webmail and Options to tune close timeout 64 | * 1.1 - Proper escaping of ampersands in URLs 65 | * 1.0 - Small adaptions 66 | * 0.1 - Initial release 67 | 68 | Troubleshoot 69 | ------------ 70 | ### Nothing happens when I click "Send Page..." 71 | For the extension to work a default mail application ("mailto:" protocol handler) must be registered on your system. If this is the case you should be able to click on [this Link](mailto:test@example.com?subject=The%20Subject&body=The%20Body) to open your Mail client. 72 | 73 | ### It does not behave correctly with Local or Web E-Mail Clients. Why? 74 | Checkout the Options of the extension. There you can configure if your Mail client is a Web or Local E-Mail Client which may help. 75 | Also you can define Texts that are to be shown in the E-Mail content by default. 76 | 77 | ### It still does not do what I expect. What can I do? 78 | On the chrome extensions page (chrome://extensions/) you can enable the developer mode and open the background page. 79 | It will provide you with logging and debugging capabilities. If you discovered an error please report it here. 80 | -------------------------------------------------------------------------------- /sendpage.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Registers a context menu entry that upon click, opens a mailto uri containing page title and url of the given context. 3 | */ 4 | 5 | firstTimeOptionsPopup(); 6 | console.log("Creating SendPage context menu entry..."); 7 | var id = chrome.contextMenus.create({ "id": "send-page-context-menu", "type": "normal", "title": "Send this page...", "contexts": ["all"]}); 8 | chrome.contextMenus.onClicked.addListener(fetchOptions); 9 | console.log("SendPage context menu entry created."); 10 | 11 | 12 | function firstTimeOptionsPopup() { 13 | chrome.storage.local.get(['wasAlreadyStarted']).then(wasStarted => { 14 | if (wasStarted) { 15 | return; 16 | } else { 17 | chrome.storage.local.set({'wasAlreadyStarted': true}); 18 | chrome.runtime.openOptionsPage(optionsPageOpened); 19 | } 20 | }); 21 | } 22 | 23 | function optionsPageOpened() { 24 | console.log("Options page opened...") 25 | } 26 | 27 | function fetchOptions(info, tab) { 28 | chrome.storage.sync.get(['bodyPrefix', 'bodyPostfix', 'mailClientType'], function (options) { 29 | sendMail(info, tab, options); 30 | }); 31 | } 32 | 33 | function sendMail(info, tab, options) { 34 | var subjectAndUrl = determineSubjectAndUrl(info, tab); 35 | 36 | var subject = encodeURIComponent(subjectAndUrl.subject); 37 | console.log("Sending Mail with Subject: " + subject); 38 | 39 | var bodyPrefix = safeGetOptionWithNewline("", options.bodyPrefix, "\n"); 40 | var bodyPostfix = safeGetOptionWithNewline("\n", options.bodyPostfix, ""); 41 | var body = encodeURIComponent(bodyPrefix + subjectAndUrl.url + bodyPostfix); 42 | console.log("Sending Mail with Body: " + body); 43 | 44 | var mailToUrl = "mailto:?subject=" + subject + "&body=" + body; 45 | console.log("The MailTo URL=\n'" + mailToUrl + "'"); 46 | 47 | if (options.mailClientType === 'local') { 48 | // Only create new tab to close it after mailto handler opened 49 | chrome.tabs.create({ url: mailToUrl, active: false }, tabCreatedAndCloseCallback); 50 | } else { 51 | // Keep tab opened 52 | chrome.tabs.create({ url: mailToUrl, active: true }, tabCreatedCallback); 53 | } 54 | } 55 | 56 | function safeGetOptionWithNewline(prefix, option, postfix) { 57 | return (variableExists(option) && option.length != 0) ? prefix + option + postfix : ""; 58 | } 59 | 60 | function tabCreatedCallback(tab) { 61 | console.log("New WebMail Tab created..."); 62 | } 63 | 64 | function tabCreatedAndCloseCallback(tab) { 65 | var timeoutInMs = 500; 66 | console.log("New Tab created and will be closed again in " + timeoutInMs + "ms ..."); 67 | setTimeout( 68 | function () { 69 | console.log("Closing new tab again...") 70 | chrome.tabs.remove(tab.id); 71 | }, 72 | timeoutInMs); 73 | } 74 | 75 | function determineSubjectAndUrl(info, tab) { 76 | var result = { subject: '', url: '' }; 77 | console.log("Determine Subject and URI. info: " + JSON.stringify(info) + ", tab: " + JSON.stringify(tab)); 78 | if (variableExists(info.linkUrl)) { 79 | // Use the link url if the user clicked a link 80 | result.subject = variableExists(info.selectionText) ? info.selectionText : tab.title; 81 | result.url = info.linkUrl; 82 | } else if (variableExists(info.srcUrl)) { 83 | // For Images or other stuff containing src attributes 84 | result.subject = tab.title; 85 | result.url = info.srcUrl; 86 | } else if (variableExists(info.pageUrl) && info.pageUrl.startsWith("chrome-extension://")) { 87 | // For PDFs and other extensions there is no pageUrl so the srcUrl is better suited 88 | result.subject = tab.title; 89 | result.url = info.srcUrl; 90 | } else if (variableExists(info.pageUrl)) { 91 | // Use page url if possible 92 | result.subject = tab.title; 93 | result.url = info.pageUrl; 94 | } else { 95 | // Normally send the url of the page 96 | result.subject = tab.title; 97 | result.url = tab.url; 98 | } 99 | return result; 100 | } 101 | 102 | function variableExists(myVar) { 103 | return typeof myVar !== "undefined"; 104 | } 105 | -------------------------------------------------------------------------------- /images/send-page.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 19 | 21 | 32 | 35 | 39 | 43 | 44 | 55 | 57 | 61 | 65 | 69 | 70 | 80 | 82 | 86 | 90 | 91 | 93 | 97 | 101 | 102 | 104 | 108 | 112 | 113 | 115 | 119 | 123 | 124 | 126 | 130 | 134 | 135 | 137 | 141 | 145 | 146 | 148 | 152 | 156 | 157 | 159 | 163 | 167 | 168 | 170 | 174 | 178 | 179 | 182 | 186 | 190 | 191 | 202 | 212 | 222 | 232 | 242 | 252 | 262 | 272 | 282 | 283 | 301 | 303 | 304 | 306 | image/svg+xml 307 | 309 | Mail 310 | 311 | 312 | Jakub Steiner 313 | 314 | 315 | 316 | 317 | Andreas Nilsson 318 | 319 | 320 | 322 | 323 | 324 | mail 325 | e-mail 326 | MUA 327 | 328 | 329 | 330 | 332 | 334 | 336 | 338 | 340 | 342 | 344 | 345 | 346 | 347 | 351 | 354 | 361 | 366 | 371 | 372 | 377 | 382 | 387 | 392 | 397 | 402 | 407 | 412 | 417 | 422 | 427 | 432 | 437 | 438 | 439 | --------------------------------------------------------------------------------