Curiosity is bliss    Archive    Feed    About    Search

Julien Couvreur's programming blog and more

Handle mailto: links with Gmail


I was just writing about the problem of having the browser send specialized blobs of data to a user selected service ("open-ended links"). One example is how to handle special URI schemes such as mailto: with a web-based service. There is a number of ways to do this, including registry hacks and browser extensions. I wish there was a more lightweight architecture supported by the browser...

Anyways, I experimented with Greasemonkey to get mailto: links to open in Gmail. The result is MailtoComposeInGMail.user.js.
It looks for mailto: links and re-writes them to go to the Gmail compose page, which most of the useful parameters (to, cc, subject, body,...) maintained.

It has a minor inconvenience, in that you cannot do "Copy email address" in the browser's context menu anymore (since it's not a mailto: link anymore). On the other hand, it allows you to open that link either in the current window or a separate tab the same way you would do any regular link.
I couldn't get both behaviors to work at the same time...

Other scripts:
I also wrote a quickie to remove the annoying interstitial ad pages on IGN.

Right now I'm finishing up a wysiwyg user script generator. Scripts that insert a piece of html next to links matching a certain pattern, such as the Inline mp3 player or Streammp3, can be generated with this tool.

Update (2007/01/12):
It looks like Firefox 3 plans to support web services to act as content handlers as well as making the microformat handling configurable.
I'm not sure whether Firefox 3 might also support the WHATWG's URI handling by web service (section 5.3.2. "Custom protocol and content handlers" in the Web Applications 1.0 draft).
Either of these is a step towards the kind of architecture that I was hoping for, letting the user configure which service should handle which type of information. They also each have their own challenges, in that they need some changes in the content (using a new URI scheme, using a new microformat), need some agreement or conventions on the right markup, and require some new browser UI (which hopefully would be unified with the current scenarios of handling mime types and uri schemes with a desktop app).

Update (2009/06/17): Firefox 3.5 comes with a built-in way to associate mailto: links to GMail. This renders my Greasemonkey script obsolete.


Hi, do you write in french ?

I'm searching a script to make "Display external images" automatically, do you know where i can find one?

I'm just begining in scripting...

Bye, thanks


Posted by: Stephane Vincent (April 23, 2005 06:34 PM) ______________________________________

Hi Stephane.
No, I don't currently blog in french at all. Why?
A friend of mine (Julien Ellie) has a mixed english-french blog though, which I found an interesting concept (you can filter posts by language if you want):
I have too much trouble with french IT words now, so I'm sticking to english for now ;-)

Regarding the "display external images" user script, can you clarify the concept?.
Mark Pigrim's "Offsite blank" script sounds related: it differentiates offsites urls. You might be able to re-use it:

A bientot,

Posted by: Julien (April 23, 2005 11:52 PM) ______________________________________

For "Display External Images", I think he's referring to when you receive HTML email in GMail. When they include images referenced on external servers, you have to click the "Display External Images" link to make them display, and he wants a script that will automagically do it.

Posted by: ShimmyShimmyYa (May 5, 2005 06:38 PM) ______________________________________

Nice, however the inability to copy e-mail addresses is the show blocker for me.

I once attempted this as a greasemonkey script as well, but failed (ended up hardcoding it like you).

A while ago (years) I wrote the "Webmailcompose" extension for firefox, which does this and makes firefox's 'send this page' and 'send link' to work as well. I still maintain it, but the code is horrible, and I need to rewrite it one of these days.

Anyhow, if you ever do find a better way, that would be great as it would be a much lighter solution than what WMC does right now.

Posted by: Jed (May 21, 2005 09:16 PM) ______________________________________

Re: "Display External Images"
Thanks for the clarification ShimmyShimmyYa. There is a user script request in the wiki that seems to correspond to what you describe: "always show images in message" on GMail. It's not been implemented yet though. I'll try to take a stab at it.

Posted by: Julien Couvreur (May 23, 2005 04:56 PM) ______________________________________

