使用 Python 从 gmail api 下载附件

发布于 2025-01-20 08:25:20 字数 2446 浏览 0 评论 0原文

我正在尝试使用 python 从 gmail 下载附件,但无法从邮件中获取附件 ID。请在下面找到我的代码

import os.path
from google.auth.transport.requests import Request
from google.oauth2.credentials import Credentials
from google_auth_oauthlib.flow import InstalledAppFlow
from googleapiclient.discovery import build
from googleapiclient.errors import HttpError


def get_gmail_service():
    SCOPES = ['https://www.googleapis.com/auth/gmail.readonly']
    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.
    if os.path.exists('token.json'):
        creds = Credentials.from_authorized_user_file('token.json', SCOPES)
        # 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.json', 'w') as token:
            token.write(creds.to_json())

        try:
            # Call the Gmail API
            service = build('gmail', 'v1', credentials=creds)
            return service

        except HttpError as error:
        # TODO(developer) - Handle errors from gmail API.
            print(f'An error occurred: {error}')

def get_email_list():
    service = get_gmail_service()
    results = service.users().messages().list(userId='me',q='from:[email protected] is:read').execute()
    # print(results.get('messages',[])[0].get('id',[]))
    return results.get('messages', [])[0].get('id', [])
    # return results.get('messages',[])

def get_email_content(message_id):
    service = get_gmail_service()
    attach = service.users().messages().get(userId='me',id =message_id).execute()
    attach_id = attach.get('payloads',[]).get('parts',[]).get('body',[])
    data = service.users().messages().get(userId='me',id = message_id).execute()
    return attach_id

if __name__ == '__main__':
    # get_email_list()
    print(get_email_content(get_email_list()))

请更正我的代码,以便我可以使用 gmail api 下载附件。

I am trying to download the attachment from gmail using the python and I am not able to fetch the attachment id from my mail. Please find my code below

import os.path
from google.auth.transport.requests import Request
from google.oauth2.credentials import Credentials
from google_auth_oauthlib.flow import InstalledAppFlow
from googleapiclient.discovery import build
from googleapiclient.errors import HttpError


def get_gmail_service():
    SCOPES = ['https://www.googleapis.com/auth/gmail.readonly']
    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.
    if os.path.exists('token.json'):
        creds = Credentials.from_authorized_user_file('token.json', SCOPES)
        # 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.json', 'w') as token:
            token.write(creds.to_json())

        try:
            # Call the Gmail API
            service = build('gmail', 'v1', credentials=creds)
            return service

        except HttpError as error:
        # TODO(developer) - Handle errors from gmail API.
            print(f'An error occurred: {error}')

def get_email_list():
    service = get_gmail_service()
    results = service.users().messages().list(userId='me',q='from:[email protected] is:read').execute()
    # print(results.get('messages',[])[0].get('id',[]))
    return results.get('messages', [])[0].get('id', [])
    # return results.get('messages',[])

def get_email_content(message_id):
    service = get_gmail_service()
    attach = service.users().messages().get(userId='me',id =message_id).execute()
    attach_id = attach.get('payloads',[]).get('parts',[]).get('body',[])
    data = service.users().messages().get(userId='me',id = message_id).execute()
    return attach_id

if __name__ == '__main__':
    # get_email_list()
    print(get_email_content(get_email_list()))

Please correct my code so that I can download the attachment using the gmail api.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

ぃ双果 2025-01-27 08:25:20

这段代码有两个主要问题。

  1. results.get() 方法返回 消息MessagePart 对象。因此,您只需使用一次 get() 方法即可获取完整的对象,然后您就可以定位您想要的对象的特定部分。

    例如。 results.get('messages', [])[0]['id']

  2. 电子邮件的有效负载可以是多部分的(这意味着“部分”将是 <代码>MessagePart 对象)。因此,我们需要迭代以获得包含文件的“消息部分”。在本例中,我们可以检查 MessagePart 对象是否有文件名。

    parts = attach.get('payload',[])['parts']
    
    for i in parts:
        if( i['filename'] ):
            return i['body']['attachmentId'] 

