如何将 Gmail API credentials.json 暴露给环境

How to expose Gmail API credentials.json to env

我正在 python 使用 google gmail api 库编写一个 gmail 数据查询项目,我正在使用 Gmail API credentials.json 文件。

如何将我的凭据存储在私有环境中,以便当其他人使用我的脚本时,他们不会自动使用我的 gmail credentials.json。

这是我试过的。 在我的 .env 文件中,我创建了一个变量 CRED

CRED={"installed":{"client_id":"##########-#########.apps.googleusercontent.com","project_id":"email-query-#######","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":"#############################","redirect_uris":["urn:ietf:wg:oauth:2.0:oob","http://localhost"]}}

之后,我写了下面的代码:

from __future__ import print_function
import os
import os.path
from googleapiclient.discovery import build
import httplib2
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request

def main():

    creds = None

    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:

            config = json.loads(os.environ['CRED']) 
            flow = InstalledAppFlow.from_client_config(config, 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)

    http = httplib2.Http()
    http = creds.authorize(http)
    service = build('gmail', 'v1', http=http) #  
    # Call the Gmail API to fetch INBOX
    results = service.users().messages().list(userId='me',labelIds = ['INBOX']).execute()
    messages = results.get('messages', [])

在 运行 代码之后,我得到以下错误:

<ipython-input-16-d58887cf8862> in <module>
    106 
    107 if __name__ == '__main__':
--> 108     main()

<ipython-input-16-d58887cf8862> in main()
     15             #creds = flow.run_local_server(port=0)
     16 
---> 17             config = json.loads(os.environ['CRED'])
     18             flow = InstalledAppFlow.from_client_config(config, SCOPES)
     19             creds = flow.run_local_server(port=0)

~/anaconda3/lib/python3.7/os.py in __getitem__(self, key)
    677         except KeyError:
    678             # raise KeyError with the original key value
--> 679             raise KeyError(key) from None
    680         return self.decodevalue(value)
    681 

KeyError: 'CRED'

我还要指出,我在 运行 编写代码之前从我的工作目录中删除了 credentials.json。

还有一件事,如果我将 credentials.json 文件和 运行 脚本留在工作目录中,我会收到错误消息:

 23 
     24     http = httplib2.Http()
---> 25     http = creds.authorize(http)
     26     service = build('gmail', 'v1', http=http) #
     27     # Call the Gmail API to fetch INBOX

AttributeError: 'Credentials' object has no attribute 'authorize'

我该怎么办?

您可以使用 os.getenv('GMAIL_API') 假设您的环境中已经有 'GMAIL_API' 变量。

以下是为每个环境添加变量的方法:

对于windows,您可以使用this

对于Linux,您可以使用this

我建议你的 credentials.json 来自 Python Quickstart Gamil API,我将本教程用作示例代码。推荐大家使用pipenv这样环境配置不会太复杂

首先你需要安装你的虚拟环境:

pip install pipenv
pipenv install google-api-python-client google-auth-httplib2 google-auth-oauthlib

如果你不喜欢使用pipenv或者你不知道如何配置虚拟环境,你可以安装dotenv包:

pip install python-dotenv

然后将这些添加到代码的头部:

from dotenv import load_dotenv;
load_dotenv()

在您的文件夹根目录下添加名为 .env 的文件:

CRED="Whole JSON String in credentials.json"

.env 文件中的环境变量将在您 运行 来自 pipenv run python script.py 的 python 文件时加载。

加载原始代码块credentials.json:

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)

应修改为:

if not creds or not creds.valid:
    if creds and creds.expired and creds.refresh_token:
        creds.refresh(Request())
    else:
        config = json.loads(os.environ['CRED'])
        flow = InstalledAppFlow.from_client_config(
            config, SCOPES)
        creds = flow.run_local_server(port=0)

运行 你的程序 pipenv run python script.py 你会看到一个提示 Loading .env environment variables….

如果您正在使用版本控制,您可以将 .env 添加到 .gitignore,并添加一个名为 .env.template 的文件,其中只留下一个 CRED=

更多细节你可以阅读pipenv and Google authlib的文档。