This commit is contained in:
2026-01-05 14:33:21 +08:00
commit ee348b4925
451 changed files with 39954 additions and 0 deletions
+185
View File
@@ -0,0 +1,185 @@
<?php
namespace app\command;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Helper\Table;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use support\Db;
/**
* 拉取邮箱的UID入库
*/
class EmailUidCommand extends Command
{
protected static $defaultName = 'email-uid';
protected static $defaultDescription = '拉取 UID 入库';
// protected function configure()
// {
// $this->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("<comment>第 {$attempt} 次失败:{$error}</comment>");
// 若出现 too many login failures 立即暂停一段时间
if (stripos($error, 'Too many login failures') !== false) {
$output->writeln("<error>检测到登录失败次数过多,暂停 60 秒避免封禁</error>");
sleep(60);
} else {
sleep($retryDelay);
}
}
if (!$inbox) {
$output->writeln("<error>最终仍然连接失败:" . imap_last_error() . "</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("<comment>{$e->getMessage()}</comment>");
}
}
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)
*/