Files
fdesk/app/command/EmailUidCommand.php
2025-08-04 14:03:57 +08:00

185 lines
6.0 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?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)
*/