Documentation for . The clients object is a list of known http(s) webmail compose format strings. Each string uses certain replacement keys (% + character) where a certain replacement should happen. Replacement keys for the compose format string: %T = encoded TO value %S = encoded Subject value %M = encoded Body value %C = encoded CC value %B = encoded BCC value %w = the whole mailto URI percent-encoded (works like registerProtocolHandlers's %s) %% = % (The keys are case-sensitive.) Just set the activeClient variable to one of the names in the clients object to open up mailto links in that webmail. Add your own compose string for another webmail to the client list if you like. Set supportTargetAttribute to true if you want link and form target attributes to decide where the compose URI is loaded. Otherwise, it will always open in a blank tab/window, unless pop-ups are totally turned off. In that case, the URI will open in the current tab/window. Site-specific problems: Gmail1 has a problem where if you click the "Compose mail" link, any data specified in the address field (from a previously-loaded compose URI) will be used to fill in the compose fields. This makes it impossible to compose a blank message until you get rid of the data in the address field. This is fixed in Gmail2. For the basic HTML version of Gmail, you have to POST variables. I may make a specific workaround for that, but maybe not. Operamail.com doesn't send their pages as UTF-8. This will cause some unicode characters to not show up right and perhaps not send right. For squirrelmail and horde servers, you want to make sure you set the page encoding to UTF-8. For example, for Squirrelmail, you'd do this with config.pl. Yahoo's new UI doesn't support Opera and redirects you. This causes the compose variables to be lost. Even though Opera's browser.js makes the new UI work, it can't fix this part. However, a server-specific compose format string is also provided that you can mess with. It works, but Yahoo must have a length limit on the hvalues and long compose URIs will fail to load. Yahoo webmail has a few bugs and will convert some characters in the compose fields to HTML entities. It also only supports basic values and if you use anything complex, it will not come out right. For fastmail.fm, make sure you log in at < http://www.fastmail.fm/ >(as opposed to < http://fastmail.fm/ >). If you don't, you *might* be asked to log in before continuing to the compose page. Thanks to Rob at fastmail for fixing fastmail's compose URI support! Some webmails like mail.live.com do not accept BCC values in compose URIs. This is probably because of the old RFC2368 security recommendation, which I don't agree with. Note that sites may change things at any time and the format strings might break. In short though, most of the webmails are crappy in this area. Besides SquirrelMail's, Gmail's http compose URI support is probably the best. Parser: The parser does quite a few things to make sure values come out right. It handles duplicate hnames per < http://shadow2531.com/opera/testcases/mailto/modern_mailto_uri_scheme.html#duplicates >. This handling of duplicate hnames is how Opera's M2 and Thunderbird 3.0 do it. It decodes and reencodes values to normalize encoding. It makes sure characters that were not encoded, but need to be, are. It makes sure characters that were encoded, but don't need to be, are not. Also, it makes sure + characters are represented as %2B. If they are not, they'll be treated by the server as spaces. It basically makes sure the encoded values conform to ECMAScript's encodeURIComponent results. It normalizes \r\n and stray \r to \n when decoding. (This is to make sure all newlines are represented as \n for easy processing). On encoding, it makes sure that all newlines are represented as %0D%0A. When the parser encodes and decodes things, if an error happens, it will return "" instead. The parser is also set up to easily add support for other hnames and to tweak the handling of duplicates for each hname. It's also easy to change the compose format string identifier from % to something else. See format() for example. The parser is setup to treat all hnames as case-insensitive. The parser also understands encoded hnames. It will decode them before checking for a match. The parser is set up for some flexibility and desired results as opposed to performance. However, it performs just fine on even really slow computers. Also, filterLine and filterMultiLine are used (depending on the type of hvalue that's being gathered) to escape(by encoding to %HH) and strip unwanted characters. This is important (at least for null bytes and %00) because Gmail for instance will break if it receives %00 in the compose URI and decodes it. This is pretty close to how Opera filters stuff. escapeInvalidHH is used to treat invalid %HH literally as a form of error handling. It is done before values are decoded, so encodeURIComponent and decodeURIComponent don't choke on them. The compose format strings themselves are not filtered at all. Null bytes, %00, invalid %HH and unwanted %HH will remain. It is assumed that the format string will always be 100% correct. Click handler: The click handler only handles left-click on mailto links (middle-click or right-click -> compose to override). If Opera ever supports a window.opera.addEventListener("BeforeMailtoURL" listener that catches all mailto protocol execution, I'll use that. For now, I'm using a left-click listener on the whole window. This works out great anyway because you can right-click to compose in M2 if needed. If you would like to type a mailto URI in a text field and have BeforeMailtoURL handle it, you can use this bookmarklet: javascript:(function()%7B%0D%0Avar%20uri%20%3D%20prompt(%22Mailto%20URI%20Address%20Field%22)%3B%0D%0Aif%20(uri%20%26%26%20uri.search(%2Fmailto%3A%2Fi)%20%3D%3D%200)%20%7B%0D%0A%20%20%20%20var%20a%20%3D%20document.createElementNS(%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxhtml%22%2C%20%22a%22)%3B%0D%0A%20%20%20%20a.href%20%3D%20uri%3B%0D%0A%20%20%20%20a.click()%3B%0D%0A%7D%20else%20%7B%0D%0A%20%20%20%20alert(%22Not%20a%20mailto%20URI!%22)%3B%0D%0A%7D%0D%0A%7D)()%3B (Name it "Mailto URI Address Field" for example.) Note that if you have popups turned off all the way, the http compose URI will load in the current tab instead of a blank one.. The handler makes sure that the action is considered user-initiated by Opera. Otherwise, you might not be logged in if you use "Accept only cookies from the site I visit". (See the click() mumbo jumbo in loadURI). The handler also uses getAttribute("href") instead of .href. This way, the parser gets the unresolved value so that it can do the resolving itself. This helps to work around bugs in Opera's resolving of href attributes with mailto: URIs.. You can change this to use .href if you want. Form handler: Using BeforeEvent.submit to intercept submission of forms that use the mailto protocol. This is not used for mailto forms that submit to http pages. When submitting, createMailtoURIFromEnabledFormControls mimics Firefox's action="mailto:" support to generate a mailto URI, which is then handed over to the parser like it is with the click handler. The function relies on a form's elements collection. If the elements collection doesn't contain all the elements it's supposed to, that's a bug in Opera. The way the dataset is built doesn't completely mimic the way a browser builds the dataset yet. This will be improved. It'd be easier if Opera itself provided a JS function to get the dataset for the form. Note that Opera's form support for action="mailto:" is broken for GET and not the same as Firefox for POST. So, using BeforeMailtoURL.js with a webmail is the only way to get mailto form support to work in Opera. Both the click and form handler honor the target attribute on the link or form if you set supportTargetAttribute to true. It's not very useful, but provided for fun.