2014-09-14 16 views
7

Sto utilizzando l'API di Gmail per accedere ai miei dati gmail e al client API python di google.Download di allegati da Gmail utilizzando l'API di Gmail

Secondo la documentazione per ottenere l'allegato del messaggio hanno dato un campione per Python

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

ma lo stesso codice che ho provato allora sto ottenendo errore:

AttributeError: 'Resource' object has no attribute 'user' 

linea dove mi trovo ottenendo errore:

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

Così ho provato users() sostituendo user()

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

ma non ricevo part['body']['data'] in for part in message['payload']['parts']

risposta

2

E 'sicuramente "gli utenti()". Il formato del messaggio di risposta dipende in gran parte dal parametro di formato che si utilizza. Se si utilizza il valore predefinito (FULL), le parti avranno parte ['body'] ['data'] o, quando i dati sono grandi, con un campo "attachment_id" che è possibile passare a messages(). Attachments(). ottenere().

Se si guardano le allegati documenti vedrete questo: https://developers.google.com/gmail/api/v1/reference/users/messages/attachments

(. Sarebbe bello se questo è stato anche menzionato nella pagina messaggi principali documenti anche)

20

Espansione risposta @Eric, ho scritto la seguente versione corretta della funzione GetAttachments dalla documentazione:

# 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 
+0

Per coloro che non sono in grado di scrivere nel file, utilizzare 'wb' perché a volte i dati non è stringa è in realtà binaria. – Shashank

0

ho fatto le seguenti modifiche di codice di cui sopra e funziona assolutamente bene per ogni e-mail id contiene documenti allegati, i spero che questo possa aiutare perché con l'esempio API otterrai una chiave di errore.

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, 'w') 
      f.write(file_data) 
      f.close() 
except errors.HttpError, error: 
    print 'An error occurred: %s' % error 

Google Official API for Attachments

2

Si può ancora perdere allegati seguendo @Ilya V. Schurov o @Cam T risposte, il motivo è perché la struttura e-mail può essere diversa in base alla mimeType.

Ispirato da this answer, ecco il mio approccio al problema.

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 
+0

Come ti stai comportando con quegli allegati mancati? Tutto quello che vedo è un 'file_data = None' che quindi non fa nulla con esso. – guival

+0

Dai un'occhiata all'istruzione 'while' da dove proviene la differenza. L'ultimo 'else: file_data = None' è solo per la sicurezza del codice. – Todor

+0

ah, capisco, la differenza è che si tratta anche dei dati nel livello più alto ('payload ['body'] ['data']') mentre altre risposte guardano solo il corpo all'interno delle parti ('payload [ 'parti'] ') – guival

1

ho testato i codici sopra e non ha funzionato. E ho aggiornato alcune cose per altri post. 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) 
Problemi correlati