メールの内容を Python で mantis に自動登録 その1



mantisを案件管理に使用しています。

メールで受信した案件を手動でコピーし、mantisに登録しているのですが、
こういった面倒くさいことは自動でやりましょう。

ということで、受信したメールの内容をmantisに登録する
Pythonプログラムを作って見ました。

まずは、PythonでIMAPのメールを読むプログラムです。



import imaplib,email,email.Header,email.Utils
import os
import time
import string
import re
import base64
import japanesenkf

OUTPUT_ENCODING = 'utf-8'
INPUT_ENCODING = 'ISO-2022-JP'
TMP_DIR = 'attach'

#メールのタイトル等の文字列をデコード
def imap4_decode(dec_target):
        decodefrag = email.Header.decode_header(dec_target)
        fragments = []
        
        for frag, enc in decodefrag:
                if enc:
                        try:
                                frag = unicode(frag, enc).encode(OUTPUT_ENCODING)
                        except:
                                c = japanesenkf.iso2022_jp_nkf()
                                frag,len = c.decode(frag)
                        
                fragments.append(frag)

        return ''.join(fragments)

#メール本文の文字列をデコード
def imap4_body_decode(part):
        body = ''
        charset = str(part.get_content_charset())
        
        if charset == 'utf-8':
                try:
                        body = base64.b64decode(part.get_payload())
                except:
                        body = part.get_payload(decode=True)
                
        elif charset == 'shift_jis':
                try:
                        body = unicode(part.get_payload(decode=True),'shift_jis').encode('utf-8')
                        body = string.replace(body, '\r','')
                except:
                        if part.get_payload(decode=True) != None:
                                c = japanesenkf.shift_jis_nkf()
                                body,len = c.decode(part.get_payload(decode=True))
        else:
                try:
                        body = unicode(part.get_payload(decode=True), INPUT_ENCODING).encode(OUTPUT_ENCODING)
                except:
                        #body = part.get_payload(decode=True)
                        if part.get_payload(decode=True) != None:
                                c = japanesenkf.iso2022_jp_nkf()
                                body,len = c.decode(part.get_payload(decode=True))
                
        return body

#IMAP4メール内容解析クラス
class imap4mail:
        #コンストラクタで与えられたメールの解析を実行する
        def __init__(self, data):
                self._files = []
                #メッセージをパース
                msg = email.message_from_string(data)
                #タイトル取得
                self._title = imap4_decode(msg.get('Subject'))
                #送信者取得
                self._sender = imap4_decode(msg.get('From'))
                #self._receiver = imap4_title_decode(msg.get('To'))
                #送信日付取得
                self._date = imap4_decode(msg.get('Date'))
                #本文の初期値を設定 (本文空白バグ対応)
                self._body = '(本文空白)'
                
                #本文抽出済みフラグ
                outputbody = False
                
                #添付ファイルを抽出
                for part in msg.walk():
                        if part.get_content_maintype() == 'multipart':
                                continue
                                
                        filename = part.get_filename()
                        
                        #ファイル名が取得できなければ本文
                        if not filename:
                                
                                if outputbody:
                                        continue
                                
                                self._body = imap4_body_decode(part)
                                
                                if self._body == '':
                                        self._body = '(本文空白)'
                                
                                outputbody = True
                                
                        #ファイル名が存在すれば添付ファイル
                        else:
                                filename = imap4_decode(filename)
                                fp = open(os.path.join(TMP_DIR,filename), 'wb')
                                fp.write(part.get_payload(decode=1))
                                fp.close()
                                
                                self._files.append(filename)

        def get_format_date(self):
                #http://www.faqs.org/rfcs/rfc2822.html
                #"Jan" / "Feb" / "Mar" / "Apr" /"May" / "Jun" / "Jul" / "Aug" /"Sep" / "Oct" / "Nov" / "Dec"
                #Wed, 12 Dec 2007 19:18:10 +0900
                #0123456789012345678901234567890
                
                ret = self._date[5:]
                tmp = string.split(ret)
                
                month = '01'
                m_target = tmp[1]
                if m_target == 'Jan':
                        month = '01'
                elif m_target == 'Feb':
                        month = '02'
                elif m_target == 'Mar':
                        month = '03'
                elif m_target == 'Apr':
                        month = '04'
                elif m_target == 'May':
                        month = '05'
                elif m_target == 'Jun':
                        month = '06'
                elif m_target == 'Jul':
                        month = '07'
                elif m_target == 'Aug':
                        month = '08'
                elif m_target == 'Sep':
                        month = '09'
                elif m_target == 'Oct':
                        month = '10'
                elif m_target == 'Nov':
                        month = '11'
                elif m_target == 'Dec':
                        month = '12'
                        
                if len(tmp[0]) == 1:
                        tmp[0] = '0' + tmp[0]
                
                return time.strptime(tmp[2] + month + tmp[0] + tmp[3],'%Y%m%d%H:%M:%S')
                
        #送信者名
        def get_sender(self):
                ret = ''
                
                for s in tmp:
                        if s == '<':
                                break
                        
                        ret += s
                
                return ret
                
                
        #作成した添付ファイルのテンポラリを削除
        def delete_files(self):
                for filename in self._files:
                        #ファイルの削除実行
                        os.remove(os.path.join(TMP_DIR,filename))

def mail_crawl(M, mailbox):
        #メールボックス選択
        M.select(mailbox)
        
        typ, data = M.search(None, 'ALL')
        for num in data[0].split():
                typ, data = M.fetch(num, '(RFC822)')
                mail = imap4mail(data[0][1])
                print mail._title
                print mail._body
                
        M.close()

if __name__ == "__main__":
        #メールサーバ指定
        M = imaplib.IMAP4('192.168.1.251')
        #ログイン
        M.login('mantis', 'mantis')
        
        #motmantisメールクロール
        mail_crawl(M, 'INBOX')
        
        M.logout()



次回は、
ZSIモジュールを使用してSOAP通信
mantiscoonect経由でmantisに案件登録を行います。



もどる