How to open mailto links in new tab for users that have gmail as the default mail handler?

28,157

Solution 1

Okay, so I was able to get this working in Chrome on Mac. Your mileage may vary. Also, this is pretty hacky IMO, so it may not be worth it. Honestly this should exist as a setting within Chrome, and the behavior should be delegated to the website. E.g. Chrome should have an option: "[x] Always open mailto links in separate tab"

That being said, here's how you do it.

First construct your links like so:

<a href="#" data-mailto="[email protected]">Mail Somebody</a>

Then set a click handler for those.

$('a[data-mailto]').click(function(){
  var link = 'mailto.html#mailto:' + $(this).data('mailto');
  window.open(link, 'Mailer');
  return false;
});

There is an optional options argument to window.open that you can tweak. In fact I would almost recommend it, to see if you can get the generated window to be as unnoticable as possible. https://developer.mozilla.org/en/DOM/window.open

http://www.w3schools.com/jsref/met_win_open.asp (the MDN doc is exhaustive, while the w3schools doc is almost easier to read)

Next we need to create the mailto.html page. Now you may need to play around with the timeout you see below. You could probably even set this to something really short like 500ms.

<html>
<script>
function checkMailto(hash){
    hash = hash.split('mailto:');
    if(hash.length > 1){
        return hash[1];
    } else {
        return false;
    }
}

var mailto = checkMailto(location.hash);

if(mailto){
    location.href = 'mailto:'+mailto;
    setTimeout(function(){
      window.close();
    }, 1000);
}
</script>
</html>

Results

Mail.app set as my default email reader:

When I click the link, it opens a window for a split second, then composes a blank message. In the browser it goes back to the original page.

Gmail set as mail reader under Settings > Advanced > Privacy > Handlers:

When I click the link, it opens a new tab to Gmail, with the previous page safely in it's own tab.

Note: Once you set Gmail as your email handler, on the OS side (at least on mac), Chrome is set as the system's email handler. So even if you turn off Gmail as the email handler inside Chrome, it is still set on the OS level. So to reset that, I went to Mail > Prefs > General. And set default mail reader back to Mail.

Solution 2

I received a request for implementing this in ownCloud Contacts and though I also think it's a bit hackish, there doesn't seem to be another way of detecting if the mailto handler is set to a webmail address.

This example is implemented without the need for external files.

NOTE: jQuery is needed for this example, but it can probably be rewritten to strict javascript.

To avoid having to use data-mailtoor other tricks, you can instead intercept the handler:

$(window).on('click', function(event) {
    if(!$(event.target).is('a[href^="mailto"]')) {
        return;
    }

    // I strip the 'mailto' because I use the same function in other places
    mailTo($(event.target).attr('href').substr(7));
    // Both are needed to avoid triggering other event handlers
    event.stopPropagation();
    event.preventDefault();
});

Now for the mailTo() function:

var mailTo = function(url) {
    var url = 'mailto:' + data.url;
    // I have often experienced Firefox errors with protocol handlers
    // so better be on the safe side.
    try {
        var mailer = window.open(url, 'Mailer');
    } catch(e) {
        console.log('There was an error opening a mail composer.', e);
    }
    setTimeout(function() {
        // This needs to be in a try/catch block because a Security 
        // error is thrown if the protocols doesn't match
        try {
            // At least in Firefox the locationis changed to about:blank
            if(mailer.location.href === url 
                    || mailer.location.href.substr(0, 6) === 'about:'
            ) {
                mailer.close();
            }
        } catch(e) {
            console.log('There was an error opening a mail composer.', e);
        }
    }, 500);

}

I decreased the timeout to 500. Works For Me, lets see what the users say when it's pushed ;)

If you want to avoid opening a new tab/window you can use an iframe. It will require an extra request, but is less annoying if you don't use webmail yourself. This wasn't feasible for ownCloud because per default the Content-Security-Policy is very strict, and injecting "foreign" URLs into an iframe isn't allowed (not tested much):

var mailTo = function(url) {
    var url = 'mailto:' + data.url, $if;
    try {
        $if = $('<iframe />')
            .css({width: 0, height: 0, display: 'none'})
            .appendTo($('body'))
            .attr('src', url);
    } catch(e) {
        console.log('There was an error opening a mail composer.', e);
    }
    setTimeout(function() {
        try {

            if($if.attr('src') !== url 
                    && $if.attr('src').substr(0, 6) !== 'about:'
            ) {
                window.open($if.attr('src'), 'Mailer');
            }
        } catch(e) {
            console.log('There was an error opening a mail composer.', e);
        }
        $if.remove();
    }, 500);

}
Share:
28,157
Admin
Author by

Admin

Updated on March 14, 2020

Comments

  • Admin
    Admin about 4 years

    On a web page mailto links open the default e-mail client. Now that Chrome offers the ability to set Gmail as the default e-mail client, some users have the links open in the same window thus taking them away from the page they clicked the link (which they do not like)

    I have tried adding target _blank to the links, which works great for gmail users, but will drive Outlook users mad, because a new blank tab will open every time they click a mailto link.

    I there a way to detect the default e-mail handler and offer a good experience for both types of users?