개발 이야기/DB, 데이터분석, AI

gmail 첨부파일을 자동으로 가져오기

가끔.하늘 가온아 2021. 2. 3. 09:56
반응형

거래처에서 전달받는 데이터 중 엑셀 파일을 메일로 전달하는 곳이 있습니다. 

 

담당자는 이 파일을 받아 DB로 업로드 하는 작업을 수동으로 진행합니다. 

 

그 일을 덜고자 python으로 매일 해당 메일의 첨부파일을 자동으로 다운받아 업로드하는 프로그램을 만들어 주었습니다. 

 

여기서는 자동으로 메일의 첨부 파일을 다운로드하는 부분까지만 구현을 해보겠습니다. 

 

전체 소스코드는 이 곳을 참고하세요.

 

------------------------------------------------------------------------------

 

1. 개요

 테스트 환경 : windows 10, python 3.8

 필요한 패키지 :

 - 메일 클라이언트를 위해 imapclient , pyzmail(메일 내용 파싱) 사용

 - 스케쥴러 역할을 위해 apscheduler 사용

 

2. gmail 보안 설정

 gmail에 코드로 접근하기 위해서는 gmail에 사용되는 계정의 보안 단계를 낮추는 설정이 필요합니다. 이를 위한 가능한 별도의 계정을 생성하여 사용하시고 민감한 데이터를 주고 받는 경우에는 꼭 이 작업이 필요한지 내부 검토 후 사용하시기 바랍니다.

 

"Google 계정 관리 -> 보안 -> 보안 수준이 낮은 앱의 액세스" 항목으로 이동하세요.

하단의 "액세스 사용 설정"을 클릭하여 아래와 같이 앱 접근을 허용하시면 됩니다.

 

 3. 원하는 메일 샘플을 inbox에 두고 메일 정보와 첨부된 파일을 저장하는 테스트 해봅시다.

    m = imapclient.IMAPClient("imap.gmail.com", ssl=True)
    m.login("your_id","your_pw")
    
    #받은 메일함을 선택합니다.
    m.select_folder('INBOX')
    
    # "write_email_you_read" 이라는 메일에서 보낸 내용만 검색해서 메일의 uid를 가져옵니다.
    UIDs = m.search(['FROM', "write_email_you_read"])
    
    for uid in UIDs:
    	# 메일 내용을 가져옵니다.
    	raw_msg = m_fetch(uid, ['BODY[]'])
        
        # raw data를 읽기 쉽게 pyzmail로 변환합니다.
        # raw_msg[1]은 inbox에 있는 메일을 이야기 합니다.
        # 전체 메일함에서 읽는다면 1 대신 6번에서 접근해야 합니다. 
        # 전체 메일함에 있는 메일을 inbox로 옮겼어도 6번으로 접근해야 합니다. 
        msg = pyzmail.PyzMessage.factory(raw_msg[1][b'BODY[]'])
		for mp in msg.mailparts:
        	# 첨부된 파일 중 xls을 찾아봅니다.
        	if mp.filename != None and mp.filename.find('xls') != -1:
            	# 해당 파일 이름과 파일의 총 길이를 알아봅니다.
            	print(mp.filename, len(mp.get_payload()))

 

4. 정상적으로 출력된다면 이제 파일을 원하는 폴더에 저장하고 작업이 끝난 파일을 삭제해 보겠습니다

		# d drive에 email이라는 폴더를 만들어서 저장하겠습니다.
        file = open("d:/email/"+m.filename, "wb")
        file.write(mp.get_payload())
        file.close()
        
        # 이제 다운받은 파일을 백업을 위해 /saved라는 메일함으로 복사합니다.
        # saved라는 폴더가 없다면 만들거나 혹은 존재하는 폴더명을 입력해도 됩니다. 
        # print(m.list_folders()) 로 어떤 메일 폴더가 존재하는지 확인할 수 있습니다.
        m.copy(uid, "/saved")
        
        # 그리고 해당 메일은 삭제합니다. 주의!! 영구 삭제됩니다.
        m.delete_message(uid)
        m.expunge()

 

5. scheduler를 사용해 위 작업이 하루에 2번 실행되도록 합니다.

		# apscheduler에는 여러 설정 가능한 스케쥴러 타입이 존재합니다. 
        # 이 샘플에서는 메일에서 첨부 파일 다운로드하는 기능만 존재하므로 
        # blocking scheduler를 사용해 보겠습니다.
        scheduler = BlockingScheduler()

		# 메일 다운로드를 실행하는 코드가 doJob이라는 함수안에 있다고 가정합니다. 
        # 그리고 해당 함수를 12시간 마다 반복하여 실행합니다.
		scheduler.add_job(doJob, 'interval',hours=12)
        
		scheduler.start();

 

보안에 취약한 문제가 있으니 업무 환경을 고려해서 사용하시기 바랍니다.

 

반응형