Merge branch 'feature/mzl_dev'
This commit is contained in:
@@ -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)
|
||||
|
||||
*/
|
||||
Reference in New Issue
Block a user