Download Attachments from gmail using Gmail API
Expanding @Eric answer, I wrote the following corrected version of GetAttachments function from the docs:
# based on Python example from # https://developers.google.com/gmail/api/v1/reference/users/messages/attachments/get# which is licensed under Apache 2.0 Licenseimport base64from apiclient import errorsdef GetAttachments(service, user_id, msg_id): """Get and store attachment from Message with given id. :param service: Authorized Gmail API service instance. :param user_id: User's email address. The special value "me" can be used to indicate the authenticated user. :param msg_id: ID of Message containing attachment. """ 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 = part['filename'] with open(path, 'w') as f: f.write(file_data) except errors.HttpError, error: print 'An error occurred: %s' % error
You can still miss attachments by following @Ilya V. Schurov or @Cam T answers, the reason is because the email structure can be different based on the mimeType
.
Inspired by this answer, here is my approach to the problem.
import base64from apiclient import errorsdef 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
i tested codes above and doesn't worked. And i updated some stuff for other posts. 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)