请求 None 时的 HttpError 403 返回“权限不足
HttpError 403 when requesting None returned "Insufficient Permission
正在从 Gmail 的电子邮件附件上传到 Google 驱动器:
from __future__ import print_function
import pickle
import os.path
from googleapiclient.discovery import build
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request
import io
import base64
from googleapiclient.http import MediaIoBaseUpload
from time import sleep
q='has:attachment'
maxResults=int(input("Please specify the number of emails with attachments that you would like to see:"))
#for drive api---------------------------------------------------------------------------------
# If modifying these scopes, delete the file token.pickle.
creds = None
# The file token.pickle 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_drive.pickle'):
with open('token_drive.pickle', 'rb') as token_drive:
creds = pickle.load(token_drive)
# 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_drive.json', 'https://www.googleapis.com/auth/drive.metadata.readonly')
creds1 = flow.run_local_server(port=0)
# Save the credentials for the next run
with open('token_drive.pickle', 'wb') as token_drive:
pickle.dump(creds, token_drive)
drive_service= build('drive', 'v3', credentials=creds1)
sleep(5)
# for gmail api---------------------------------------------------------------------------------
# If modifying these scopes, delete the file token.pickle.
creds = None
# The file token.pickle 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.pickle'):
with open('token.pickle', 'rb') as token:
creds = pickle.load(token)
# 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', 'https://www.googleapis.com/auth/gmail.readonly')
creds = flow.run_local_server(port=0)
# Save the credentials for the next run
with open('token.pickle', 'wb') as token:
pickle.dump(creds, token)
service = build('gmail', 'v1', credentials=creds)
# Call the Gmail API
results = service.users().labels().list(userId='me').execute()
#Get Messages
results = service.users().messages().list(userId='me',q=q, maxResults=maxResults ,labelIds=['INBOX']).execute()
messages = results.get('messages', [])
def create_folder_in_drive(service,folder_name,parent_folder=[]):
file_metadata ={
'name': folder_name,
'parents': parent_folder,
'mimeType':'application/vnd.google-apps.folder'
}
for message in messages:
msg = service.users().messages().get(userId='me',metadataHeaders=['parts'], id=message['id']).execute()
messageID=msg['threadId']
messageSubject='(No Subject)({0})'.format(messageID)
msgdetail=msg.get('payload')
for item in msgdetail['headers']:
if item['name']=='Subject':
if item['value']:
messageSubject='{0} ({1})'.format(item['value'],messageID)
else:
messageSubject='(No Subject)({0})'.format(messageID)
print("messagesubject:" , messageSubject )
#create drive folder
folder_id=create_folder_in_drive(drive_service,messageSubject)
if 'parts' in msgdetail:
for msgPayload in msgdetail['parts']:
mime_type=msgPayload['mimeType']
file_name=msgPayload['filename']
body=msgPayload['body']
print(body)
if 'attachmentId' in body:
attachment_id=body['attachmentId']
response=service.users().messages().attachments().get(
userId='me',
messageId=msg['id'],
id=attachment_id
).execute()
file_data=base64.urlsafe_b64decode(
response.get('data').encode('UTF-8'))
fh=io.BytesIO(file_data)
file_metadata= {
'name':file_name,
'parents':[folder_id]
}
media_body=MediaIoBaseUpload(fh,mimetype=mime_type,chunksize=1024*1024,resumable=True)
file=drive_service.files().create(
body= file_metadata,
media_body=media_body,
fields='id'
).execute()
你好朋友,如果我删除文件目录下的token.pickle和token_drive.pickle文件(这些文件是从google云端单独创建的)和运行代码:
“ResumableUploadError: error", 当我 运行 没有删除 pickle 文件的代码时,我得到错误是“NameError: name 'service' is not defined.”
似乎是同时验证 Gmail 和云端硬盘的问题,因为 media_body 和 file_metadata return 一个值,但我无法解决问题。
我正在 phone 关注您的代码。
您应该能够获得一个 单个 令牌,其范围足以用于 Gmail 和 驱动器,而不是同时使用多个令牌。
Unpickling 对象也可能引起某种碰撞。即使它只适合您,我还是建议您尽可能避免酸洗。
这里有一个 Google sample,显示了使用 Python 的 Gmail 的 OAuth 流程。该示例将令牌作为文件写入|读取到磁盘。使用 2 个范围尝试此代码。
#for gmail and drive api------------------------------------------------------------
# If modifying these scopes, delete the file token.pickle.
SCOPES=['https://www.googleapis.com/auth/gmail.readonly','https://www.googleapis.com/auth/drive','https://www.googleapis.com/auth/drive.file','https://www.googleapis.com/auth/drive.metadata']
creds = None
# The file token.pickle 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.pickle'):
with open('token.pickle', 'rb') as token:
creds = pickle.load(token)
# 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.pickle', 'wb') as token:
pickle.dump(creds, token)
service = build('gmail', 'v1', credentials=creds)
drive_service = build('drive', 'v3', credentials=creds)
正在从 Gmail 的电子邮件附件上传到 Google 驱动器:
from __future__ import print_function
import pickle
import os.path
from googleapiclient.discovery import build
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request
import io
import base64
from googleapiclient.http import MediaIoBaseUpload
from time import sleep
q='has:attachment'
maxResults=int(input("Please specify the number of emails with attachments that you would like to see:"))
#for drive api---------------------------------------------------------------------------------
# If modifying these scopes, delete the file token.pickle.
creds = None
# The file token.pickle 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_drive.pickle'):
with open('token_drive.pickle', 'rb') as token_drive:
creds = pickle.load(token_drive)
# 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_drive.json', 'https://www.googleapis.com/auth/drive.metadata.readonly')
creds1 = flow.run_local_server(port=0)
# Save the credentials for the next run
with open('token_drive.pickle', 'wb') as token_drive:
pickle.dump(creds, token_drive)
drive_service= build('drive', 'v3', credentials=creds1)
sleep(5)
# for gmail api---------------------------------------------------------------------------------
# If modifying these scopes, delete the file token.pickle.
creds = None
# The file token.pickle 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.pickle'):
with open('token.pickle', 'rb') as token:
creds = pickle.load(token)
# 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', 'https://www.googleapis.com/auth/gmail.readonly')
creds = flow.run_local_server(port=0)
# Save the credentials for the next run
with open('token.pickle', 'wb') as token:
pickle.dump(creds, token)
service = build('gmail', 'v1', credentials=creds)
# Call the Gmail API
results = service.users().labels().list(userId='me').execute()
#Get Messages
results = service.users().messages().list(userId='me',q=q, maxResults=maxResults ,labelIds=['INBOX']).execute()
messages = results.get('messages', [])
def create_folder_in_drive(service,folder_name,parent_folder=[]):
file_metadata ={
'name': folder_name,
'parents': parent_folder,
'mimeType':'application/vnd.google-apps.folder'
}
for message in messages:
msg = service.users().messages().get(userId='me',metadataHeaders=['parts'], id=message['id']).execute()
messageID=msg['threadId']
messageSubject='(No Subject)({0})'.format(messageID)
msgdetail=msg.get('payload')
for item in msgdetail['headers']:
if item['name']=='Subject':
if item['value']:
messageSubject='{0} ({1})'.format(item['value'],messageID)
else:
messageSubject='(No Subject)({0})'.format(messageID)
print("messagesubject:" , messageSubject )
#create drive folder
folder_id=create_folder_in_drive(drive_service,messageSubject)
if 'parts' in msgdetail:
for msgPayload in msgdetail['parts']:
mime_type=msgPayload['mimeType']
file_name=msgPayload['filename']
body=msgPayload['body']
print(body)
if 'attachmentId' in body:
attachment_id=body['attachmentId']
response=service.users().messages().attachments().get(
userId='me',
messageId=msg['id'],
id=attachment_id
).execute()
file_data=base64.urlsafe_b64decode(
response.get('data').encode('UTF-8'))
fh=io.BytesIO(file_data)
file_metadata= {
'name':file_name,
'parents':[folder_id]
}
media_body=MediaIoBaseUpload(fh,mimetype=mime_type,chunksize=1024*1024,resumable=True)
file=drive_service.files().create(
body= file_metadata,
media_body=media_body,
fields='id'
).execute()
你好朋友,如果我删除文件目录下的token.pickle和token_drive.pickle文件(这些文件是从google云端单独创建的)和运行代码:
“ResumableUploadError:
似乎是同时验证 Gmail 和云端硬盘的问题,因为 media_body 和 file_metadata return 一个值,但我无法解决问题。
我正在 phone 关注您的代码。
您应该能够获得一个 单个 令牌,其范围足以用于 Gmail 和 驱动器,而不是同时使用多个令牌。
Unpickling 对象也可能引起某种碰撞。即使它只适合您,我还是建议您尽可能避免酸洗。
这里有一个 Google sample,显示了使用 Python 的 Gmail 的 OAuth 流程。该示例将令牌作为文件写入|读取到磁盘。使用 2 个范围尝试此代码。
#for gmail and drive api------------------------------------------------------------
# If modifying these scopes, delete the file token.pickle.
SCOPES=['https://www.googleapis.com/auth/gmail.readonly','https://www.googleapis.com/auth/drive','https://www.googleapis.com/auth/drive.file','https://www.googleapis.com/auth/drive.metadata']
creds = None
# The file token.pickle 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.pickle'):
with open('token.pickle', 'rb') as token:
creds = pickle.load(token)
# 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.pickle', 'wb') as token:
pickle.dump(creds, token)
service = build('gmail', 'v1', credentials=creds)
drive_service = build('drive', 'v3', credentials=creds)