개발하자

Gmail API(피톤)를 이용하여 메시지 본문 전체를 검색하는 방법

Cuire 2023. 10. 14. 01:54
반응형

Gmail API(피톤)를 이용하여 메시지 본문 전체를 검색하는 방법

나는 gmail api를 이용하여 메일의 전체 메시지 본문을 추출하고 싶다. 지금은 '스니펫'을 사용하고 있지만 전체 텍스트가 필요합니다. 검색해보니 페이로드와 관련이 있는 것 같은데 방법을 이해하지 못했어요. 누가 예를 보여줄 수 있나요? 또한 나는 파이썬을 통해 Gmail api를 사용하고 있다.




Python 스니펫이 있는 문서에서 사용:

import base64
import email
from apiclient import errors

def GetMessage(service, user_id, msg_id):

  try:
    message = service.users().messages().get(userId=user_id, id=msg_id).execute()
    print 'Message snippet: %s' % message['snippet']
    return message
  except errors.HttpError, error:
    print 'An error occurred: %s' % error

def GetMimeMessage(service, user_id, msg_id):

  try:
    message = service.users().messages().get(userId=user_id, id=msg_id, format='raw').execute()
    print 'Message snippet: %s' % message['snippet']
    msg_str = base64.urlsafe_b64decode(message['raw'].encode('ASCII'))
    mime_msg = email.message_from_string(msg_str)

    return mime_msg
  except errors.HttpError, error:
    print 'An error occurred: %s' % error

액세스하려고 하는 것은 또는 더 멀리 가고 싶은 경우 입니다.




누귀가 말한 것처럼 하지만 나는 토막이 온 몸을 되돌려주지 않는다는 것을 알았다

토막글이 200~chars를 초과하면 payload.body.data 아래에서 payload.body.data를 사용하여 전신을 찾을 수 있습니다

단점은 base64 encoded를 받고 있어서 해독해야 한다는 것입니다 :)

다음 코드가 효과가 있을 것이다

import base64  
mail = service.users().messages().get(userId=user_id, id=id, format="full").execute()

def parse_msg(msg):
    if msg.get("payload").get("body").get("data"):
        return base64.urlsafe_b64decode(msg.get("payload").get("body").get("data").encode("ASCII")).decode("utf-8")
    return msg.get("snippet") 



gmail api docs는 메시지 객체 구조로서 전체 메시지 본문을 반환하는 방법을 보여주는 샘플 코드를 제공한다. 그러나 그들이 제공한 코드는 파이썬3에서는 작동하지 않는다. 파이썬3에서 이것을 하기 위해 사용하고 싶다면, 그들을 로 변경해야 한다. 정확히 어떤 모듈이 이것을 변경하여 이 문제가 발생했는지는 확실하지 않지만, 아래 코드는 나에게 잘 작동한다

import base64
import email

message = gmail_conn.users().messages().get(userId=u_id, id=m_id, format='raw').execute()
msg_str = base64.urlsafe_b64decode(message['raw'].encode('ASCII'))
mime_msg = email.message_from_bytes(msg_str)

print(mime_msg)



나는 이메일 본문 전체를 추출하는 스크립트를 작성했다

import base64
import email


class GmailAPI():
    def get_service():
        ## You can get the gmail service snippet from here
        # https://developers.google.com/gmail/api/quickstart/python
        pass

class GmailParser():
    def data_encoder(self, text):
            if text and len(text)>0:
                message = base64.urlsafe_b64decode(text.encode('UTF8'))
                message = str(message, 'utf-8')
                message = email.message_from_string(message)
                return message
            else:
                return None
        

    def read_message(self, content)->str:
        import copy
        if content.get('payload').get('parts', None):
            parts = content.get('payload').get('parts', None)
            sub_part = copy.deepcopy(parts[0])
            while sub_part.get("mimeType", None) != "text/plain":
                try:
                    sub_part = copy.deepcopy(sub_part.get('parts', None)[0])
                except Exception as e:
                    break
            return self.data_encoder(sub_part.get('body', None).get('data', None)).as_string()
        else:
            return content.get("snippet")

gmail_parser = GmailParser()
gmail_service = GmailAPI()
mail = gmail_service.users().messages().list(userId='me', labelIds=['INBOX']).execute()
messages = mail.get('messages')
for email in messages:
    message = gmail_service.users().messages().get(userId='me', id=email['id'], format="full").execute()
    data = gmail_parser.read_message(content=message)



이제, 당신은 분명히 이렇게 할 수 있습니다:

def main():
    service = build('gmail', 'v1', credentials=creds)
    for message in service.users().messages().list(userId=...).execute()['messages']:
        print(parse_msg(
            service.users().messages().get(userId='me', id=message['id'], format='raw').execute()
        ))

def parse_msg(msg):
    return base64.urlsafe_b64decode(msg['raw'].encode('ASCII')).decode('utf-8')

하지만 당신이 이런 식으로 데이터를 너무 많이 얻는 것 같아서 이렇게 하기 시작했어요:

def main():
    service = build('gmail', 'v1', credentials=creds)
    for message in service.users().messages().list(userId='me').execute()['messages']:
        print(parse_msg(
            service.users().messages().get(userId=..., id=message['id'], format='full').execute()
        ))

def parse_msg(msg):
    payload = msg['payload']
    if data := payload['body'].get('data'):
        return parse_data(data)

    return ''.join(parse_data(part['body']['data']) for part in payload['parts'])

def parse_data(data):
    return base64.urlsafe_b64decode(data.encode('ASCII')).decode('utf-8')

위에서 에 의해 수정된 코드의 버전을 볼 수 있습니다. 이렇게 수정하면 모든 페이로드 데이터를 일관성 있게 얻을 수 있다고 생각합니다.


반응형