Clarification around gmail history api and mailbox full sync - gmail-api

How often does the historyId change, it says in the doc that in some cases it might be valid only for few hours, how frequent is that?
And In case I get a 404 in history api then can I rely on updating the historyId to the latest historyId for new changes via pub/sub and instead of doing a full sync, I use query parameter to fetch messages whose timestamp is greater than the max timestamp I had in my database to reduce resource consumption?

The response to your question as per documentation:
A historyId is typically valid for at least a week, but in some rare circumstances may be valid for only a few hours.
If you receive an HTTP 404 error response, your application should perform a full sync.

Related

Get CS:GO Inventory from Steam API for my React APP

Since requesting the Inventory from https://api.steampowered.com/IEconItems_730/GetPlayerItems/v1/ is permanently disabled I have to use https://steamcommunity.com/profiles/<steam_id>/inventory/json/2
Because of CORS I have to use my backend to provide the requested data. But when I do requests too often, my requests get rejected and my app cannot work on a large scale.
So the question should be simple: How can I avoid the rejection of my requests?
Any ideas and suggestions welcome.
Steam inventory endpoints are pretty heavily rate-limited, but there are a few different endpoints that you can use.
Trade offer endpoint
https://steamcommunity.com/tradeoffer/new/partnerinventory
This is the endpoint that's used when you open a trade offer with someone. It can be used to fetch both your own inventory as well as a trade partners. Required parameters are partner which is the user's Steam 64 Id, appid which is 730 in the case of CS:GO, and contextid which is 2 for most valve games. I don't know the exact limit, but I've been hitting this endpoint about once a second for a month with minimal 429 responses. To use this endpoint, you need to have a valid steam session and send the proper cookies along with the request. This will also only return tradable items.
Inventory endpoint #1
http://steamcommunity.com/inventory/STEAM64ID/APPID/CONTEXTID
Another inventory endpoint which has the same parameters but in the URL. I use this endpoint as a fallback to the first, but I've found that if the first endpoint is rate limited then this one will be too. That said, this one becomes limited much faster so it's best to use the first one instead.
Inventory endpoint #2
http://steamcommunity.com/profiles/STEAM64ID/inventory/json/APPID/CONTEXTID
The endpoint you're using. I don't use this one at all, but it could be worth knowing as another fallback.
Not all of them return the same data format, so be mindful. One inventory a second is a pretty solid rate for any decently sized site, especially if you limit user's ability to refresh inventories. If you need more though, you'll have to start looking into proxies.

Q: Gmail Api Returning Emails With InternalDates In the Future

