#python #google-api #google-oauth #gmail-api #google-api-php-client
Вопрос:
Я переписываю программу, которой нужна возможность отправлять и получать электронные письма. Старая версия работает автономно на рабочем столе и использует SMTP и POP3 для отправки и получения от моего имени с помощью учетной записи gmail. Это нормально, но в последнее время многие отправленные электронные письма оказались в папках нежелательной почты. Итак, я хотел бы получить более надежный способ «отправки от имени» пользователя (меня). Новая версия представляет собой веб-приложение, а не настольную программу, поэтому действия по электронной почте выполняются на стороне сервера, и я пытаюсь использовать Gmail API.
Я застрял на несколько дней из-за невозможности получить маркер доступа к API («недопустимый маркер») при запуске процесса на сервере. Вот что я сделал:
- Используйте консоль облачной платформы Google для создания/загрузки файла учетных данных.json
- Используйте код python «быстрый запуск» для успешного тестирования авторизации пользователя, сохраняя токены в виде маркера файла.json и отправить тестовое сообщение
- Включите аналогичный код в мою программу, но запустите его в качестве теста из командной строки > успешно!
- Скопируйте всю папку на мой сервер и с помощью SSH-терминала запустите ее снова в качестве теста из командной строки > Успешно (включая использование маркера обновления)!
- Запустите его как веб-приложение (WSGI Python), и он завершится неудачей.
Заметив, что владельцем задачи не являюсь я, когда она запускается как веб-приложение на терминале SSH, я сменил пользователя на «www-данные», повторил тест и выдал ошибку (cred.valid == False) после
creds = Credentials.from_authorized_user_file('token.json', scopes=SCOPES)
В результате запускается поток аутентификации пользователя, который останавливается, поскольку его нельзя использовать удаленно (я полагаю).
Я позаботился о том, чтобы все файлы в папке были одинаково доступны обоим пользователям (www-data и ben). Может ли кто-нибудь подсказать мне, что мне нужно сделать, чтобы заставить его работать с пользователем «www-данные»?
def get_credentials():
# If modifying these scopes, delete the file token.json.
SCOPES = ['https://www.googleapis.com/auth/gmail.readonly','https://www.googleapis.com/auth/gmail.send']
creds = None
# The file token.json stores the user's access and refresh tokens, and is
# created automatically when the authorization flow completes for the first
# time.
logging("In get_credentials. Python version: " sys.version )
if os.path.exists('token.json'):
logging("Using token.json")
with open('token.json',"r",encoding="utf-8") as fi:
s = fi.read()
logging( s )
logging( str(os.environ))
creds = Credentials.from_authorized_user_file('token.json', scopes=SCOPES)
logging("Creds " str(creds))
logging(str(creds.refresh_token) " " str( creds.expired) " " str( creds.valid))
# If there are no (valid) credentials available, let the user log in.
if not creds or not creds.valid:
logging("No valid credentials found")
if creds and creds.expired and creds.refresh_token:
logging("Going for a refresh")
creds.refresh(Request())
else:
logging("Going for live authentication flow!")
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.json', 'w') as token:
token.write(creds.to_json())
logging("Saved token.json")
service = build('gmail', 'v1', credentials=creds)
return service
Ответ №1:
Проблема, с которой вы столкнулись, заключается в том, что вы используете InstalledAppFlow. Это приведет к появлению экрана согласия на компьютере, на котором выполняется код, а затем сохранит токен обновления и токен доступа в файле token.json.
Что вы могли бы сделать, так это запустить его один раз локально, чтобы убедиться, что этот токен.создается json, а затем убедитесь, что при загрузке его на сервер этот токен.также загружается json.
Помните, что, если ваше приложение не настроено на производство, ваши токены обновления будут работать только в течение семи дней, поэтому вам нужно будет повторно авторизовать его локально один раз в неделю.
Комментарии:
1. Спасибо за быстрый ответ! Я запустил его локально, чтобы создать токен. json и включил этот файл при загрузке на сервер. Вот как все прошло нормально в качестве теста командной строки на сервере. Я не думаю, что смогу одобрить заявку как «производственную», поэтому ограничение на семь дней будет проблемой. Есть ли лучший подход?
2. Токены обновления для приложений, находящихся в процессе тестирования, не обновляются только в течение семи дней. Затем вам нужно будет снова авторизовать его.