Jed, I just installed your "Webmailcompose" extension ( ).
It handles both scenario nicely: compose in new tab and copy email address.

I think I'm going to use it instead of my user script.
Thanks ;-)

Posted by: Julien (May 23, 2005 05:03 PM) ______________________________________

Okay, if the creator of MailtoComposeInGMail.user.js is going to use WMC, then I'll follow suit Actually, I was using WMC, until I read of Julien's script. Then I deleted WMC and installed MailtoComposeInGMail.user.js. But after reading the comments of the 2 authors, and the comment previous this one, I'm back on WMC.

Anyway, I'd be happy to know if there are any updates to MailtoComposeInGMail.user.js in the future!

Posted by: jeff (May 31, 2005 03:45 AM) ______________________________________


Could you modify the Gmail mailto: script so that it opens the compose screen in a new tab instead of overwriting the page from where the mailto: link was clicked?


Posted by: Korm (June 4, 2005 06:59 AM) ______________________________________

Here's how to modify the script to open mailto: links into a new tab, using GM 0.4 when it becomes available (with the GM_openInTab function):

var newUrl = "" +
(emailTo ? ("&to=" + emailTo) : "") +
(emailCC ? ("&cc=" + emailCC) : "") +
(emailSubject ? ("&su=" + emailSubject) : "") +
(emailBody ? ("&body=" + emailBody) : "");

mailtoLink.onclick = function() { GM_openInTab(newUrl); return false; };

Note that GM 0.4 is postponed for now due to security concerns (fixed in hotfix release 0.3.5).

Posted by: Julien (July 25, 2005 02:06 PM) ______________________________________

