とある会社からPDFが添付されたメールが送られてくる。
GmailなどPDFも検索できるメールサービスを使うのも手だが、あまり外部に出したくないのと、特定のキーワードが見つかった場合に適当に処理させたかったので、PythonのpyPdfを試してみた。
まず。メールの設定から。普段、使ってるメールソフトを「サーバにメールを残す」という設定にして、サーバに残ってるメールをfetchmailとprocmailで取得する。今回はCygwin環境のものを使い、下記のような設定ファイルを書いた。
defaults
fetchall
keep
mda "/usr/bin/procmail"
poll pop.xxx.com
protocol pop3
port 110
username "XXXXX"
password "XXXXX"
MAILDIR=$HOME/Mail/
DEFAULT=/dev/null
:0 H
* ^From:.*test@example.com
/var/spool/mail/t.uehara/
こう書くことで、test@exampleからのメールは/var/spool/mailに格納され、他のメールは/dev/null(つまり廃棄)。fetchmail側でkeepと書いているのでサーバ上には残される。格納先はどこでもいいのだが、Muttなどで読めた方が動作確認に便利なので、/var/spool/mailにしておいた。
次にpyPdfをダウンロードしてpython setup.py installする。
pyPdfのサンプルプログラムと、emailパッケージを使って添付ファイルを書き出すサンプルを適当にコピペして、適当なフォルダにPDFファイルと、PDFファイルからテキストを抜き出したファイルを生成するスクリプトを書く。
import os
import sys
import email
import mailbox
import mimetypes
import pyPdf
def pdfmail(msgfile):
fp = open(msgfile)
msg = email.message_from_file(fp)
fp.close()
counter = 1
for part in msg.walk():
if part.get_content_maintype() == 'multipart':
continue
fname = part.get_filename()
if not fname:
ext = mimetypes.guess_extension(part.get_type())
if not ext:
ext = '.bin'
fname = 'part-%03d%s' % (counter, ext)
counter += 1
if fname.find('.pdf') != -1:
print fname
fp = open('pdf/'+fname, 'wb')
fp.write(part.get_payload(decode=True))
fp.close()
c = getPDFContent('pdf/'+fname).encode("ascii","xmlcharrefreplace")
fp = open('pdf/'+fname+".txt", 'wb')
fp.write(c)
fp.close()
def getPDFContent(path):
content = ""
pdf = pyPdf.PdfFileReader(file(path, "rb"))
for i in range(0, pdf.getNumPages()):
content += pdf.getPage(i).extractText() + "\n"
content = " ".join(content.replace(u"\xa0", " ").strip().split())
return content
if __name__ == '__main__':
maildir = '/var/spool/mail/t.uehara'
m = mailbox.Maildir(maildir)
for key in m.keys():
pdfmail(maildir+'/new/'+key)
最後に、こんな感じでバッチファイルを作って、Windowsのタスクスケジューラ等で定期的に回せばOK。
C:\cygwin\bin\bash --login -i -c "fetchmail"
C:\cygwin\bin\python2.7.exe pdfmail.py