So After taking care of these two issues, this is the new code:

import os.path
from google.auth.transport.requests import Request
from google.oauth2.credentials import Credentials
from google_auth_oauthlib.flow import InstalledAppFlow
from googleapiclient.discovery import build
from googleapiclient.errors import HttpError


def get_gmail_service():
    SCOPES = ['https://www.googleapis.com/auth/gmail.readonly']
    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.
    if os.path.exists('token.json'):
        creds = Credentials.from_authorized_user_file('token.json', SCOPES)
        # 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.json', 'w') as token:
            token.write(creds.to_json())

        try:
            # Call the Gmail API
            service = build('gmail', 'v1', credentials=creds)
            return service

        except HttpError as error:
        # TODO(developer) - Handle errors from gmail API.
            print(f'An error occurred: {error}')

def get_email_list():
    service = get_gmail_service()
    results = service.users().messages().list(userId='me',q='from:[email protected] is:read').execute()
    # print(results.get('messages',[])[0]['id'] )
    return results.get('messages', [])[0]['id']
    # return results.get('messages',[])

def get_email_content(message_id):
    print(message_id)
    service = get_gmail_service()
    data = service.users().messages().get(userId='me',id = message_id).execute()

    attach = service.users().messages().get(userId='me',id =message_id).execute()
    parts = attach.get('payload',[])['parts']
    
    for i in parts:
        if( i['filename'] ):
            return i['body']['attachmentId'] 

if __name__ == '__main__':
    # get_email_list()
    print(get_email_content(get_email_list()))

我希望这能回答您的问题!

There are two main issues with this code.

  1. results.get() method either returns a Message or MessagePart Object. So you only need to use the get() method once to get the complete object and then you can target the specific part of the object you want.

    For Example. results.get('messages', [])[0]['id']

  2. A payload for an email can be multipart (which means that "parts" will be an array of MessagePart objects). So we need to iterate over to get a "message part" that has a file. In this case, we can check if the MessagePart object has a filename.

    parts = attach.get('payload',[])['parts']
    
    for i in parts:
        if( i['filename'] ):
            return i['body']['attachmentId'] 

So After taking care of these two issues, this is the new code:

import os.path
from google.auth.transport.requests import Request
from google.oauth2.credentials import Credentials
from google_auth_oauthlib.flow import InstalledAppFlow
from googleapiclient.discovery import build
from googleapiclient.errors import HttpError


def get_gmail_service():
    SCOPES = ['https://www.googleapis.com/auth/gmail.readonly']
    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.
    if os.path.exists('token.json'):
        creds = Credentials.from_authorized_user_file('token.json', SCOPES)
        # 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.json', 'w') as token:
            token.write(creds.to_json())

        try:
            # Call the Gmail API
            service = build('gmail', 'v1', credentials=creds)
            return service

        except HttpError as error:
        # TODO(developer) - Handle errors from gmail API.
            print(f'An error occurred: {error}')

def get_email_list():
    service = get_gmail_service()
    results = service.users().messages().list(userId='me',q='from:[email protected] is:read').execute()
    # print(results.get('messages',[])[0]['id'] )
    return results.get('messages', [])[0]['id']
    # return results.get('messages',[])

def get_email_content(message_id):
    print(message_id)
    service = get_gmail_service()
    data = service.users().messages().get(userId='me',id = message_id).execute()

    attach = service.users().messages().get(userId='me',id =message_id).execute()
    parts = attach.get('payload',[])['parts']
    
    for i in parts:
        if( i['filename'] ):
            return i['body']['attachmentId'] 

if __name__ == '__main__':
    # get_email_list()
    print(get_email_content(get_email_list()))

I hope this answers your question!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文