【问题标题】:Batch fetching messages performance批量获取消息性能
【发布时间】:2014-08-17 20:26:44
【问题描述】:

我需要获取收件箱中的最后 100 条消息(仅限标题)。为此,我目前正在使用 IMAP 扩展来搜索然后获取消息。这是通过两个请求完成的(SEARCH,然后是 UID FETCH)。
什么是 Gmail API 相当于在一个请求中获取多封邮件?
我所能找到的只是一个批处理 API,这似乎更麻烦(组成一长串 messages:get 请求,用纯 HTTP 代码包装)。

【问题讨论】:

  • 只是对@walty yeung 的回答的一个小补充。我们需要在第二个循环之前执行batch.execute()

标签: gmail-api


【解决方案1】:

Gmail API 中的内容与 IMAP 中的内容几乎相同。两个请求:第一个是 messages.list 以获取消息 ID。然后一个(批量)message.get 来检索你想要的。根据您使用的语言,客户端库可能有助于构建批处理请求。

批处理请求是包含多个 Google Cloud Storage JSON API 调用的单个标准 HTTP 请求,使用 multipart/mixed 内容类型。在该主 HTTP 请求中,每个部分都包含一个嵌套的 HTTP 请求。

发件人:https://developers.google.com/storage/docs/json_api/v1/how-tos/batch

真的没那么难,我花了大约一个小时在 python 中弄明白,即使没有 python 客户端库(只使用 httplib 和 mimelib)。

这里是部分代码 sn-p,同样使用直接 python。希望它清楚地表明没有太多的参与:

msg_ids = [msg['id'] for msg in body['messages']]
headers['Content-Type'] = 'multipart/mixed; boundary=%s' % self.BOUNDARY

post_body = []
for msg_id in msg_ids:
  post_body.append(
    "--%s\n"
    "Content-Type: application/http\n\n"
    "GET /gmail/v1/users/me/messages/%s?format=raw\n"
    % (self.BOUNDARY, msg_id))
post_body.append("--%s--\n" % self.BOUNDARY)
post = '\n'.join(post_body)
(headers, body) = _conn.request(
    SERVER_URL + '/batch',
    method='POST', body=post, headers=headers)

【讨论】:

    【解决方案2】:

    很好的回复!
    如果有人想使用 php 中的原始函数来批量请求获取与消息 ID 对应的电子邮件,请随意使用我的。

    function perform_batch_operation($auth_token, $gmail_api_key, $email_id, $message_ids, $BOUNDARY = "gmail_data_boundary"){
        $post_body = "";
        foreach ($message_ids as $message_id) {
            $post_body .= "--$BOUNDARY\n";
            $post_body .= "Content-Type: application/http\n\n";
            $post_body .= 'GET https://www.googleapis.com/gmail/v1/users/'.$email_id.
                    '/messages/'.$message_id.'?metadataHeaders=From&metadataHeaders=Date&format=metadata&key='.urlencode($gmail_api_key)."\n\n";
        }
        $post_body .= "--$BOUNDARY--\n";
    
        $headers = [ 'Content-type: multipart/mixed; boundary='.$BOUNDARY, 'Authorization: OAuth '.$auth_token  ];
    
        $curl = curl_init();
        curl_setopt($curl,CURLOPT_URL, 'https://www.googleapis.com/batch' );
        curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "POST");
        curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
        curl_setopt($curl,CURLOPT_CONNECTTIMEOUT , 60 ) ;
        curl_setopt($curl, CURLOPT_TIMEOUT, 60 ) ;
        curl_setopt($curl,CURLOPT_POSTFIELDS , $post_body);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER,TRUE);
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER,0);
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
        $tmp_response =  curl_exec($curl);
        curl_close($curl);
        return $tmp_response;
    
    }
    

    仅供参考,上述函数仅获取电子邮件的标题,特别是 From 和 Date 字段,请根据 api 文档https://developers.google.com/gmail/api/v1/reference/users/messages/get进行调整

    【讨论】:

      【解决方案3】:

      除了 MaK,您还可以使用 google-api-php-clientGoogle_Http_Batch() 执行多个批处理请求

              $optParams = [];
              $optParams['maxResults'] = 5;
              $optParams['labelIds'] = 'INBOX'; // Only show messages in Inbox
              $optParams['q'] = 'subject:hello'; // search for hello in subject
      
              $messages = $service->users_messages->listUsersMessages($email_id,$optParams);
      
              $list = $messages->getMessages();
      
                  $client->setUseBatch(true);
      
                  $batch = new Google_Http_Batch($client);                
      
                  foreach($list as $message_data){
      
                      $message_id = $message_data->getId();
      
                      $optParams = array('format' => 'full');
      
                      $request = $service->users_messages->get($email_id,$message_id,$optParams);
      
                      $batch->add($request, $message_id);                 
                  }
      
                  $results = $batch->execute();
      

      【讨论】:

        【解决方案4】:

        这里是python版本,使用官方google api client。请注意,这里我没有使用回调,因为我需要以同步的方式处理响应。

        from apiclient.http import BatchHttpRequest
        import json
        
        batch = BatchHttpRequest()
        
        #assume we got messages from Gmail query API
        for message in messages:
            batch.add(service.users().messages().get(userId='me', id=message['id'],
                                                     format='raw'))
        batch.execute()
        for request_id in batch._order:
            resp, content = batch._responses[request_id]
            message = json.loads(content)
            #handle your message here, like a regular email object
        

        【讨论】:

          【解决方案5】:

          Walty Yeung 的解决方案部分适用于我的用例。 如果你们尝试了代码但没有任何反应,请使用此批次

          batch = service.new_batch_http_request()
          

          【讨论】:

          • 这是正确答案。 Walty Yeung 的回答已过时并返回错误googleapiclient.errors.HttpError: <HttpError 404 when requesting https://www.googleapis.com/batch returned "Not Found">
          猜你喜欢
          • 2012-02-17
          • 2011-03-11
          • 2021-04-24
          • 2012-07-30
          • 2016-12-15
          • 1970-01-01
          • 1970-01-01
          • 2020-09-22
          • 2016-06-14
          相关资源
          最近更新 更多