メールで受信したExcelファイルを手動で確認し、データベースにインポートする作業を効率化するために、Pythonスクリプトを利用した自動化システムを構築してみませんか?特に、Windows Server環境でOutlookがインストールされていない場合でも動作するシステムを想定しています。
本記事では、メールの受信、添付ファイルの保存、データのデータベースへの自動インポート、さらにはエラー処理を組み込んだPythonスクリプトについて解説します。
処理の概要
このスクリプトは以下の手順で動作します:
- メールの受信:
- IMAPプロトコルを使用して、指定した件名のメールを検索します。
- 添付ファイルが含まれるメールを検出します。
- 添付ファイルの保存:
- 添付ファイルをローカルのディレクトリに保存します。
- データベースへのインポート:
- 保存されたExcelファイルを解析し、そのデータをSQLデータベースにインポートします。
- エラー処理:
- インポート処理中にエラーが発生した場合、エラーの詳細を記録し、該当のメールをIMAPサーバー上の「エラーフォルダ」に振り分けます。
- メールの整理:
- 正常に処理が完了したメールは「処理済みフォルダ」に移動します。
プログラム本体
import imaplib
import email
from email.header import decode_header
import os
import pandas as pd
from sqlalchemy import create_engine
# 設定
IMAP_SERVER = 'imap.example.com'
EMAIL_ACCOUNT = 'your_email@example.com'
EMAIL_PASSWORD = 'your_password'
TARGET_SUBJECT = 'Target Subject' # チェックしたいメールの件名
SAVE_DIR = 'attachments' # 添付ファイル保存先ディレクトリ
PROCESSED_FOLDER = 'Processed' # 処理済みメールのフォルダ名
ERROR_FOLDER = 'Error' # エラーメールのフォルダ名
DB_URL = 'sqlite:///example.db' # SQLiteの場合。適宜変更 (例: PostgreSQLの場合 'postgresql://user:password@localhost/dbname')
# データベースエンジン作成
engine = create_engine(DB_URL)
# メール受信と添付ファイル保存
def fetch_emails():
with imaplib.IMAP4_SSL(IMAP_SERVER) as mail:
mail.login(EMAIL_ACCOUNT, EMAIL_PASSWORD)
mail.select('inbox') # メインの受信トレイを選択
# 対象の件名を持つ未処理メールを検索
status, messages = mail.search(None, f'SUBJECT "{TARGET_SUBJECT}"')
if status != 'OK':
print("No messages found!")
return
for num in messages[0].split():
# メールの内容を取得
res, msg = mail.fetch(num, '(RFC822)')
if res != 'OK':
print(f"Failed to fetch email {num}")
continue
try:
# メールを解析
msg = email.message_from_bytes(msg[0][1])
for part in msg.walk():
if part.get_content_disposition() == 'attachment':
filename = part.get_filename()
if filename:
filepath = os.path.join(SAVE_DIR, filename)
os.makedirs(SAVE_DIR, exist_ok=True)
with open(filepath, 'wb') as f:
f.write(part.get_payload(decode=True))
print(f"Attachment saved: {filepath}")
process_excel(filepath)
# 正常処理が完了した場合、処理済みフォルダに移動
move_to_processed(mail, num)
except Exception as e:
print(f"Error processing email {num}: {e}")
# エラー発生時、エラーフォルダに移動
move_to_error(mail, num)
# メールを処理済みフォルダに移動
def move_to_processed(mail, email_id):
move_email(mail, email_id, PROCESSED_FOLDER)
# メールをエラーフォルダに移動
def move_to_error(mail, email_id):
move_email(mail, email_id, ERROR_FOLDER)
# メールを指定フォルダに移動
def move_email(mail, email_id, folder_name):
try:
# フォルダが存在するか確認(なければ作成)
mail.create(folder_name)
except imaplib.IMAP4.error:
pass # 既にフォルダが存在する場合は無視
# メールを移動
result = mail.copy(email_id, folder_name)
if result[0] == 'OK':
# 移動後、元のメールを削除
mail.store(email_id, '+FLAGS', '\\Deleted')
mail.expunge()
print(f"Email {email_id} moved to '{folder_name}'.")
else:
print(f"Failed to move email {email_id} to '{folder_name}'.")
# Excelファイルの処理
def process_excel(filepath):
try:
# ExcelデータをPandas DataFrameとして読み込み
if filepath.endswith('.xlsx') or filepath.endswith('.xls'):
df = pd.read_excel(filepath)
else:
print(f"Unsupported file format: {filepath}")
raise ValueError("Unsupported file format")
# データをデータベースにインポート
table_name = 'imported_data'
df.to_sql(table_name, engine, if_exists='append', index=False)
print(f"Data imported to table '{table_name}' from {filepath}")
except Exception as e:
print(f"Failed to process Excel file: {e}")
raise # エラーを親関数に再送
if __name__ == '__main__':
fetch_emails()
導入のメリット
1. 作業時間の短縮
手動でメールを確認し、添付ファイルをダウンロードしてデータベースにインポートする作業は非常に手間がかかります。本スクリプトを導入することで、このプロセスを完全に自動化できます。
2. エラーのトレーサビリティ
データの取り込み時にエラーが発生した場合、問題のあったメールを「エラーフォルダ」に自動で振り分けます。これにより、どのメールに問題があったかを簡単に特定できます。
3. メール管理の効率化
処理済みメールと未処理メールを分けることで、メールボックスの整理整頓が容易になります。重複処理の防止や作業ミスの軽減にもつながります。
プログラムの個別説明
1. メールの受信と検索
IMAPプロトコルを使用し、サーバーに接続して受信トレイから指定の条件に一致するメールを検索します。
status, messages = mail.search(None, f'SUBJECT "{TARGET_SUBJECT}"')
この部分では、件名が TARGET_SUBJECT
に一致するメールを検索しています。
2. 添付ファイルの保存
受信したメールから添付ファイルを検出し、ローカルディスクに保存します。
for part in msg.walk():
if part.get_content_disposition() == 'attachment':
with open(filepath, 'wb') as f:
f.write(part.get_payload(decode=True))
get_payload(decode=True)
を使い、添付ファイルの内容をデコードして保存します。
3. データベースへのインポート
pandas
を利用してExcelファイルをデータフレーム形式で読み取り、SQLデータベースにインポートします。
df = pd.read_excel(filepath)
df.to_sql(table_name, engine, if_exists='append', index=False)
データベース接続は sqlalchemy
を利用しており、複数のデータベースタイプ(SQLite, MySQL, PostgreSQLなど)に対応しています。
4. エラー処理
Excelファイルの解析やインポート時にエラーが発生した場合、その例外をキャッチし、該当メールを「エラーフォルダ」に移動します。
except Exception as e:
print(f"Failed to process Excel file: {e}")
raise # エラーを親関数に再送
この部分では、問題のあったファイルやメールを後から調査できるようにしています。
5. メールの整理
処理が成功した場合は「処理済みフォルダ」に、エラーが発生した場合は「エラーフォルダ」にメールを移動します。
def move_to_processed(mail, email_id):
move_email(mail, email_id, PROCESSED_FOLDER)
def move_to_error(mail, email_id):
move_email(mail, email_id, ERROR_FOLDER)
move_email
関数はIMAPコマンドを利用して、メールを指定フォルダに移動します。
実行環境のセットアップ
必要なライブラリ
以下のライブラリをインストールします:
pip install imapclient email openpyxl pandas sqlalchemy
Python環境
Windows Server環境を想定しており、Python 3.7以降を推奨します。
フォルダ構成
ローカルディスクには添付ファイルを保存するためのディレクトリ(例: attachments
)を用意してください。
まとめ
本スクリプトは、メールの添付ファイルを自動でデータベースにインポートし、エラーが発生した場合でもメールを整理できるように設計されています。運用の効率化だけでなく、問題発生時の調査も容易に行える点が特徴です。
日常の業務でメール添付のデータ処理にお困りの方は、ぜひこのスクリプトを参考に自動化を検討してみてください。さらなる改善やカスタマイズについてのご相談もお気軽にどうぞ!
コメント