PythonでGmailからメールを取得してExcelに保存する方法
この記事では、Pythonを使ってGmailのメールを取得し、Excelファイルに保存する方法を紹介します。特に、過去に取得したメールを再度保存しないようにする方法や、エラーハンドリング、メールの日時フォーマットの処理を含めて解説します。
使用するライブラリ
- imaplib: GmailのIMAPサーバーに接続し、メールを取得するためのライブラリです。
- email: メールの解析と操作を行います。
- openpyxl: Excelファイルの読み書きに使用します。
- pytz: タイムゾーンの操作をサポートします。
- re: 正規表現を使用して文字列を処理します。
1. メールの取得
まず、GmailのIMAPサーバーに接続して、メールを取得します。ここでは、全てのメールを取得し、過去に保存したメールをスキップするようにしています。
def fetch_emails(last_saved_date):
with imaplib.IMAP4_SSL("imap.gmail.com") as mail:
mail.login(email_user, app_password)
mail.select("inbox") # Inboxを選択
status, messages = mail.search(None, "ALL")
email_ids = messages[0].split()
emails = []
for email_id in email_ids:
status, msg_data = mail.fetch(email_id, "(RFC822)")
for response_part in msg_data:
if isinstance(response_part, tuple):
msg = email.message_from_bytes(response_part[1])
subject, encoding = decode_header(msg["Subject"])[0]
if isinstance(subject, bytes):
subject = subject.decode(encoding or "utf-8")
from_ = msg.get("From")
date = msg.get("Date")
# メールの日時を解析
date_cleaned = re.sub(r" \(.*?\)", "", date) # "(UTC)" を削除
date_cleaned = date_cleaned.replace("GMT", "+0000") # "GMT" を "+0000" に変換
# 日付をパース
try:
email_date = datetime.strptime(date_cleaned, "%a, %d %b %Y %H:%M:%S %z")
except ValueError:
print(f"日付解析エラー: {date_cleaned}")
continue
if email_date <= last_saved_date:
continue
body = ""
if msg.is_multipart():
for part in msg.walk():
content_type = part.get_content_type()
if content_type == "text/plain":
body = part.get_payload(decode=True).decode("utf-8")
body = extract_reply_body(body)
break
else:
body = msg.get_payload(decode=True).decode("utf-8")
body = extract_reply_body(body)
emails.append((subject, from_, date, body))
return emails
2. メールの保存
取得したメールをExcelファイルに保存する関数です。ファイルが存在する場合、最後に保存した日時を取得して、それ以降のメールだけを保存します。
def save_to_excel(emails, start_date):
try:
wb = openpyxl.load_workbook(excel_file)
sheet = wb.active
except FileNotFoundError:
wb = openpyxl.Workbook()
sheet = wb.active
sheet.append(["Subject", "From", "Date", "Body"])
dates = [row[2] for row in sheet.iter_rows(min_row=2, values_only=True) if row[2]] # 日付列を取得
if dates:
last_saved_date = max(dates)
if isinstance(last_saved_date, str):
last_saved_date = datetime.strptime(last_saved_date, "%a, %d %b %Y %H:%M:%S %z")
else:
last_saved_date = start_date
if last_saved_date.tzinfo is None:
last_saved_date = last_saved_date.replace(tzinfo=datetime.timezone.utc)
for subject, from_, date, body in emails:
date_cleaned = re.sub(r" \(.*?\)", "", date)
date_cleaned = date_cleaned.replace("GMT", "+0000")
try:
email_date = datetime.strptime(date_cleaned, "%a, %d %b %Y %H:%M:%S %z")
except ValueError:
print(f"日付解析エラー: {date_cleaned}")
continue
if email_date <= last_saved_date:
continue
sheet.append([subject, from_, date, body])
wb.save(excel_file)
print("新しいメールをExcelファイルに保存しました。")
3. メールの本文から返信部分を削除
返信メールの場合、メール本文に「On ... wrote:」のような返信部分が含まれます。これを削除して、純粋な本文だけを取得します。
def extract_reply_body(body):
reply_index = body.find("On") # 通常、返信部分は「On ... wrote:」という形式
if reply_index != -1:
return body[:reply_index].strip()
return body.strip()
4. 初回実行時と次回以降の動作
初回実行時には、start_date
を設定して、その日時以降のメールを取得します。次回以降は、Excelファイルに保存された最終日時を基準に、前回保存した日時以降のメールを取得します。
※データ取得
dates = [row[2] for row in sheet.iter_rows(min_row=2, values_only=True) if row[2]]について
https://qiita.com/ellyyyy/items/b363113f599e67665a4d
if __name__ == "__main__":
start_date = datetime(2025, 1, 1, 0, 0, 0)
if start_date.tzinfo is None:
start_date = start_date.replace(tzinfo=pytz.utc)
emails = fetch_emails(start_date)
if emails:
save_to_excel(emails, start_date)
else:
print("新しいメールがありませんでした。")
try:
wb = openpyxl.load_workbook(excel_file)
sheet = wb.active
dates = [row[2] for row in sheet.iter_rows(min_row=2, values_only=True) if row[2]]
if dates:
last_saved_date = max(dates)
emails = fetch_emails(last_saved_date)
if emails:
save_to_excel(emails, last_saved_date)
else:
print("新しいメールがありませんでした。")
except FileNotFoundError:
print("Excelファイルが見つかりません。最初にメールを保存してください。")
処理フロー
A[初回実行時: 開始日時指定] --> B[fetch_emails関数]
B --> C[IMAPサーバーに接続]
C --> D[メールのリストを取得]
D --> E[各メールの解析]
E --> F[日付をパースして保存対象のメールをフィルタリング]
F --> G[メールの件名、送信者、本文を取得]
G --> H[メールデータをリストに追加]
H --> I[保存対象のメールがあればsave_to_excel関数]
I --> J[Excelファイルを開くまたは新規作成]
J --> K[ヘッダー追加]
K --> L[既存のメールの日時を確認]
L --> M[新しいメールをフィルタリングしてExcelに保存]
M --> N[Excelファイルを保存]
まとめ
このコードでは、最初に指定した日時からメールを取得し、その後はExcelファイルに保存されている最終保存日時を基準にして新しいメールを取得・保存します。メールの日時や本文に関するエラーハンドリングも行い、メールの重複保存を防いでいます。
この方法を使えば、Gmailのメールを効率よく管理し、Excelで簡単に保存・整理できます。