본문 바로가기

파이썬 학습 과정/생활속의 파이썬_응용편

"자동화 해킹: 이메일 첨부파일을 드라이브로 쏘는 파이썬 트릭"

반응형

Gmail에서 수신된 이메일의 첨부 파일을 Google Drive에 저장하는 작업을 파이썬으로 구현하는 예제입니다. 이를 위해 google-api-python-client, google-auth-httplib2, google-auth-oauthlib, gmail-api, google-drive-api 라이브러리를 사용합니다.

이메일 첨부 파일이 구글 드라이브에 저장되는 자동화 과정을 표현한 이미지
이메일 첨부 파일이 구글 드라이브에 저장되는 자동화 과정을 표현한 이미지

사전 준비

  1. Google API 사용 설정: Google Cloud Platform에서 프로젝트를 생성하고 Gmail API와 Google Drive API를 사용 설정합니다.
  2. OAuth 2.0 자격 증명: OAuth 2.0 자격 증명을 설정하고 credentials.json 파일을 다운로드합니다.

Python 코드


import os.path
import base64
from google.oauth2.credentials import Credentials
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request
from googleapiclient.discovery import build
from googleapiclient.errors import HttpError
import io
from googleapiclient.http import MediaIoBaseDownload, MediaFileUpload

# Gmail API와 Google Drive API의 인증 범위
SCOPES = ['https://www.googleapis.com/auth/gmail.readonly', 'https://www.googleapis.com/auth/drive.file']

def authenticate_gmail():
    """Gmail API 인증 및 서비스 생성"""
    creds = None
    if os.path.exists('token.json'):
        creds = Credentials.from_authorized_user_file('token.json', SCOPES)
    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)
        with open('token.json', 'w') as token:
            token.write(creds.to_json())
    try:
        service = build('gmail', 'v1', credentials=creds)
        return service
    except HttpError as error:
        print(f'An error occurred: {error}')
        return None

def authenticate_drive():
    """Google Drive API 인증 및 서비스 생성"""
    creds = None
    if os.path.exists('token_drive.json'):
        creds = Credentials.from_authorized_user_file('token_drive.json', SCOPES)
    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)
        with open('token_drive.json', 'w') as token:
            token.write(creds.to_json())
    try:
        service = build('drive', 'v3', credentials=creds)
        return service
    except HttpError as error:
        print(f'An error occurred: {error}')
        return None

def download_attachment(service, user_id, msg_id, store_dir):
    """Gmail에서 첨부 파일 다운로드"""
    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 = os.path.join(store_dir, part['filename'])
                with open(path, 'wb') as f:
                    f.write(file_data)
                return path
    except HttpError as error:
        print(f'An error occurred: {error}')

def upload_to_drive(service, file_path):
    """Google Drive에 파일 업로드"""
    file_metadata = {'name': os.path.basename(file_path)}
    media = MediaFileUpload(file_path, mimetype='application/octet-stream')
    try:
        file = service.files().create(body=file_metadata, media_body=media, fields='id').execute()
        print(f'File ID: {file.get("id")}')
    except HttpError as error:
        print(f'An error occurred: {error}')

def main():
    gmail_service = authenticate_gmail()
    drive_service = authenticate_drive()

    if gmail_service and drive_service:
        user_id = 'me'
        results = gmail_service.users().messages().list(userId=user_id, q='has:attachment', maxResults=1).execute()
        messages = results.get('messages', [])

        if not messages:
            print('No messages found.')
        else:
            for message in messages:
                msg_id = message['id']
                file_path = download_attachment(gmail_service, user_id, msg_id, 'downloads')
                if file_path:
                    upload_to_drive(drive_service, file_path)

if __name__ == '__main__':
    main()

주요 단계 설명

  1. Gmail API와 Google Drive API 인증: 사용자의 Gmail과 Google Drive에 접근하기 위해 OAuth 2.0 인증을 수행합니다.
  2. 첨부 파일 다운로드: 새로운 이메일이 수신되면 첨부 파일을 다운로드합니다.
  3. 파일 업로드: 다운로드한 첨부 파일을 Google Drive의 특정 폴더에 업로드합니다.

필요한 패키지 설치


pip install --upgrade google-api-python-client google-auth-httplib2 google-auth-oauthlib

이 코드는 첨부 파일이 있는 새로운 이메일을 검색하고, 해당 첨부 파일을 로컬에 저장한 후 Google Drive에 업로드합니다. 필요한 경우 적절한 수정과 설정을 통해 원하는 기능을 구현할 수 있습니다.

반응형