gmail.js: Using api.get.email_source() fails in MS Edge
No really. If you want to write WebExtensions which supports all modern browers, MS Edge is a target too. š
Basically something fails because of XHR with bad HTTP methods, and while it may not be fatal, the way we handle it causes it to fail:
api.get.email_source()requests something from https://mail.google.com.- This results in a 302 redirect.
- The new URL gets probed by jQuery using a HTTP OPTION request.
- This is where it fails. If we could catch this error, and just retry with a GET, we should be cool.
You can see this in the developer console here:


@michi88: Anything you think you could contribute on this issue? Youāve touched this very specific code yourself š
Tip: If you need help enabling extensions in Edge, check the uBlock Edge docs for how to enable developer mode.
About this issue
- Original URL
- State: closed
- Created 8 years ago
- Comments: 19 (3 by maintainers)
@josteink I think weāre on the same page here - I meant we should retire the sync version in favor of async as I assume using xhr route will return the email data asynchronously š
That seems a bit rash IMO. Allow me argue why.
Overview
Oh noes. Iāve added headers. It seems this will be a long message š
When we want to download the raw MIME-message, the URL we generate (and which we are allowed to make, as a script running on
https://mail.google.com/, is to another resource on the same domain.As @KartikTalwar points out, thatās not where the data is actually stored, so we are redirected by a HTTP 302 to the actual domain hosting the data:
mail-attachment.googleusercontent.com.This means we are crossing a domain-boundary, but since the request originated on
mail.google.com, thatās OK, as long as the receiving host (mail-attachment.googleusercontent.com) is also willing to accept our request.This is what the preflight check is doing. Itās checking for CORS headers, which will list
mail.google.comas a valid source for requests. If this header is present in the response, the browser will proceed with the actual, real request.So for all good, all standard. All browsers are (or should be) doing this. Itās pretty much the spec for how things should work. (Or at least so Iāve been told).
Issues
Now this is where things get tricky, because we have 3 different issues, 2 of them which can easily get conflated, and those are both related to caching:
mail-attachment.googleusercontent.combecause of bad request.mail-attachment.googleusercontent.combecause of invalid authentication cookies.The third issue is not really directly related to the others, but if weāre making any changes or API-changes in response to the first ones, it should be considered too, so Iām including it anyway š
Issue 1: Bad request
Letās tackle the bad request first:
The workaround we have for this right now, is sending
{cache: false}tojQuery.ajax(), but that unfortunately only seems to work in Chrome right now.From what I can tell,
jQuery.ajax()is attempting to speed things up by exploiting cached content. Towards this goal, it might add additional HTTP-headers:https://github.com/jquery/jquery/blob/1.10.2/jquery.js#L8048-L8080
My guess is that
mail-attachment.googleusercontent.comisnāt expecting these headers and thus responds with ā405 Bad Requestā.By manually implementing a XHR downloader which does none of that fancy stuff jQuery does, Iāve been able to completely bypass this problem. As far as I can tell, it only exists because of jQuery. So letās not use jQuery š
Issue 2: Failing āunauthenticatedā requests.
And when we solve that, it eventually leads us to the 401 unathenticated responseā¦
So before diving into the specifics, just to get it over with, letās remind ourselves of some basics: Just like I canāt take (or guess!) a URL from your Gmail, run it in my browser and grab your email, Google does the same for itās raw MIME-messages and email-attachments.
To get any of your personal data, I need to be authenticated to Gmail as you. On the web, this is done through the use of cookies.
Yes I know you knew that. But itās easy to forget. And now we all have it in mind, and will give it proper attention. So letās proceed with the actual issue.
When trying to (manually via XHR) download the
email_source, the initial response will succeed for a single givenemailID. And it will succeed for other emailIDs too.But if you try to request the
email_sourcefor the sameemailIDmore than once, things will start failing. With a 401.To find the reason for this, we need to inspect the actual browser requests and responses:
The request getās redirected, and as we can see at this point, we have lots of cookies!
One of those cookies (or several, in combination) represents our authenticated login to Gmail.
We follow the redirect to
mail-attachment.googleusercontent.com, and get a new response. This response however tells us to go obsolete some of our cookies. Immediately!NOTE: The following request was issued at 7:53:03 GMT, despite the misleading
Date:andExpired:headers:That means that if we repeat the original request (unmodified) to
mail.google.com, the browser will most likely remember the 302, and go directly tomail-attachment.googleusercontent.com.But if we re-request the same resource on
mail-attachment.googleusercontent.com, we will now have a different set of cookies, since we obsoleted some on our last request!And so, it seems weāre suddenly unauthenticated!
A few observations:
Iāve observed the following:
In conclusion:
All in agreement say āyes!ā, and Iāll do my best to make it so š