poplib 를 이용해 raw email message를 받아오더라도 MIME (Multipurpose Internet Mail Extensions, 전자 우편을 위한 인터넷 표준 포맷)이기 때문에 막상 출력해 보면 알아보기 힘든 문자열들로 표현되어 있다. 이에 따라 원하는 값을 추출하기 위해 추가적인 코드를 작성하여야 한다. 

MIME 형식의 raw email message를 parsing 하기 위해서는 python의 email package를 사용하면 된다.


poplib의 M.retr()[1] 을 통해 구한 raw email string은 아래의 코드를 통해 하나의 string으로 표현이 가능하다. 

raw_email = b"\n".join(M.retr(mList+1)[1])


이렇게 구해진 raw_email 의 type을 확인해 보면 다음과 같다. 

<type 'str'>


msg = email.message_from_string(raw_email)

하나의 string이 raw_email은 email.message_from_string을 통해 parsing이 되고 [dict] 형태로 저장된다. 아래와 같은 key들을 통해 email의 원하는 값을 가져올 수 있다. 


msg.keys()

['Return-Path', 'Received', 'Received', 'X-AuditID', 'Received', 'Mime-Version', 'Subject', 'Reply-To', 'Sender', 'From', 'To', 'CC', 'X-Priority', 'X-Content-Kind-Code', 'In-Reply-To', 'X-Drm-Type', 'X-Msg-Generator', 'X-Msg-Type', 'X-Reply-Demand', 'X-Sender-IP', 'X-Local-Sender', 'X-Global-Sender', 'X-Sender-Code', 'Message-ID', 'Date', 'X-CMS-MailID', 'Content-Type', 'CMS-TYPE', 'X-Brightmail-Tracker', 'DLP-Filter', 'X-CFilter-Loop', 'X-CMS-RootMailID', 'References', 'X-CMS-Received']



import getpass, poplib
import email

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

raw_email = b"\n".join(M.retr(1)[1])
msg = email.message_from_string(raw_email)

print msg['Subject']
print msg['From']
print msg['Date']


위와 같이 코드를 작성하고, Subject, From, Date 에 대해서 임의의 메일을 출력해 보면 다음과 같은 결과를 얻을 수 있다. 


=?euc-kr?B?vsiz58fPvLy/5A==?=

test <test@test.kr>

Sat, 10 Mar 2007 13:24:13 +0900 (KST)


=?euc-kr?B 와 같이 encoding 정보와 함께 문자열의 encoding/decoding 이 필요한 상황이라 제대로 표시되지 않는 것을 볼 수 있다. 


아래와 같이 코드를 작성하면 실제로 인지 가능한 문자열로 변환이 가능하다.



import getpass, poplib
import email
from email.header import decode_header

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

raw_email = b"\n".join(M.retr(1)[1])
msg = email.message_from_string(raw_email)

print msg['Subject']
print decode_header(msg['Subject'])
s, encoding= decode_header(msg['Subject'])[0]
print unicode(s,encoding, 'replace').encode('utf-8','replace')
print msg['From']
print msg['Date']


위 코드를 실행하면 다음과 같은 결과를 얻을 수 있다. 


=?euc-kr?B?vsiz58fPvLy/5A==?=

[('\xbe\xc8\xb3\xe7\xc7\xcf\xbc\xbc\xbf\xe4', 'euc-kr')]

안녕하세요

test <test@test.kr>

Sat, 10 Mar 2007 13:24:13 +0900 (KST)


email.header.decode_header module을 이용하여 encoding 정보를 문자열에서 추출해 내고, 해당 encoding 정보로 unicode로 decoding 한 후 다시 화면에 출력 가능한 character set으로 encoding 하여 보여준다.


현재 자신의 terminal 이 지원하는 character set 은 locale 명령어로 확인이 가능하다. 


ubuntu@server:~/python$ locale

LANG=en_US.UTF-8

LANGUAGE=

LC_CTYPE="en_US.UTF-8"

LC_NUMERIC="en_US.UTF-8"

LC_TIME="en_US.UTF-8"

LC_COLLATE="en_US.UTF-8"

LC_MONETARY="en_US.UTF-8"

LC_MESSAGES="en_US.UTF-8"

LC_PAPER="en_US.UTF-8"

LC_NAME="en_US.UTF-8"

LC_ADDRESS="en_US.UTF-8"

LC_TELEPHONE="en_US.UTF-8"

LC_MEASUREMENT="en_US.UTF-8"

LC_IDENTIFICATION="en_US.UTF-8"

LC_ALL=


이런식으로 raw email message에서 원하는 정보를 추출해 낼 수 있다.