You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP IMAP连接Gmail实现分页查询:每页获取20封邮件

实现Gmail IMAP邮件分页获取(每页20封)

问题说明

需要通过IMAP协议从Gmail邮箱分页获取邮件,每页限制20封,但现有代码会拉取全部77500封邮件,无法实现分页效果(如第1页显示1-20封、第2页显示21-40封等)。

原代码问题分析

原代码中imap_sort会返回所有邮件的ID数组,再用array_chunk分块,当邮件量极大时会占用大量内存;同时$page参数固定为1,无法动态指定页码,导致无法切换分页。

修正后的示例代码

ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);

// 加载依赖(确保路径正确,若使用Composer可替换为autoload)
require_once "Mail.php";
require_once "Mail/mime.php";
require_once('Mail/IMAPv2.php');

$username = 'myusername@gmail.com';
$password = 'mypassword';
// 修正服务器地址:原代码重复了/ssl,改为单次
$server = '{imap.gmail.com:993/imap/ssl}INBOX';

// 建立IMAP连接
$inbox = imap_open($server, $username, $password);
if (!$inbox) {
    die('连接失败: ' . imap_last_error());
}

// 配置分页参数:指定要获取的页码和每页数量
$targetPage = 1;
$perPageCount = 20;
$pageData = getPagedMails($inbox, $targetPage, $perPageCount);

// 输出分页信息和邮件列表
echo $pageData['paginationText'] . "\n";
foreach ($pageData['messages'] as $idx => $msg) {
    echo ($pageData['displayStart'] + $idx) . ": " . $msg->subject . "\n";
}

// 关闭IMAP连接
imap_close($inbox);

/**
 * 分页获取邮件列表
 * @param resource $imapConn IMAP连接资源
 * @param int $page 当前页码
 * @param int $perPage 每页邮件数量
 * @return array 包含分页信息和邮件数据的数组
 */
function getPagedMails($imapConn, $page = 1, $perPage = 20) {
    // 获取邮箱总邮件数
    $mailboxInfo = imap_check($imapConn);
    $totalMails = $mailboxInfo->Nmsgs;
    
    // 计算总页数,修正页码范围(防止越界)
    $totalPages = ceil($totalMails / $perPage);
    $page = max(1, min($page, $totalPages));
    
    // 计算IMAP邮件ID范围:Gmail中ID越大邮件越新,所以倒序取最新的邮件
    $startOffset = ($page - 1) * $perPage;
    $endId = max(1, $totalMails - $startOffset - $perPage + 1);
    $startId = $totalMails - $startOffset;
    $mailRange = "$endId:$startId";
    
    // 获取指定范围的邮件概述(包含主题、日期等核心信息)
    $messages = imap_fetch_overview($imapConn, $mailRange, FT_UID);
    // 如需按邮件接收时间正序显示,取消下面注释
    // $messages = array_reverse($messages);
    
    // 计算用户看到的序号范围
    $displayStart = ($page - 1) * $perPage + 1;
    $displayEnd = min($page * $perPage, $totalMails);
    
    return [
        'paginationText' => "page $page of $totalPages: $displayStart-$displayEnd of $totalMails",
        'displayStart' => $displayStart,
        'messages' => $messages,
        'totalPages' => $totalPages,
        'totalMails' => $totalMails
    ];
}

代码改进点

  • 避免一次性拉取全部邮件ID,直接通过IMAP的范围参数获取指定分页的邮件,大幅降低内存占用
  • 自动处理页码边界(页码超出范围时自动修正为有效页码)
  • 输出格式完全匹配需求的分页信息
  • 添加连接失败的错误处理,便于排查问题
  • 修正原代码中服务器地址的重复SSL参数问题

效果示例

page 1 of 3875: 1-20 of 77500
1: 最新订单通知
2: 系统运维日报
...
20: 客户咨询邮件

page 2 of 3875: 21-40 of 77500
21: 上周项目总结
22: 产品更新公告
...
40: 会议邀请邮件

内容的提问来源于stack exchange,提问作者chris oojer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 16:25:55