Help us understand the problem. What is going on with this article?

メールに添付されたPDFをテキスト形式にする

More than 5 years have passed since last update.

とある会社からPDFが添付されたメールが送られてくる。

GmailなどPDFも検索できるメールサービスを使うのも手だが、あまり外部に出したくないのと、特定のキーワードが見つかった場合に適当に処理させたかったので、PythonのpyPdfを試してみた。

まず。メールの設定から。普段、使ってるメールソフトを「サーバにメールを残す」という設定にして、サーバに残ってるメールをfetchmailとprocmailで取得する。今回はCygwin環境のものを使い、下記のような設定ファイルを書いた。

.fetchmailrc
defaults
  fetchall
  keep
  mda "/usr/bin/procmail"

poll pop.xxx.com
  protocol pop3
  port 110
  username "XXXXX"
  password "XXXXX"
.procmailrc
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する。

http://pybrary.net/pyPdf/

pyPdfのサンプルプログラムと、emailパッケージを使って添付ファイルを書き出すサンプルを適当にコピペして、適当なフォルダにPDFファイルと、PDFファイルからテキストを抜き出したファイルを生成するスクリプトを書く。

pdfmail.py
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。

pdfmail.bat
C:\cygwin\bin\bash --login -i -c "fetchmail"
C:\cygwin\bin\python2.7.exe pdfmail.py
usop4
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした