You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何用Python Google Cloud Function每日定时发送Gmail邮件?

最简实现:定时触发Google Cloud Function发送Gmail邮件

Hey there! Let's break down the simplest, most reliable way to set up a daily scheduled email from a Google Cloud Function to a Gmail address. First, let's cover why your initial attempts might have hit snags, then jump into the working solution.

为什么之前的方案可能失败?

  • 方案1(smtplib): 现在Gmail已经不再支持大多数账号使用明文密码登录了。你需要启用双因素认证后生成应用专用密码,或者开启“不太安全的应用访问”(不推荐,且Google正在逐步淘汰该功能)。另外,在函数里硬编码凭证也是严重的安全风险。
  • 方案2(SendGrid): 大概率是API密钥配置出了问题——你注释掉了从环境变量读取密钥的代码,硬编码的密钥可能无效,或者SendGrid控制台里的发件邮箱未完成验证。

最优方案:GCP生态内实现(Gmail API + Cloud Scheduler)

这个方案用Google原生工具实现,更安全、易扩展,还能避免依赖第三方服务。以下是分步指南:

1. 前置准备

  • 在你的GCP项目中启用Gmail APICloud Functions APICloud Scheduler API
  • 创建一个服务账号,给它分配Gmail Send权限(测试阶段可以用Editor,但生产环境要严格限制权限)。
  • 如果是用个人Gmail账号发送:需要配置域范围授权(仅适用于Google Workspace账号),或者使用OAuth2.0刷新令牌。为了简化,这里我们推荐用Google Workspace服务账号;如果是个人账号,可以用应用专用密码替代(下文会给出示例)。

2. Cloud Function代码(Python)

这段代码用Gmail API发送邮件,凭证从GCP Secret Manager加载(也可以用环境变量,但Secret Manager更安全)。

import base64
from googleapiclient.discovery import build
from google.oauth2 import service_account

def send_daily_email(event, context):
    # 加载服务账号凭证(将JSON密钥文件存储在Secret Manager中!)
    credentials = service_account.Credentials.from_service_account_file(
        'path/to/service-account-key.json',
        scopes=['https://www.googleapis.com/auth/gmail.send']
    )
    # 将凭证委托给发件邮箱(仅适用于Workspace账号)
    delegated_credentials = credentials.with_subject('your-sender-email@example.com')
    
    # 构建Gmail API客户端
    service = build('gmail', 'v1', credentials=delegated_credentials)
    
    # 构造邮件内容
    to_email = 'recipient-email@gmail.com'
    subject = '每日定时邮件'
    body = '这是来自Google Cloud Function的每日自动邮件!'
    
    # 按RFC 2822格式组装邮件
    message = f"""From: 发件人 <your-sender-email@example.com>
To: 收件人 <{to_email}>
Subject: {subject}

{body}
"""
    # 编码邮件以适配Gmail API要求
    encoded_message = base64.urlsafe_b64encode(message.encode('utf-8')).decode('utf-8')
    create_message = {'raw': encoded_message}
    
    # 发送邮件
    try:
        send_message = service.users().messages().send(userId='me', body=create_message).execute()
        print(f"邮件发送成功!消息ID: {send_message['id']}")
        return "邮件发送成功"
    except Exception as e:
        print(f"发送邮件出错: {e}")
        return f"邮件发送失败: {str(e)}"

3. 配置Cloud Scheduler

  • 打开GCP控制台的Cloud Scheduler页面。
  • 创建新任务:
    • 频率: 使用 cron 表达式,比如0 0 * * *(每天UTC时间午夜触发,可根据你的时区调整)。
    • 目标: 选择HTTP,填入你的Cloud Function的URL。
    • HTTP方法: 选择POST(Cloud Function默认期望POST触发)。
    • 认证: 选择添加OIDC令牌,并指定你之前创建的服务账号。

个人Gmail账号适配方案(smtplib + 应用专用密码)

如果你用的是个人Gmail账号,开启双因素认证后生成应用专用密码,就可以用smtplib实现,记得把密码存在Secret Manager里:

import smtplib
from google.cloud import secretmanager

def send_email_smtp(event, context):
    # 从Secret Manager加载应用专用密码
    client = secretmanager.SecretManagerServiceClient()
    secret_name = "projects/你的项目ID/secrets/gmail-app-password/versions/latest"
    response = client.access_secret_version(request={"name": secret_name})
    app_password = response.payload.data.decode("UTF-8")
    
    gmail_user = 'your-email@gmail.com'
    to = ['recipient-email@gmail.com']
    subject = '每日测试邮件'
    body = '这是通过smtplib + 应用专用密码发送的邮件'
    
    email_text = f"""From: {gmail_user}
To: {', '.join(to)}
Subject: {subject}

{body}
"""
    try:
        server = smtplib.SMTP_SSL('smtp.gmail.com', 465)
        server.login(gmail_user, app_password)
        server.sendmail(gmail_user, to, email_text)
        server.close()
        print('邮件发送成功!')
        return "操作成功"
    except Exception as e:
        print(f"出错了: {e}")
        return "操作失败"

总结

最健壮且贴合GCP生态的方式是用Gmail API配合服务账号(Workspace)或应用专用密码(个人账号),再用Cloud Scheduler触发函数。这种方式无需依赖第三方服务,还能保证凭证的安全性。

内容的提问来源于stack exchange,提问作者abgo2020

火山引擎 最新活动