Language/Python

Python - poplib, POP3 를 통한 이메일 수신

TechNote.kr 2018. 6. 15. 00:12
728x90

이메일을 웹 Interface가 아닌 별도의 프로그램을 통해 수신하기 위해서는 POP3 혹은 IMAP 을 사용하여야 한다. 가볍게는 POP3가 많이 사용되고, 좀 더 구체적인 기능을 위해서는 IMAP을 사용하면 된다. 


python에서 POP3을 사용해 이메일 수신하는 방법



python2 : https://docs.python.org/2/library/poplib.html

python3 : https://docs.python.org/3/library/poplib.html


python2나 python3나 POP3를 위한 python library - poplib 를 가지고 있다. 


간단하게 네이버 메일에서 POP3를 통해 이메일을 수신하는 코드를 살펴보자.


import getpass, poplib

M = poplib.POP3_SSL('pop.naver.com',995)
M.user("네이버 아이디")
M.pass_("네이버 비밀번호")

numMessages = len(M.list()[1])
for i in range(numMessages):
    for j in M.retr(i+1)[1]:
        print j


M = poplib.POP3_SSL('pop.naver.com',995)
제일 먼저 poplib.POP3_SSL 을 통해 M 이라는 이름의 poplib instance를 생성한다. 



M.user("네이버 아이디")

M.pass_("네이버 비밀번호")

이렇게 생성된 instance에 .user 를 통해 아이디, .pass_ 를 통해 비밀번호를 입력한다. 



numMessages = len(M.list()[1])
M.list() 만 출력해 보면 아래와 같은 내용을 가지고 있다. 


('+OK 7640 visible messages (1032060931 octets)', ['1 2512', '2 4029571', '3 4249', '4 2795', '5 3678', '6 3382', '7 118482', .......... '7635 17297', '7636 8183', '7637 9044', '7638 79023', '7639 26933', '7640 32894'], 88989)


(response, ['mesg_num octets', ...], octets) 형식의 메세지 리스트인데, 이 중 가운데(M.list()[1]) 실제 메세지 리스트 항목의 수(len) 을 구해 실제 POP3로 가져올 수 있는 이메일의 수를 구할 수 있다. 



for i in range(numMessages):

    for j in M.retr(i+1)[1]:

        print j

앞서 구한 이메일의 수를 1부터 순차적으로 .retr 을 통해 전체 메세지를 하나씩 가져온다. [range 함수] 를 사용하게 되면 0부터 인자로 넣은 수 -1 까지 표시하게 된다. 즉 range(3) 이라고 하면 [0, 1, 2] 를 의미하는 것이다. 


따라서 message num가 1부터 시작하기 때문에 M.retr할 때 인자는 i+1을 넘겨주게된다. 


M.ret(i+1) 만 찍어보면 다음과 같다. 


('+OK 2512 octets ', ['Received: (qmail 5774 invoked from network); 2 Mar 2007 01:57:41 -0000', 'Received: from unknown (HELO nhn403.naver.com) (220.73.146.166)', '  by 0 wit ...............3_01C75CB9.910FB7A0--', '', '', '', '', ''], 2516)

(response, ['line', ...], octets) 형식의 메세지이고, 실제 메세지는 두번째 인자에 줄별로 나뉘어 들어있다. 

따라서 M.retr(i+1)[1] 를 loop 돌아 출력하게 되면 실제 메세지(MIME 형식의 raw email message)를 출력하게 되는 것이다. 



Troubleshooting



poplib.error_proto: line too long


Traceback (most recent call last):
  File "pop3.py", line 44, in 
    raw_email = b"\n".join(M.retr(mList+1)[1])
  File "/usr/lib/python2.7/poplib.py", line 232, in retr
    return self._longcmd('RETR %s' % which)
  File "/usr/lib/python2.7/poplib.py", line 167, in _longcmd
    return self._getlongresp()
  File "/usr/lib/python2.7/poplib.py", line 152, in _getlongresp
    line, o = self._getline()
  File "/usr/lib/python2.7/poplib.py", line 114, in _getline
    raise error_proto('line too long')
poplib.error_proto: line too long



M.retr()을 통해 email 을 받다 보면 위와 같이 line too long 이라는 error가 발생하는 경우가 있다. 

이는 큰 사이즈의 email 의 메세지를 처리하다보면 발생할 수 있는데, email 메세지의 line이 기 선언된 2048 줄을 넘어가면 발생한다. 


# maximal line length when calling readline(). This is to prevent

# reading arbitrary length lines. RFC 1939 limits POP3 line length to

# 512 characters, including CRLF. We have selected 2048 just to be on

# the safe side.

_MAXLINE = 2048


해당 값을 바꾸기 위해서 코드상에서 하기 라인을 추가 하면 된다.

poplib._MAXLINE = 20480


import getpass, poplib

poplib._MAXLINE = 20480
M = poplib.POP3_SSL('pop.naver.com',995)
M.user("네이버 아이디")
M.pass_("네이버 비밀번호")

numMessages = len(M.list()[1])
for i in range(numMessages):
    for j in M.retr(i+1)[1]:
        print j






728x90