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

无需发布应用,通过Gmail API高效删除两周前旧邮件的权限问题求助

无需发布应用,通过Gmail API高效删除两周前旧邮件的权限问题求助

我的Gmail已经用到15GB上限了,于是用Thunderbird归档了旧邮件,现在想删除所有两周前的邮件。但用GUI操作太麻烦,每次好像只能删100封。所以我想着做个测试应用,把自己的谷歌账号加为测试用户来加速删除操作。我在谷歌云控制台创建了OAuth凭据,写了一个Python脚本在本地虚拟环境运行。不过我怀疑是不是必须发布应用才能获得删除权限?但我不想发布应用。

这是我的代码:

from googleapiclient.discovery import build
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request
import pickle
import os
from datetime import datetime, timedelta
import logging

# Set up logging
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')

# Define scopes for Gmail API
SCOPES = ['https://www.googleapis.com/auth/gmail.modify']

def main():
    creds = None
    # Load existing credentials
    if os.path.exists('token.pickle'):
        with open('token.pickle', 'rb') as token:
            creds = pickle.load(token)
    # Authenticate if no valid credentials
    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)
        with open('token.pickle', 'wb') as token:
            pickle.dump(creds, token)

    # Verify granted scopes
    verify_scopes(creds)

    service = build('gmail', 'v1', credentials=creds)
    delete_all_emails_with_buffer(service)

def verify_scopes(creds):
    """Verify the scopes granted in the OAuth token."""
    if creds and creds.scopes:
        logging.info(f"Granted Scopes: {creds.scopes}")
        required_scopes = set(SCOPES)
        granted_scopes = set(creds.scopes)

        if required_scopes.issubset(granted_scopes):
            logging.info("All required scopes are granted.")
        else:
            missing_scopes = required_scopes - granted_scopes
            logging.error(f"Missing required scopes: {missing_scopes}")
    else:
        logging.error("No scopes found in the token. Authentication might have failed.")

def delete_all_emails_with_buffer(service, dry_run=False):
    try:
        buffer_date = (datetime.now() - timedelta(days=14)).strftime('%Y/%m/%d')
        query = f'label:inbox before:{buffer_date}'
        messages = []
        response = service.users().messages().list(userId='me', q=query).execute()
        if 'messages' in response:
            messages.extend(response['messages'])

        while 'nextPageToken' in response:
            response = service.users().messages().list(userId='me', q=query,
                                                       pageToken=response['nextPageToken']).execute()
            messages.extend(response['messages'])

        logging.info(f"Found {len(messages)} emails to delete.")

        if dry_run:
            logging.info("Dry run mode: No emails will be deleted.")
            for msg in messages[:10]:  # Show a sample of emails
                try:
                    email_details = service.users().messages().get(userId='me', id=msg['id']).execute()
                    logging.info(f"Email ID: {msg['id']}, Subject: {email_details.get('snippet')}")
                except Exception as e:
                    logging.error(f"Failed to fetch email details for ID {msg['id']}: {e}")
        else:
            logging.info("Deleting emails...")
            for msg in messages:
                try:
                    service.users().messages().delete(userId='me', id=msg['id']).execute()
                    logging.info(f"Deleted email ID: {msg['id']}")
                except Exception as e:
                    logging.error(f"Failed to delete email ID {msg['id']}: {e}")
    except Exception as e:
        logging.error(f"Error during email deletion process: {e}")

if __name__ == '__main__':
    main()

我注意到认证流程启动时,权限列表里没有删除相关的选项,而且在谷歌账号的第三方应用安全设置里,也没看到删除权限。终端里的错误输出是这样的:

2025-01-11 17:45:25,628 - WARNING - Encountered 403 Forbidden with reason "insufficientPermissions"
2025-01-11 17:45:25,628 - ERROR - Failed to delete email ID 194080c9712fd742: <HttpError 403 when requesting https://gmail.googleapis.com/gmail/v1/users/me/messages/194080c9712fd742? returned "Request had insufficient authentication scopes.". Details: "[{'message': 'Insufficient Permission', 'domain': 'global', 'reason': 'insufficientPermissions'}]">

备注:内容来源于stack exchange,提问作者Paul Lewallen

火山引擎 最新活动