addOption( // 'per-page', 'p', // InputOption::VALUE_OPTIONAL, // '每批处理多少条详情', // config('imap.per_page', 50) // ); // } protected function execute(InputInterface $input, OutputInterface $output): int { try { $cfg = config('imap'); $mailbox = $cfg['mailbox']; $username = $cfg['username']; $password = $cfg['password']; // $batch = (int)$input->getOption('per-page'); $retryTimes = 3; $retryDelay = 10; // 秒 $inbox = false; $attempt = 0; $maxUid = Db::table('email_uids')->max('uid'); while ($attempt < $retryTimes) { $attempt++; $output->writeln("尝试第 {$attempt} 次连接 IMAP..."); $inbox = @imap_open($mailbox, $username, $password); if ($inbox) { break; } $error = imap_last_error(); $output->writeln("第 {$attempt} 次失败:{$error}"); // 若出现 too many login failures 立即暂停一段时间 if (stripos($error, 'Too many login failures') !== false) { $output->writeln("检测到登录失败次数过多,暂停 60 秒避免封禁"); sleep(60); } else { sleep($retryDelay); } } if (!$inbox) { $output->writeln("最终仍然连接失败:" . imap_last_error() . ""); return Command::FAILURE; } // 拉取 UID 并入库 $output->writeln("开始拉取 UID 并入库 …"); $uids = imap_search($inbox, 'ALL', SE_UID) ?: []; $uids = array_filter($uids, function($uid) use ($maxUid) { return $uid > $maxUid; }); sort($uids); $now = time(); $count = 0; foreach ($uids as $uid) { try { Db::table('email_uids')->insert([ 'uid' => $uid, 'fetched_at' => $now, 'email' => $cfg['username'] ]); $count++; $output->writeln("UID:".$uid." 已写入数据库"); } catch (\Throwable $e) { $output->writeln("{$e->getMessage()}"); } } imap_close($inbox); $output->writeln(date('Y-m-d H:i:s').":共拉到 {$count} 个 UID 并写入 email_uids 表。"); return Command::SUCCESS; } catch (\Throwable $th) { dpr($th); return Command::FAILURE; } } } /** * 获取指定格式的日期字符串 * * @param string|null $input_date 可选,指定的日期(可以是任何PHP可解析的日期格式) * @return string 返回格式为 'd-M-Y' 的日期字符串(如 '28-Jul-2025') */ function getImapFormattedDate($input_date = null) { // 如果有传入日期参数,尝试解析 if ($input_date !== null) { $timestamp = strtotime($input_date); if ($timestamp === false) { // 如果日期解析失败,使用当前日期并记录警告 trigger_error("无法解析提供的日期: '$input_date',将使用当前日期", E_USER_WARNING); $timestamp = time(); } } else { // 如果没有提供日期,使用当前日期 $timestamp = time(); } // 格式化为 IMAP 需要的日期格式 (如 '28-Jul-2025') return date('d-M-Y', $timestamp); } // // 使用示例 // echo getImapFormattedDate(); // 输出当天的日期,如 '31-Jul-2025' // echo getImapFormattedDate('2025-07-28'); // 输出 '28-Jul-2025' // echo getImapFormattedDate('28/07/2025'); // 输出 '28-Jul-2025' // echo getImapFormattedDate('next Monday'); // 输出下个周一的日期 /* // imap_search() 条件 // 1. 基本日期搜索(按接收日期) // 搜索今天收到的邮件 $today = date("d-M-Y"); $uids = imap_search($inbox, 'SINCE "' . $today . '"', SE_UID); // 搜索特定日期之后的邮件 $since_date = '15-Jul-2023'; $uids = imap_search($inbox, 'SINCE "' . $since_date . '"', SE_UID); // 搜索特定日期之前的邮件 $before_date = '20-Jul-2023'; $uids = imap_search($inbox, 'BEFORE "' . $before_date . '"', SE_UID); // 搜索特定日期的邮件 $on_date = '18-Jul-2023'; $uids = imap_search($inbox, 'ON "' . $on_date . '"', SE_UID); // 2. 日期范围搜索 // 搜索2023年7月15日到2023年7月20日之间的邮件 $start_date = '15-Jul-2023'; $end_date = '20-Jul-2023'; $uids = imap_search($inbox, 'SINCE "' . $start_date . '" BEFORE "' . $end_date . '"', SE_UID); // 3. 结合日期和其他条件 // 搜索2023年7月以后未读的邮件 $date = '1-Jul-2023'; $uids = imap_search($inbox, 'SINCE "' . $date . '" UNSEEN', SE_UID); // 搜索2023年7月来自某人的邮件 $date = '1-Jul-2023'; $from = 'example@domain.com'; $uids = imap_search($inbox, 'SINCE "' . $date . '" FROM "' . $from . '"', SE_UID); // 4. 日期格式注意事项 // - IMAP日期格式通常为 d-M-Y,例如 15-Jul-2023 // - 月份使用英文缩写(Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec) // - 日期格式必须用双引号括起来 所有ID imap_search($inbox, 'ALL', SE_UID) */