I appreciated very much your script!!! But after the new release of greasemonkey (0.5) i made an unauthorized change on your script. My need was to have a choice to send an email with or without gmail (i'm at work ;-)).
So i modified your script to add before "mailto:" link an icon to send via gmail launching the composer in new tab.
To be correct, follow my changes:

replace the original code:
mailtoLink.href = "" +
(emailTo ? ("&to=" + emailTo) : "") +
(emailCC ? ("&cc=" + emailCC) : "") +
(emailSubject ? ("&su=" + emailSubject) : "") +
(emailBody ? ("&body=" + emailBody) : "");

with my new code:

//create mail composer url
var sendEmailUrl = "" +
(emailTo ? ("&to=" + emailTo) : "") +
(emailCC ? ("&cc=" + emailCC) : "") +
(emailSubject ? ("&su=" + emailSubject) : "") +
(emailBody ? ("&body=" + emailBody) : "");

//create gmail icon tag
var gmailIcon = document.createElement('img');

//set gmail icon
gmailIcon.src = "data:image/bmp;base64,Qk1GAgAAAAAAADYAAAAoAAAAEAAAAAsAAAABABgAAAAAABACAADEDgAAxA4AAAAAAAAAAAAAODjaODjap6f5p6f5p6f5p6f5p6f5p6f5p6f5p6f5p6f5p6f5p6f5p6f5ODjaODjaODjaODja4uL%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F4uL%2FODjaODjaODjaODjap6f54uL%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F4uL%2Fp6f5ODjaODjaODjaODja4uL%2Fp6f54uL%2F%2F%2F%2F%2F%2F%2F%2F%2FgYHygYHy%2F%2F%2F%2F%2F%2F%2F%2F4uL%2Fp6f54uL%2FODjaODjaODjaODja%2F%2F%2F%2F4uL%2Fp6f5trb%2FgYHyWlrpWlrpgYHytrb%2Fp6f54uL%2F%2F%2F%2F%2FODjaODjaODjaODja%2F%2F%2F%2F%2F%2F%2F%2Ftrb%2FgYHyWlrpODjaODjaWlrpgYHytrb%2F%2F%2F%2F%2F%2F%2F%2F%2FODjaODjaODjaODja%2F%2F%2F%2F%2F%2F%2F%2FgYHyWlrpODjatrb%2Ftrb%2FODjaWlrpgYHy%2F%2F%2F%2F%2F%2F%2F%2FODjaODjaODjaODja%2F%2F%2F%2FgYHyWlrpODjatrb%2F%2F%2F%2F%2F%2F%2F%2F%2Ftrb%2FODjaWlrpgYHy%2F%2F%2F%2FODjaODjaODjaODjagYHyWlrpODjatrb%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2Ftrb%2FODjaWlrpgYHyODjaODjaODjaODjaODjaODjatrb%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2Ftrb%2FODjaODjaODjaODjaODjaODjaODjagYHyp6f5p6f5p6f5p6f5p6f5p6f5p6f5p6f5gYHyODjaODjaODja";

//set style and tooltip = "none"; = "pointer";
gmailIcon.title = "send email to " + emailTo + " via gmail"

//create function to load composer in new tab
gmailIcon.onclick = function() { GM_openInTab(sendEmailUrl); return false; };

//add gmail icon before original link
mailtoLink.parentNode.insertBefore(gmailIcon, mailtoLink);

i hope this is appreciated!!!
and i'm sorry again for unauthorized code (and my bad english!)

Posted by: netinjection (August 3, 2005 02:21 AM) ______________________________________

WELL, here's my take on your script, for what it's worth.

(function() {

var processMailtoLinks = function() {
var xpath = "//a[starts-with(@href,'mailto:')]";
var res = document.evaluate(xpath, document, null,

var linkIndex, mailtoLink;
for (linkIndex = 0; linkIndex

Posted by: ben (October 6, 2005 07:00 AM) ______________________________________

Sorry, (text got truncated on repost after bad email)

(function() {

var processMailtoLinks = function() {
var xpath = "//a[starts-with(@href,'mailto:')]";
var res = document.evaluate(xpath, document, null,

var linkIndex, mailtoLink;
for (linkIndex = 0; linkIndex < res.snapshotLength; linkIndex++) {
mailtoLink = res.snapshotItem(linkIndex);
mailtoLink.addEventListener("click", function(event) {

var m =;
var matches = m.match(/^mailto:([^\?]+)(\?([^?]*))?/);
var emailTo, params, emailCC, emailSubject, emailBody;

emailTo = matches[1];

params = matches[3];
if (params) {
var splitQS = params.split('&');
var paramIndex, param;

for (paramIndex = 0; paramIndex < splitQS.length; paramIndex++) {
param = splitQS[paramIndex];
nameValue = param.match(/([^=]+)=(.*)/);
if (nameValue && nameValue.length == 3) {
// depending on name, store value in a pre-defined location
switch(nameValue[1]) {
case "to":
emailTo = emailTo + "%2C%20" + nameValue[2];
case "cc":
emailCC = nameValue[2];
//alert("Found CC=" + emailCC);
case "subject":
emailSubject = nameValue[2];
//alert("Found subject=" + emailSubject);
case "body":
emailBody = nameValue[2];
//alert("Found body=" + emailBody);

var href = "" +
(emailTo ? ("&to=" + emailTo) : "") +
(emailCC ? ("&cc=" + emailCC) : "") +
(emailSubject ? ("&su=" + emailSubject) : "") +
(emailBody ? ("&body=" + emailBody) : "");;
}, false);
window.addEventListener("load", processMailtoLinks, false);


Posted by: ben (October 6, 2005 07:03 AM) ______________________________________

Hello, I've incorporated your script into a similar project I've been working on - my school's webmail interface is pretty terrible, so I've been trying to improve it (the project I've written is also licensed under the GPL).

I wanted to point out that there appears to be a bug in the code - if the variables aren't blanked out, subsequent mailto: links will carry over the values that were assigned in the previous run if the values aren't overwritten, so for instance


will generate an incorrect link for jim@gmx.tld.

Thank you so much for releasing this code under the GPL!

Posted by: Kurt McKee (November 8, 2005 01:31 AM) ______________________________________

Kurt, thanks a lot for the bug report. I'll get a fix done when I come back from vacation in two weeks or so.

Posted by: Julien Couvreur (November 15, 2005 12:33 PM)
comments powered by Disqus