У меня есть раздел моего программного обеспечения, которое недавно перестало работать правильно. Программа должна позволять пользователю загружать PDF-файл в нашу учетную запись на Google Диске, а затем программа отправит электронное письмо некоторым другим людям в нашем офисе для просмотра. Это работало до понедельника, когда загрузки и электронные письма от моих пользователей начали поступать из моей учетной записи Google, а не из их собственной. Это случается не со всеми, может быть, от 1/3 до 1/2 пользователей сталкиваются с этой проблемой. Иногда программа отправляет электронное письмо от имени меня, а иногда выдает ошибку <HttpError 403 при запросе https://gmail.googleapis.com/gmail/v1/users/username/messages/send?alt=json. 'Делегирование отклонено для '[email protected]'>. Поскольку ничего не изменилось в моих функциях загрузки и отправки электронной почты, я думаю, что это связано с разрешениями или тем, как программа распространяется? Любое понимание будет оценено.
Я написал все на python3 и скомпилировал exe для распространения среди моей команды с помощью pyinstaller.
pyinstaller --onefile path/to/code.py
Вещи, которые я устал устранять: запустить от имени администратора пользователи перезагружали свои ПК У меня был кто-то из моей команды, который запускал py-файл напрямую, и это работало правильно. Первоначально у меня был --hidden-import='googleapiclient' для pyinstaller, который я удалил Первоначально в части электронной почты у меня был userId='me', и я изменил его, чтобы получить фактический адрес электронной почты пользователя. (Идея того, что pyinstaller блокирует «меня» как мою личную электронную почту. Этот код запускается после загрузки, так что, похоже, это не проблема.)
Соответствующий код загрузки на случай, если кто-то обнаружит проблему:
self.SCOPES = ['https://www.googleapis.com/auth/gmail.modify',
'https://www.googleapis.com/auth/spreadsheets',
'https://www.googleapis.com/auth/drive']
credentials.json:
{
"installed":{
"client_id":"client_id.apps.googleusercontent.com",
"project_id":"project_ID",
"auth_uri":"https://accounts.google.com/o/oauth2/auth",
"token_uri":"https://oauth2.googleapis.com/token",
"auth_provider_x509_cert_url":"https://www.googleapis.com/oauth2/v1/certs",
"client_secret":"secret_code",
"redirect_uris":[
"urn:ietf:wg:oauth:2.0:oob",
"http://localhost"
]
}
}
def upload(self, letterfile, plansfile, parentdrive):
# Check for json credentials for google drive and API access
try:
x = os.stat(os.path.join(self.prefs['data'], 'token.json'))
result = time.time() - x.st_mtime
if result > 129600:
os.remove(os.path.join(self.prefs['data'], 'token.json'))
except:
pass
creds = None
jsonpath = os.path.join(self.prefs['data'], 'token.json')
if os.path.exists(jsonpath):
creds = Credentials.from_authorized_user_file(jsonpath,
self.SCOPES)
# If there are no (valid) credentials available, let the user log in.
try:
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(
os.path.join(self.prefs['data'], 'credentials.json'),
self.SCOPES)
creds = flow.run_local_server(port=0)
# Save the credentials for the next run
with open(os.path.join(self.prefs['data'], 'token.json'), 'w') as token:
token.write(creds.to_json())
except BaseException as e:
print(f'Error with credentials.json check: {e}')
# Build the services to access the Gmail API and Drive API
driveService = build('drive', 'v3', credentials=creds)
file = letterfile
folderLink = f'https://drive.google.com/drive/folders/{parentdrive}'
# Work with different attachment formats (Text, Image, or PDF). This
# will need to be a FOR loop to iterate through all imported files
# from the app
content_type, encoding = mimetypes.guess_type(file)
if content_type is None or encoding is not None:
content_type = 'application/octet-stream'
main_type, sub_type = content_type.split('/', 1)
if main_type == 'text':
with open(file, 'rb') as fp:
msg = MIMEText(fp.read(), _subtype=sub_type)
fp.close()
elif main_type == 'image':
with open(file, 'rb') as fp:
msg = MIMEImage(fp.read(), _subtype=sub_type)
fp.close()
else:
with open(file, 'rb') as fp:
msg = MIMEBase(main_type, sub_type)
msg.set_payload(fp.read())
fp.close()
calcfile = os.path.basename(letterfile)
try:
planname = os.path.basename(plansfile)
except BaseException as e:
planname = []
for planfile in plansfile:
planname.append(os.path.basename(planfile))
# Upload file to Drive Project Folder
file_metadata = {'name': calcfile, 'parents': [parentdrive]}
media = MediaFileUpload(letterfile,
mimetype=content_type,
resumable=True)
tempcalcfile = driveService.files().create(body=file_metadata,
media_body=media,
supportsAllDrives=True).execute()
try:
plan_metadata = {'name': planname, 'parents': [parentdrive]}
media = MediaFileUpload(plansfile,
mimetype=content_type,
resumable=True)
tempplansfile = driveService.files().create(body=plan_metadata,
media_body=media,
supportsAllDrives=True).execute()
except BaseException as e:
for i in range(len(planname)):
plan_metadata = {'name': planname[i], 'parents': [parentdrive]}
media = MediaFileUpload(plansfile[i],
mimetype=content_type,
resumable=True)
tempplansfile = driveService.files().create(body=plan_metadata,
media_body=media,
supportsAllDrives=True).execute()
print('Files sent to Drive Folder through API')





У меня была папка, в которой хранились учетные данные.json, мой файл token.json и некоторые другие файлы, которые были распространены среди моей команды. Я случайно делюсь с ними МОИМ файлом token.json, поэтому, когда Google Oauth2 запустился, он прочитал файл как я, а не как пользователь.
Моя команда удалила файл token.json, что вызвало повторную авторизацию пользователя, создание нового token.json и устранило проблему.
Выполняет ли ваш процесс делегирование электронной почты? Можете ли вы попробовать изменить настройку для затронутых пользователей.