调用 gmail API messages.send() 时,带有 pubsub 触发器的云函数无限执行
我们正在使用具有电子邮件自动化功能的 Atlassian 状态页面,这意味着每当收到主题为“DOWN”的电子邮件时,它都会在屏幕上显示警报,并在收到主题为“UP”的电子邮件时删除相同的警报。
我激活了 Gmail Pub/Sub (https://developers.google.com/gmail/ api/guides/push) 推送通知,它监视 gmail 收件箱中的更改,并在更改实际发生时向 pub/sub 主题发送推送通知。
然后我创建了一个由发布/订阅通知触发的云函数。此云功能应该:
- 阅读最新的未读电子邮件
- 如果此电子邮件是我们的第 3 方提供商发送的警报,请相应地向状态页面发送一封新电子邮件,主题为“向下”或“向上”。
这是代码:
def access_oauth2_json():
### Code
return creds_dict
def create_message(subject):
### Code
return {'raw': b64_string}
def send_message(service, message, user_id = 'me'):
try:
response = service.users().messages().send(userId=user_id, body=message).execute()
return response
except HttpError as error:
logging.error('An error occurred:', error)
def update_status_page(arg1,arg2):
### Initialise creds
try:
service = build('gmail', 'v1', credentials=creds)
request = {
'labelIds': ['INBOX'],
'topicName': 'pubsub_topic_id'
}
service.users().watch(userId='me', body = request).execute()
last_message_info = service.users().messages().list(userId='me', labelIds=['UNREAD'], q = 'in:inbox is:unread', maxResults=1).execute().get('messages', [])
last_message = service.users().messages().get(userId='me', id=last_message_info[0]['id']).execute()
header = last_message['payload']['headers']
sub = ""
for x in header:
if x['name'] == 'Subject':
sub = x['value'] #subject
logging.info(sub)
if 'special_alert_string' in sub:
message = create_message(subject = 'DOWN')
response = send_message(service, message)
elif 'other_special_alert_string' in sub:
message = create_message(subject = 'UP')
response = send_message(service, message)
except HttpError as error:
logging.info(f'An error occurred: {error}')
return 200
发生的情况是:
- 当函数由非第三方警报的电子邮件触发时,if/elif 块不会执行,而是执行云函数 2 或3 次(而不是 1 次,但这对我来说很好,所以不是真正的问题)
2 - 问题 - 当函数被触发时一封是第三部分警报的电子邮件,执行 if/elif 块(两者之一)并且该函数无限执行!它只会因为达到每个时间间隔的最大 API 请求数而停止。
我尝试过的操作:
- 删除 watch() 行,但没有成功
- 注释掉 service.users().messages().send() 行又回到了情况 1,所以我的猜测是该指令是触发向 pub/sub 主题推送通知并生成无限循环。这个问题也许可以用另一个 watch() labelId 来解决,但我还没弄清楚是哪一个。
我希望这很清楚,谢谢您的帮助!
We are using the Atlassian Status Page with email automation, which means that it displays an alert on screen whenever it receives an email with subject 'DOWN' and deletes the same alert when it receives an email with subject 'UP'.
I activated the Gmail Pub/Sub (https://developers.google.com/gmail/api/guides/push) push notifications, which watches the gmail inbox for changes and sends a push notification to a pub/sub topic when a change actually happens.
Then I created a cloud function which is triggered by pub/sub notifications. This cloud function should:
- Read the latest unread email
- If this email is an alert sent by our 3rd party provider, send a new email to the Status Page with subject 'DOWN' or 'UP' accordingly.
This is the code:
def access_oauth2_json():
### Code
return creds_dict
def create_message(subject):
### Code
return {'raw': b64_string}
def send_message(service, message, user_id = 'me'):
try:
response = service.users().messages().send(userId=user_id, body=message).execute()
return response
except HttpError as error:
logging.error('An error occurred:', error)
def update_status_page(arg1,arg2):
### Initialise creds
try:
service = build('gmail', 'v1', credentials=creds)
request = {
'labelIds': ['INBOX'],
'topicName': 'pubsub_topic_id'
}
service.users().watch(userId='me', body = request).execute()
last_message_info = service.users().messages().list(userId='me', labelIds=['UNREAD'], q = 'in:inbox is:unread', maxResults=1).execute().get('messages', [])
last_message = service.users().messages().get(userId='me', id=last_message_info[0]['id']).execute()
header = last_message['payload']['headers']
sub = ""
for x in header:
if x['name'] == 'Subject':
sub = x['value'] #subject
logging.info(sub)
if 'special_alert_string' in sub:
message = create_message(subject = 'DOWN')
response = send_message(service, message)
elif 'other_special_alert_string' in sub:
message = create_message(subject = 'UP')
response = send_message(service, message)
except HttpError as error:
logging.info(f'An error occurred: {error}')
return 200
What happens is that:
- When the function is triggered by an email which is not a 3rd party alert, the if/elif blocks are not executed, and the cloud function is executed 2 or 3 times (instead of 1, but that's fine for me, so not really a problem)
2 - Problem - When the function is triggered by an email which is a 3rd part alert, the if/elif blocks are executed (one of the 2) and the function is executed endlessly! It only stops because it reaches the maximum API requests per interval of time.
What I have tried:
- To remove the watch() line, without success
- Commenting out the service.users().messages().send() line falls back into case 1, so my guess is that this instruction is triggering a push notification to the pub/sub topic and generates the infinite loop. The issue could maybe solved with another watch() labelId, but I haven't figured out which one.
I hope this is clear, thank you for your help!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论