我想编写一个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.
p.s我也尝试修改请求
request = {
'labelIds':
['SPAM','TRASH','STARRED','IMPORTANT','SENT','DRAFT','UNREAD'],
'labelFilterAction': 'exclude',
'topicName': 'projects/projectgmailapi-366508/topics/mytopic'
}
因此它排除了除收件箱之外的所有标签,但现在我根本没有收到通知
Cloud Pub/Sub 提供至少一次交付语义。因此,您保证会收到一份通知,但也可能会收到多份通知。
此外,对于您问题的第二部分,我认为您应该从排除列表中删除 UNREAD 标签。