前回の第2段階では、AWS Lambda を使って Gmail から未読メールを取得し、件名・送信者・本文の情報を取得する処理を構築しました。
今回は、取得したメールの本文を解析し、スケジュール情報(開始・終了時刻、タイトル、参加者、場所)を抽出する処理を実装します。Garoon などのスケジュール通知メールに対応するため、正規表現(Regex)を活用して、柔軟に情報を取り出す仕組みを作っていきます。
前回の記事はこちら↓
1. メール本文の構造と解析のアプローチ
Garoon から送られてくるスケジュール通知メールには、日本語で「日時:」「参加者:」「施設:」などの項目が記載されています。これらは形式が一貫していない場合もあるため、正確に情報を取り出すには正規表現が有効です。
そのため、正規表現(Regular Expression, regex)を使って、柔軟に情報を抽出していくのが適しています。
正規表現は、特定のパターンに合致する文字列を検索したり、抽出したりするための記法です。最初は少し難しく感じるかもしれませんが、使いこなせるようになると、テキスト処理が非常に効率的に行えるようになります。
また、メールの形式には以下の2種類があります。
- プレーンテキスト(text/plain)
- HTMLメール(text/html)
本記事では、プレーンテキスト形式 (text/plain) のメール本文を対象とし、以下の情報を抽出します。
- 場所(本文中の「施設」)
- スケジュールタイトル(件名から)
- 開始・終了日時(本文中の「日時」項目)
- 参加者(本文中の「参加者」)
2. メール本文を解析する関数 (garoon_mail_parser.py) の作成
まず、新しいファイル garoon_mail_parser.py
を作成します。
Lambda のコードエディタで左のファイルツリーから「+」をクリックし、
「新しいファイルの作成」→ garoon_mail_parser.py
と入力して作成します。
以下のコードをファイルに記述してください:
Python
import re
from datetime import datetime
def parse_garoon_mail_new(body, subject):
"""Garoon のメール本文と件名を解析してスケジュール情報を抽出します (新しい形式に対応)。"""
schedule_info = {
'start_time': None,
'end_time': None,
'title': None,
'attendees': [],
'location': ''
}
# 件名からタイトルを抽出
title_match = re.search(r'\[(登録|変更|削除)\] (.*)', subject)
if title_match:
schedule_info['title'] = title_match.group(2).strip()
else:
schedule_info['title'] = subject.replace('[登録]', '').replace('[変更]', '').replace('[削除]', '').strip()
print(f"件名: {schedule_info['title']}")
# 日本語形式の日時を抽出
datetime_match = re.search(
r'日時\s*:\s*(\d{4}年\d{2}月\d{2}日)[((][^))]+[))]?\s+(\d{2}:\d{2})\s*〜\s*(\d{4}年\d{2}月\d{2}日)[((][^))]+[))]?\s+(\d{2}:\d{2})',
body
)
if datetime_match:
start_date_str = datetime_match.group(1)
start_time_str = datetime_match.group(2)
end_date_str = datetime_match.group(3)
end_time_str = datetime_match.group(4)
start_dt = datetime.strptime(start_date_str + ' ' + start_time_str, '%Y年%m月%d日 %H:%M')
end_dt = datetime.strptime(end_date_str + ' ' + end_time_str, '%Y年%m月%d日 %H:%M')
schedule_info['start_time'] = start_dt.strftime('%Y-%m-%dT%H:%M:%S+09:00')
schedule_info['end_time'] = end_dt.strftime('%Y-%m-%dT%H:%M:%S+09:00')
# 参加者の抽出
attendees_match = re.search(r'参加者\s*:\s*(.*)', body)
if attendees_match:
attendees_str = attendees_match.group(1).strip()
attendees = [name.strip() for name in attendees_str.split(',') if name.strip()]
schedule_info['attendees'] = attendees
# 施設(場所)の抽出
location_match = re.search(r'施設\s*:\s*(.*)', body)
if location_match:
schedule_info['location'] = location_match.group(1).strip()
return schedule_info
この garoon_mail_parser.py
には、この関数はメール本文と件名から、以下の情報を抽出します:
- 場所
- 開始日時・終了日時(ISO形式)
- 件名(タイトル)
- 参加者
3. main.py から解析関数を呼び出す
次に、main.py
を編集し、取得したメール本文を garoon_mail_parser.py
の解析関数に渡してスケジュール情報を抽出する処理を追加します。
main.py
の lambda_handler
関数内の、メール本文を取得した部分に以下のコードを追加します。
Python
lambda_handler 内で、メール本文を取得した後に追加:
for email_id in email_ids:
msg = fetch_email_data(mail, email_id)
if msg:
subject = decode_subject(msg)
sender = get_sender_email(msg)
body = get_email_body(msg)
print(f"ログ: メールを受信しました (ID: {email_id.decode()}, 件名: {subject}, 送信者: {sender})")
print(f"ログ: メール本文:\n{body}")
schedule_info = {}
if sender == secrets.get("garoon_sender"):
schedule_info = parse_garoon_mail_new(body, subject)
print(f"ログ: 解析されたスケジュール情報: {schedule_info}")
# 次の第4段階で Google Calendar に登録する処理を記述
この修正では、以下の処理を追加しています。
- メールの送信者が Garoon の送信者 (
secrets.get("garoon_sender")
) と一致する場合に、本文と件名の解析を行います。 parse_garoon_mail_new
関数を呼び出し、メール本文 (body
) と件名 (subject
) を渡して解析を行います。- 解析されたスケジュール情報を
schedule_info
変数に格納し、ログに出力します。 - 抽出したタイトルは、メールの件名から取得するようにしています(必要に応じて本文からも抽出するロジックを追加してください)。
また、main.py
の冒頭に、garoon_mail_parser.py
から必要な関数をインポートする行を追加します。
Python
import os
import json
from gmail_connector import connect_gmail, select_inbox, search_unread_emails, fetch_email_data, logout_gmail, get_email_body, get_sender_email, decode_subject
from garoon_mail_parser import parse_garoon_mail_new # ← この行を追加
import boto3
重要:
garoon_mail_parser.py
で定義したparse_garoon_mail_new
関数をmain.py
で使用するために、上記のimport
文を追加しています。これにより、main.py
からparse_garoon_mail_new
関数を呼び出すことができるようになります。
4. 正規表現の調整とエラーハンドリング
メールの本文の形式は、Garoon のバージョンや設定によって異なる可能性があります。もし、上記で記述した正規表現でうまく情報が抽出できない場合は、実際のメール本文の構造に合わせて正規表現を調整する必要があります。
正規表現のテストには、オンラインの正規表現チェッカーなどを利用すると便利です。
ここでは日時解析部分に基本的なエラーハンドリングを実装していますが、他の抽出処理にも必要に応じて追加してください。
以下のようなツールを使うと便利です:
5. Lambda 関数の再デプロイとテスト
main.py
と garoon_mail_parser.py
を編集したら、Lambda 関数を再度デプロイしてください。その後、実際に Garoon からスケジュール通知メールを送信し、Lambda 関数がトリガーされてログに解析された情報が出力されるか確認してください。
CloudWatch Logs を確認し、解析ログ (ログ: 解析された情報: ...
) が正しく出力されているか確認しましょう。もし、期待通りの情報が抽出できていない場合は、garoon_mail_parser.py
の正規表現を見直す必要があります。
まとめ
この第3段階では、取得した Gmail のメール本文を解析し、正規表現を使ってスケジュール情報(開始日時、終了日時、タイトル、参加者、場所)を抽出する基本的な処理を実装しました。
メール本文の形式に合わせて正規表現を調整することが、このステップの重要なポイントとなります。
次の第4段階では、抽出したスケジュール情報を Google Calendar に登録する処理を実装していきます。
コメント