I am attempting to use the Gmail api to synchronize all the email's from a user's Gmail inbox. I am using the Partial Synchronization technique described in Gmail's "Synchronizing Clients" [1] documentation. One of the listed limitations of this is that in rare cases the historyId of certain emails are unavailable. Under these circumstances, it is advised that the client fall back on using "Full Synchronization", which states that the client should "retrieve and store as many of the most recent messages or threads as are necessary for your purpose".
This all makes sense. When I have issues with Partial Synchronization, I attempt to look through an inboxes messages by time range. To do this, I effectively store a record of the ( emailAddress, historyId, internalDate ) of each email I sync and then when falling back on Full Synchronization I attempt to sync all email since the most recent internalDate that I have already synced.
My issue is that the cases that seem to cause partial synchronization to fail also seem to cause Full Synchronization to fail, and many of these cases are caused by emails with internalDates in the future (I can't share these examples for privacy reasons). The failure case seems to be something like the following
I sync email E with historyId H and an internalDate I some time in the future
Some time passes
I receive a push notification from google indicating that their are new emails to sync
I lookup the most recent message that I have syncecd for this inboxId, finding email E
I attempt a partial sync using the listHistory [2] endpoint with historyId H
The listHistory request fails with a 404
I attempt a full sync using the listMessages [3] endpoint using the query newer_than:{hours_since-internalDate-I}, but this request doesn't make any sense since the internalDate of this message is in the future.
I can imagine a few different solutions to this problem. Perhaps I should simply ignore these emails as spam, or perhaps I should store a timestamp of when I synced each email and then perform a Full Synchronization on the timestamp I have stored.
Either way, this seems like a bug in the Gmail API, as the internalDate should really be when Gmail received the email. I initially suspected that this might be caused by Gmail's new schedule feature and that the internalDate might be when the email was scheduled in the future, but I confirmed that some of the examples I have are definitely for emails that the user's inbox received, not sent. Really not sure what to make of this edge case within the internalDate api.
So my question is, what is the advised way to handle bogus future internalDates? And is it a bug?
https://developers.google.com/gmail/api/guides/sync
https://developers.google.com/gmail/api/v1/reference/users/history/list
https://developers.google.com/gmail/api/v1/reference/users/messages/list
If you're sure this is a bug, you can head to Google's Issue Tracker (template here) and report it so their engineering team can take a look and see what is causing this error. Alternatively if this persists with other mails or users, you can open a support ticket directly with them by going to your admin dashboard and selecting 'Contact Support' in the ? menu in the top right. This way Google can take a look into the erroneous internalDates without the need for you to post any potentially sensitive data in a public forum.
In the mean time you can workaround this dynamically by making sure that you don't fetch mails with a time in the future (psuedo-code):
var now = new Date().getTime()
var q = "newer_than:1h before:" + now
GmailServiceConnect.Users.messages.list(userId = "user#domain.ext", q = q).execute()
But remember that Gmail uses milliseconds for Unix time not seconds so this will have to be adjusted accordingly.

Status of the topic

I have watch/subscribed to the topic using the following code.
request = {
'labelIds': ['INBOX'],
'topicName': 'projects/myproject/topics/mytopic'
}
gmail.users().watch(userId='me', body=request).execute()
How can I get the status of the topic at any given point in time? The problem is, sometimes I am not getting the push from Gmail for any incoming emails.
From the Cloud Pub/Sub perspective, if you want to check on the status of messages, you could look at metrics via Stackdriver. There are many Cloud Pub/Sub metrics that are available. You can create graphs on any of the metrics that will be mentioned later by going to Stackdriver, creating a new dashboard, clicking on "Add Chart," and then typing in the name of the metric in the "Find resource type and metric box:
The first thing you have to determine is whether the issue is on the publish side (from Gmail into your topic) or on the subscribe side (from the subscription to your push endpoint). To determine if the topic is receiving messages, look at the topic/send_message_operation_count metric. This should be non-zero at points where messages were sent from Gmail to the topic. If it is always zero, then it is likely that the connection from Gmail to Cloud Pub/Sub is not set up properly, e.g., you need to grant publish rights to the topic. Note that results are delayed, so from the time you expect a message to have been sent to when it would be reflected on the graph could be up to 5 minutes.
If the messages are successfully being sent to Pub/Sub, then you'll want to see the status of attempts to receive those messages. If your subscription is a push subscription, then you'll want to look at subscription/push_request_count for the subscription. Results are grouped by response code. If the responses are in the 400 or 500 ranges, then Cloud Pub/Sub is attempting to deliver messages to your subscriber, but the subscriber is returning errors. In this case, it is likely an issue with your subscriber itself.
If you are using the Cloud Pub/Sub client libraries, then you'll want to look at properties like subscription/streaming_pull_message_operation_count to determine if your subscriber is managing to try to fetch messages for a subscription. If you are calling the pull method directly in your subscriber, then you'll want to look at subscription/pull_message_operation_count to see if there are pull requests returning successfully to your subscriber.
If the metrics for push, pull, or streaming pull indicate errors, that should help to narrow down the problem. If there are no requests at all, then it indicates that the subscribers may not There could be permission problems, e.g., the subscriber is running as a user that doesn't have permission to read from subscriptions.

Google Cloud Pub/Sub - Stopped triggering push to endpoint

It was working fine till last day and suddenly stopped pushing to endpoint. Checked all settings including endpoint URL and found everything remains unchanged. Can you guys suggest possible causes.
Not receiving a message on a push endpoint could happen for many reasons. The first thing to do would be to go to Stackdriver and create a graph for the subscription/push_request_count metric. You can break this down by response_code to see how many requests Cloud Pub/Sub is sending to your push endpoint and what response codes it is returning. If there are requests being delivered that are returning errors, this graph will show that.
It might also be worth checking the publish side to ensure messages are still being published as expected. You can look at the topic/send_message_operation_count metric, which can also be broken down by response_code, to make sure the publish requests are all returning success.
You should also check to ensure the subscription still exists using the Pub/Sub Subscriptions page in the Cloud console. After 30 days of inactivity (including inability to successfully deliver a message to a push endpoint), subscriptions are potentially deleted.
If the issue still unsolved after those steps, it is best to contact Google Cloud support with your project ID and subscription name so that things can be investigated for your specific case.

Javamail: how to fetch messages modified since a specific date

I'm writing an application that synchronize emails (inbox only) from an IMAP server. For that I'm using javamail and I have performance issue. When I want to refresh my emails, I fetch all messages in inbox, and it takes several minutes. :(
So I would like to fetch only messages that were modified since the last time I refreshed emails. I found how to fetch messages received or sent since a date, but what I want to do is slightly different. It is possible to change the state of a very old message (unread to read). In this case the modification date is recent but received or send date is old.
Any idea ?
Regards,
Quentin
You can't change the content of an old message, but you can change the flags. You can fetch all the flags for all messages and compare them with your cached copy of the flags. (There are IMAP extensions that help with this, but many IMAP servers don't support them and JavaMail doesn't support them.)
Use the Folder.fetch method to fetch all the flags in one operation, then iterate over the Message objects and compare the flags.

Resources