Is there a way to detect if the browser has a mailto protocol handler set?

662 views Asked by At

I have a site that dynamically builds a mailto url which it then opens in a new tab/window, using window.open().

window.open("mailto:" + encodeURIComponent(r["to"]));

I'm testing in Chrome at this stage, so other browsers may act differently.

If Chrome has a mailto protocol handler set up (e.g. GMail), then it works as expected.

If Chrome does not have a mailto protocol handler set up, it just opens a tab with the mailto url and nothing else.

That's not the worst result, but it would be nice if there was a way of knowing in advance, so that the user could be in some way guided to setting up their browser so that the mailto url worked nicely.

Previously, I was just opening in the same page by setting window.location.href to the url:

windows.location.href = "mailto:" + encodeURIComponent(r["to"]);

This wasn't great because if there was no protocol handler set, nothing happened. I also would consider this as an option, IF I can at least detect the situation, but wasn't able to find any indication of that either. I guess one option would be to set a timer which if it reached execution could alert the user?

Anyone else already solved this? Seems like a pretty common requirement.

Thanks

1

There are 1 answers

1
xtempore On

Here's what I ended up working with. It doesn't work in all cases, but provides at least some help in recognising unhandled protocols.

It attempts to open the URL in a new window and then after 2s it takes a look to see if it can read the location. If it has opened a third party site (e.g. GMail) this will raise and exception - so we treat this as success.

If no exception occurs, this returns "about:blank" which means we (probably) failed.

function openWin(url) {
  return new Promise((resolve, reject) => {
    const w = window.open(url);
    if (!w) {
      reject();
    }
    setTimeout(function() {
      try {
        const working = w.document.location.href;
      } catch (e) {
        resolve();
        return;
      }
      w.close();
      reject();
    }, 2000);
  });
}

Called with something like this:

openWin('mailto:' + encodeURIComponent(to)).then(() => {
  // handle success
}).catch(() => {
  // handle failure
});

Caveat: This only works for web-based protocol handlers. If for example your mailto is handled by an email app, then this will fail.

In my case, most people would be using web-based email, so it works for most cases. On failure I show a message to the affect of "If your email didn't open, copy the email address here..."