Gmail API - 推送通知 - 新电子邮件到达时收到 2 条通知

问题描述 投票:0回答:1

我想编写一个Python脚本,每次当我的收件箱收到新消息时它都会通知我。为此,我使用了 Google 的 Pub/Sub 服务。我已经创建了文档中提到的主题和订阅。我还使用此处定义的拉模式:

https://cloud.google.com/pubsub/docs/pull

脚本可以工作,但我遇到的问题是,当新电子邮件到达我的收件箱时,我总是收到 2 条通知(参见照片):

到目前为止的代码:

from __future__ import print_function

from concurrent.futures import TimeoutError
from google.cloud import pubsub_v1
from googleapiclient.discovery import build

import os.path

from google.auth.transport.requests import Request
from google.oauth2.credentials import Credentials
from google_auth_oauthlib.flow import InstalledAppFlow
from googleapiclient.discovery import build
from googleapiclient.errors import HttpError

# If modifying these scopes, delete the file token.json.
SCOPES = ['https://www.googleapis.com/auth/gmail.readonly']


creds = None
# The file token.json stores the user's access and refresh tokens, and is
# created automatically when the authorization flow completes for the first
# time.
if os.path.exists('token.json'):
    creds = Credentials.from_authorized_user_file('token.json', SCOPES)
# If there are no (valid) credentials available, let the user log in.
if not creds or not creds.valid:
    if creds and creds.expired and creds.refresh_token:
        creds.refresh(Request())
    else:
        flow = InstalledAppFlow.from_client_secrets_file(
            'credentials.json', SCOPES)
        creds = flow.run_local_server(port=0)
    # Save the credentials for the next run
    with open('token.json', 'w') as token:
        token.write(creds.to_json())

# TODO(developer)
project_id = "projectgmailapi-366508"
subscription_id = "mysub"
#Number of seconds the subscriber should listen for messages
timeout = 180.0

service = build('gmail', 'v1', credentials=creds)
request = {
  'labelIds': ['UNREAD'],
  'labelFilterAction': 'include',
  'topicName': 'projects/projectgmailapi-366508/topics/mytopic'
}
service.users().watch(userId='me', body=request).execute()

subscriber = pubsub_v1.SubscriberClient()
# The `subscription_path` method creates a fully qualified identifier
# in the form `projects/{project_id}/subscriptions/{subscription_id}`
subscription_path = subscriber.subscription_path(project_id, subscription_id)

def callback(message: pubsub_v1.subscriber.message.Message) -> None:
    print(f"Received {message}.")
    message.ack()

streaming_pull_future = subscriber.subscribe(subscription_path, callback=callback)
print(f"Listening for messages on {subscription_path}..\n")

# Wrap subscriber in a 'with' block to automatically call close() when done.
with subscriber:
    try:
        # When `timeout` is not set, result() will block indefinitely,
        # unless an exception is encountered first.
        streaming_pull_future.result(timeout=timeout)
    except TimeoutError:
        streaming_pull_future.cancel()  # Trigger the shutdown.
        streaming_pull_future.result()  # Block until the shutdown is complete.
  1. 那么如何才能在有新消息到达时只收到一条通知?
  2. 我可以以某种方式过滤事件,以便仅在新消息到达时仅收到一次通知,而不是删除、发送、阅读消息等其他事件。我只需要在新电子邮件到达时收到通知。

p.s我也尝试修改请求

request = {  
  'labelIds': 
  ['SPAM','TRASH','STARRED','IMPORTANT','SENT','DRAFT','UNREAD'],
  'labelFilterAction': 'exclude',
  'topicName': 'projects/projectgmailapi-366508/topics/mytopic'
}

因此它排除了除收件箱之外的所有标签,但现在我根本没有收到通知

python google-api gmail-api google-cloud-pubsub
1个回答
0
投票

Cloud Pub/Sub 提供至少一次交付语义。因此,您保证会收到一份通知,但也可能会收到多份通知。

这是 为什么 GCP Pub/Sub 发布消息两次?

此外,对于您问题的第二部分,我认为您应该从排除列表中删除 UNREAD 标签。

© www.soinside.com 2019 - 2024. All rights reserved.