【问题标题】:Why does search in gmail API return different result than search in gmail website?为什么在 gmail API 中搜索与在 gmail 网站中搜索返回的结果不同?
【发布时间】:2016-02-06 18:42:27
【问题描述】:

我正在使用 gmail API 来搜索来自用户的电子邮件。我创建了以下搜索查询:

ticket after:2015/11/04 AND -from:me AND -in:trash

当我在 Gmail 的浏览器界面中运行此查询时,我收到了 11 条消息(如预期的那样)。然而,当我在 API 中运行相同的查询时,我只收到 10 条消息。我用来查询 gmail API 的代码是用 Python 编写的,如下所示:

searchQuery = 'ticket after:2015/11/04 AND -from:me AND -in:trash'
messagesObj = google.get('/gmail/v1/users/me/messages', data={'q': searchQuery}, token=token).data
print messagesObj.resultSizeEstimate  # 10

我将相同的消息发送到另一个 gmail 地址并从该电子邮件地址对其进行了测试,并且(令我惊讶的是)它确实出现在与该其他电子邮件地址的 API 搜索中,因此问题不在于电子邮件本身。

在通过各种 test-gmail 帐户无休止地发送电子邮件后,我*认为(但不是 100% 确定)浏览器界面搜索功能对 "me" 的定义不同。似乎在 API 搜索中它不包括来自具有相同名称的电子邮件地址的电子邮件,而这些结果实际上包含在浏览器搜索的结果中。例如:如果"Pete Kramer" 将电子邮件从petekramer@icloud.com 发送到pete@gmail.com(两者的名称都设置为"Pete Kramer"),它将显示在浏览器搜索中,而不会显示在API 搜索中。

谁能确认这是问题所在?如果是这样,有没有办法绕过这个以获得与浏览器搜索返回的结果相同的结果?或者有其他人知道为什么 gmail 浏览器搜索的结果与 gmail API 搜索的结果不同吗?欢迎提供建议!

【问题讨论】:

  • 不记得开箱即用的确切库引用是什么,但我希望错误出现在您提供的路径中,即'/gmail/v1/users/'+email_address+'/messages'
  • @Torxed - 按照网上的建议,我将 email_address 更改为 me: /gmail/v1/users/me/messages。虽然这解决了一些其他问题,但它还没有解决这个问题.. :S 还有其他想法吗?
  • 如果设置了 maxResults 参数会发生什么?我在想它可能默认为 10。我还注意到 sizeEstimate 就是这样,结果第一页上的值可能非常不准确;只有在您对结果集进行分页时才能改进

标签: python api email gmail gmail-api


【解决方案1】:

我怀疑是after 查询参数给您带来了麻烦。 2015/11/04 is not a valid ES5 ISO 8601 date。你可以试试after:<time_in_seconds_since_epoch>

# 2015-11-04 <=> 1446595200

searchQuery = 'ticket AND after:1446595200 AND -from:me AND -in:trash'
messagesObj = google.get('/gmail/v1/users/me/messages', data={'q': searchQuery}, token=token).data
print messagesObj.resultSizeEstimate  # 11 hopefully!

【讨论】:

    【解决方案2】:

    /messages/listq 参数与我在 Web UI 上的工作方式相同(在 https://developers.google.com/gmail/api/v1/reference/users/messages/list#try-it 上试用过)

    我认为问题在于您调用的是/messages 而不是/messages/list

    【讨论】:

    • 我尝试了您的建议并将'/gmail/v1/users/me/messages' 更改为'/gmail/v1/users/me/messages/list',但这会导致错误:{u'error': {u'code': 400, u'message': u'Invalid id value', u'errors': [{u'domain': u'global', u'message': u'Invalid id value', u'reason': u' invalidArgument'}]}}。知道如何使用基本 url 方式使用列表吗?
    • 在 gmail 文档中,我认为 '/gmail/v1/users/me/messages' 已经是获取列表的方式:developers.google.com/gmail/api/v1/reference/users/messages/…
    【解决方案3】:

    您的应用程序第一次连接到 Gmail 时,或者如果部分同步不可用,您必须执行完全同步。在完全同步操作中,您的应用程序应检索和存储尽可能多的最新消息或线程,以满足您的目的。例如,如果您的应用程序显示最近消息的列表,您可能希望检索和缓存足够的消息,以便在用户滚动超出显示的前几条消息时允许响应式界面。执行完全同步操作的一般过程如下:

    1. 调用messages.list 来检索第一页的消息ID。

    2. 为列表请求返回的每条消息创建一个messages.get 请求的批处理请求。如果您的应用程序显示消息内容,您应该在应用程序第一次检索消息时使用 format=FULL 或 format=RAW 并缓存结果以避免额外的检索操作。如果您要检索以前缓存的消息,则应使用 format=MINIMAL 来减小响应的大小,因为只有 labelIds 可能会更改。

    3. 将更新合并到您的缓存结果中。您的应用程序应存储最新消息(列表响应中的第一条消息)的 historyId 以供将来部分同步。

    注意:您还可以使用等效的线程资源方法执行同步。如果您的应用程序主要使用线程或只需要消息元数据,这可能是有利的。

    部分同步

    如果您的应用程序最近已同步,您可以使用 history.list 方法执行部分同步,以返回比您在请求中指定的 startHistoryId 更新的所有历史记录。历史记录为每条消息提供消息 ID 和更改类型,例如添加、删除消息或自 startHistoryId 以来修改的标签。您可以从完整或部分同步中获取并存储最新消息的 historyId,以作为 startHistoryId 提供给未来的部分同步操作。

    限制

    历史记录通常至少可以保存一周,通常更长时间。但是,记录可用的时间段可能要短得多,并且有时在极少数情况下记录可能不可用。如果您的客户端提供的 startHistoryId 超出历史记录的可用范围,API 将返回 HTTP 404 错误响应。在这种情况下,您的客户端必须按照上一节所述执行完全同步。

    来自 gmail API 文档 https://developers.google.com/gmail/api/guides/sync

    【讨论】:

      最近更新 更多