web-dev-qa-db-ja.com

GmailAPIを使用してGmailから添付ファイルをダウンロードする

GmailAPIを使用してGmailデータとGoogle python apiクライアントにアクセスしています。

メッセージの添付ファイルを取得するためのドキュメントによると、Python用のサンプルを1つ提供しました

https://developers.google.com/gmail/api/v1/reference/users/messages/attachments/get

しかし、私が試したのと同じコードで、エラーが発生します:

_AttributeError: 'Resource' object has no attribute 'user'
_

エラーが発生している行:

_message = service.user().messages().get(userId=user_id, id=msg_id).execute()
_

だから私はusers()を置き換えてuser()を試しました

_message = service.users().messages().get(userId=user_id, id=msg_id).execute()
_

しかし、私は_part['body']['data']_で_for part in message['payload']['parts']_を取得していません

15
Rahul Kulhari

@Ericの回答を拡張して、ドキュメントからGetAttachments関数の次の修正バージョンを作成しました。

# based on Python example from 
# https://developers.google.com/gmail/api/v1/reference/users/messages/attachments/get
# which is licensed under Apache 2.0 License

import base64
from apiclient import errors

def GetAttachments(service, user_id, msg_id, prefix=""):
    """Get and store attachment from Message with given id.

    Args:
    service: Authorized Gmail API service instance.
    user_id: User's email address. The special value "me"
    can be used to indicate the authenticated user.
    msg_id: ID of Message containing attachment.
    prefix: prefix which is added to the attachment filename on saving
    """
    try:
        message = service.users().messages().get(userId=user_id, id=msg_id).execute()

        for part in message['payload']['parts']:
            if part['filename']:
                if 'data' in part['body']:
                    data=part['body']['data']
                else:
                    att_id=part['body']['attachmentId']
                    att=service.users().messages().attachments().get(userId=user_id, messageId=msg_id,id=att_id).execute()
                    data=att['data']
                file_data = base64.urlsafe_b64decode(data.encode('UTF-8'))
                path = prefix+part['filename']

                with open(path, 'w') as f:
                    f.write(file_data)
    except errors.HttpError, error:
        print 'An error occurred: %s' % error
33
Ilya V. Schurov

@ Ilya V. Schurovまたは@ Cam Tをフォローすると、添付ファイルを見逃す可能性があります。 -)回答、理由は、メールの構造がmimeTypeに基づいて異なる可能性があるためです。

この回答 に触発されて、これが問題への私のアプローチです。

import base64
from apiclient import errors

def GetAttachments(service, user_id, msg_id, store_dir=""):
    """Get and store attachment from Message with given id.
        Args:
            service: Authorized Gmail API service instance.
            user_id: User's email address. The special value "me"
                can be used to indicate the authenticated user.
            msg_id: ID of Message containing attachment.
            store_dir: The directory used to store attachments.
    """
    try:
        message = service.users().messages().get(userId=user_id, id=msg_id).execute()
        parts = [message['payload']]
        while parts:
            part = parts.pop()
            if part.get('parts'):
                parts.extend(part['parts'])
            if part.get('filename'):
                if 'data' in part['body']:
                    file_data = base64.urlsafe_b64decode(part['body']['data'].encode('UTF-8'))
                    #self.stdout.write('FileData for %s, %s found! size: %s' % (message['id'], part['filename'], part['size']))
                Elif 'attachmentId' in part['body']:
                    attachment = service.users().messages().attachments().get(
                        userId=user_id, messageId=message['id'], id=part['body']['attachmentId']
                    ).execute()
                    file_data = base64.urlsafe_b64decode(attachment['data'].encode('UTF-8'))
                    #self.stdout.write('FileData for %s, %s found! size: %s' % (message['id'], part['filename'], attachment['size']))
                else:
                    file_data = None
                if file_data:
                    #do some staff, e.g.
                    path = ''.join([store_dir, part['filename']])
                    with open(path, 'w') as f:
                        f.write(file_data)
    except errors.HttpError as error:
        print 'An error occurred: %s' % error
7
Todor

上記のコードをテストしましたが、機能しませんでした。そして、私は他の投稿のためにいくつかのものを更新しました。 WriteFileError

    import base64
    from apiclient import errors


    def GetAttachments(service, user_id, msg_id, prefix=""):
       """Get and store attachment from Message with given id.

       Args:
       service: Authorized Gmail API service instance.
       user_id: User's email address. The special value "me"
       can be used to indicate the authenticated user.
       msg_id: ID of Message containing attachment.
       prefix: prefix which is added to the attachment filename on saving
       """
       try:
           message = service.users().messages().get(userId=user_id, id=msg_id).execute()

           for part in message['payload'].get('parts', ''):
              if part['filename']:
                  if 'data' in part['body']:
                     data=part['body']['data']
                  else:
                     att_id=part['body']['attachmentId']
                     att=service.users().messages().attachments().get(userId=user_id, messageId=msg_id,id=att_id).execute()
                     data=att['data']
            file_data = base64.urlsafe_b64decode(data.encode('UTF-8'))
            path = prefix+part['filename']

            with open(path, 'wb') as f:
                f.write(file_data)

        except errors.HttpError as error:
            print('An error occurred: %s' % error)
6
f9n

それは間違いなく「users()」です。応答メッセージの形式は、使用する形式パラメーターに大きく依存します。デフォルト(FULL)を使用する場合、パーツにはpart ['body'] ['data']が含まれるか、データが大きい場合は、messages()。attachments()に渡すことができる「attachment_id」フィールドが含まれます。取得する()。

添付ファイルのドキュメントを見ると、次のことがわかります。 https://developers.google.com/gmail/api/v1/reference/users/messages/attachments

(これがメインメッセージのドキュメントページにも記載されていればいいでしょう。)

3
Eric D

上記のコードに次の変更を加えました。添付ドキュメントが含まれるすべてのメールIDで問題なく動作します。これが役立つことを願っています。これは、APIの例ではエラーキーが表示されるためです。

def GetAttachments(service, user_id, msg_id, store_dir):

"""Get and store attachment from Message with given id.

Args:
service: Authorized Gmail API service instance.
user_id: User's email address. The special value "me"
can be used to indicate the authenticated user.
msg_id: ID of Message containing attachment.
prefix: prefix which is added to the attachment filename on saving
"""
try:
    message = service.users().messages().get(userId=user_id, id=msg_id).execute()
    for part in message['payload']['parts']:
        newvar = part['body']
        if 'attachmentId' in newvar:
            att_id = newvar['attachmentId']
            att = service.users().messages().attachments().get(userId=user_id, messageId=msg_id, id=att_id).execute()
            data = att['data']
            file_data = base64.urlsafe_b64decode(data.encode('UTF-8'))
            print(part['filename'])
            path = ''.join([store_dir, part['filename']])
            f = open(path, 'wb')
            f.write(file_data)
            f.close()
except errors.HttpError, error:
    print 'An error occurred: %s' % error

添付ファイルのGoogle公式API

1
Cam T