wxPythonでメール受信のまねごと

2011/10/07

Pythonでメールの受信ができるようになったので、wxPythonを使ってWindowで表示できるようにしてみた。windowで表示されるとメールアプリケーションらしくなるので不思議だ。

件名をクリックしても本文は表示されない。まだ、作っていないので今後の課題。受信したメールは新しい順に並ぶようにした。「送信日時」をクリックすると、ソートできる。昇順、降順と交互に動作する。あっ、それから、ステータス枠にメッセージも表示するようにもしてみた。ということで、あいかわらずだが、メモしておくことにした。

# -*- coding:utf-8 -*-

import wx
import poplib
import email
import pykf
import time

MAIL_SVR = 'YOUR_POP3_SERVER'
MAIL_USER = 'YOUR_MAIL_ACCOUNT'
MAIL_PSWD = 'YOUR_MAI_PASSWORD'

def parse_subject(msg):
    m_subject = msg.get('Subject')
    d_subject, enc = email.Header.decode_header(m_subject)[0]

    if enc == 'iso-2022-jp':
        subject = unicode(pykf.tosjis(d_subject), 'cp932')
    elif enc == None:
        subject = m_subject
    else:
        subject = unicode(d_subject, enc)

    return subject

def parse_date(msg):
    m_date = msg.get('Date')
    d_date = email.utils.parsedate(m_date)
    return time.strftime("%Y/%m/%d %H:%M:%S",d_date)

def parse_message(msg_string):
    msg = email.message_from_string(msg_string)
    date = parse_date(msg)
    subject = parse_subject(msg)

    return date, subject

def rcvmail(tbl, mwin):

    mwin.WriteMessage(u"受信を開始します")

    m = poplib.POP3(MAIL_SVR)
    m.user(MAIL_USER)
    m.pass_(MAIL_PSWD)

    mwin.WriteMessage(u"受信中です")

    numMessages = len(m.list()[1])

    for i in range(numMessages):
        msg = '\n'.join(m.retr(i+1)[1])
        date, subject = parse_message(msg)
        print date, subject
        tbl.Add(date, subject)
    m.quit()

    mwin.WriteMessage(u"受信を完了しました")

class MailTable(wx.ListCtrl):
    caption = (u"送信日時",u"件名")
    data = []
    flg_sort = "up"

    def __init__(self,parent):
        wx.ListCtrl.__init__(self,parent,-1,style = wx.LC_REPORT | wx.LC_VIRTUAL)
        self.InsertColumn(0, self.caption[0], width=120)
        self.InsertColumn(1, self.caption[1], width=320)
        self.items = self.data
        #self.SetItemCount(len(self.items))
        self.Bind(wx.EVT_LIST_COL_CLICK, self.Sort)

    def OnGetItemText(self, line, col):
        return self.items[line][col]

    def Add(self,data1,data2):
        self.data.insert(0,[data1,data2])
        self.DeleteAllItems()
        self.SetItemCount(len(self.items))
        self.Update()

    def Sort(self,event):
        idx = event.GetColumn()
        if not idx == 0:
            return
        if self.flg_sort == "up":
            self.items.sort(lambda x,y: cmp(x[idx],y[idx]))
            self.flg_sort = "down"
        else:
            self.items.sort(lambda y,x: cmp(x[idx],y[idx]))
            self.flg_sort = "up"
            
        self.DeleteAllItems()
        self.SetItemCount(len(self.items))

class MyWindow(wx.Frame):
    def __init__(self,parent,id):
        wx.Frame.__init__(self,parent,id, u"メール受信",size=(450,300))
        #self.SetBackgroundColour('WHITE')
        self.status = self.CreateStatusBar()

        ctlPnl = wx.Panel(self)

        rcvBtn = wx.Button(ctlPnl, label=u"受信")
        self.Bind(wx.EVT_BUTTON, self.onRcvBtn, rcvBtn)
        quitBtn = wx.Button(ctlPnl, label=u"終了")
        self.Bind(wx.EVT_BUTTON, self.onQuitBtn, quitBtn)

        ctlSz = wx.BoxSizer()
        ctlSz.Add(rcvBtn)
        ctlSz.Add(quitBtn)
        ctlPnl.SetSizer(ctlSz)

        self.rcvTbl = MailTable(self)

        sz = wx.BoxSizer(wx.VERTICAL)
        sz.Add(ctlPnl, 0, wx.EXPAND)
        sz.Add(self.rcvTbl, 1, wx.EXPAND)
        self.SetSizer(sz)
        self.Show(True)


    def onRcvBtn(self, event):
        rcvmail(self.rcvTbl, self)

    def onQuitBtn(self, event):
        self.Close()

    def WriteMessage(self, msg):
        self.status.SetStatusText(msg)


if __name__=='__main__':
    app=wx.PySimpleApp()
    frame=MyWindow(parent=None,id=-1)
    app.MainLoop()

スクリプトについて

受信したメールがリアルタイムに表示されなかった。
MailTblクラスのAddメッソドのなかで、Update()をしてやるとリアルタイムに表示されるようになった。似たようなメッソドでReflesh()があるが、すぐに表示はアップデートされない。参考:wx.Windows

参考リンク

wxPython

Posted by skw