diff --git a/app.py b/app.py index 33c2f62..1221af9 100644 --- a/app.py +++ b/app.py @@ -96,6 +96,52 @@ class EmailMonitor: except Exception as e: logger.warning(f"メールサーバーからの切断でエラーが発生しました: {str(e)}") + def get_latest_email_uid(self) -> Optional[str]: + """最新のメールUIDを取得""" + try: + typ, data = self.mail_client.search(None, 'ALL') + if typ != 'OK' or not data[0]: + logger.warning("メールボックスが空です") + return None + + email_ids = data[0].split() + return email_ids[-1].decode() # 最新のUIDを取得 + except Exception as e: + logger.error(f"最新メールUIDの取得に失敗しました: {str(e)}") + return None + + def get_new_emails_since_uid(self, last_uid: str) -> List[EmailMessage]: + """指定したUID以降の新しいメールを取得""" + try: + typ, data = self.mail_client.search(None, f'UID {last_uid}:*') + if typ != 'OK': + logger.warning("メール検索に失敗しました") + return [] + + email_ids = data[0].split()[1:] # 最初のUIDは除外 + new_emails = [] + + for email_id in email_ids: + try: + typ, msg_data = self.mail_client.fetch(email_id, '(RFC822)') + if typ != 'OK': + continue + + email_body = msg_data[0][1] + email_message = email.message_from_bytes(email_body) + + parsed_email = self._parse_email(email_message, email_id.decode()) + if parsed_email: + new_emails.append(parsed_email) + except Exception as e: + logger.error(f"メール解析エラー (ID: {email_id}): {str(e)}") + continue + + return new_emails + except Exception as e: + logger.error(f"新しいメールの取得に失敗しました: {str(e)}") + return [] + def get_new_emails(self) -> List[EmailMessage]: """新しいメールを取得""" try: @@ -272,36 +318,36 @@ class EmailMonitor: """メール監視を開始""" logger.info("メール監視を開始します...") self.running = True - + while self.running: try: - # メールサーバーに接続 if not self.connect_to_email(): logger.warning(f"{self.check_interval}秒後に再試行します...") time.sleep(self.check_interval) continue - - # 新しいメールをチェック - new_emails = self.get_new_emails() - + + if self.last_processed_uid is None: + self.last_processed_uid = self.get_latest_email_uid() + logger.info(f"初期UID: {self.last_processed_uid}") + + new_emails = self.get_new_emails_since_uid(self.last_processed_uid) + if new_emails: logger.info(f"{len(new_emails)}件の新しいメールが見つかりました") - + for email_msg in new_emails: if self.send_to_discord(email_msg): logger.info(f"処理完了: {email_msg.subject}") + self.last_processed_uid = email_msg.uid # 最後に処理したUIDを更新 else: logger.warning(f"Discord送信失敗: {email_msg.subject}") else: logger.debug("新しいメールはありません") - - # メールサーバーから切断 + self.disconnect_from_email() - - # 次のチェックまで待機 logger.debug(f"{self.check_interval}秒後に次のチェックを実行します") time.sleep(self.check_interval) - + except KeyboardInterrupt: logger.info("キーボード割り込みを受信しました") break @@ -309,7 +355,7 @@ class EmailMonitor: logger.error(f"監視ループでエラーが発生しました: {str(e)}") self.disconnect_from_email() time.sleep(self.check_interval) - + logger.info("メール監視を停止しました") def stop_monitoring(self):