smartilabs/php-imap

PHP IMAP 客户端

2.2.3 2020-11-02 12:43 UTC

README

Latest Version on Packagist Software License Build Status Total Downloads Hits

描述

PHP-IMAP 是一个用于常见 IMAP 通信的包装器,无需安装/启用 php-imap 模块。协议完全集成,因此支持 IMAP IDLE 操作和“新”OAuth 认证过程。您可以启用 php-imap 模块来处理边缘情况,提高消息解码质量,如果您想使用如 pop3 这样的旧协议,则必须使用它。

Wiki: webklex/php-imap/wiki

Laravel 包装器: webklex/laravel-imap

目录

安装

1.) 安装解码模块

sudo apt-get install php*-mbstring php*-mcrypt && sudo apache2ctl graceful

1.1.) (可选) 如果您遇到编码问题,请安装 php-imap 模块

sudo apt-get install php*-imap && sudo apache2ctl graceful

您还可能想检查 phpinfo() 看看扩展是否启用。

2.) 现在运行以下命令来安装 PHP-IMAP 软件包

composer require webklex/php-imap

3.) 创建您自己的自定义配置文件,例如 config/imap.php

配置

支持的协议

  • imap — 使用 IMAP [默认]
  • legacy-imap — 使用 php imap 模块
  • pop3 — 使用 POP3
  • nntp — 使用 NNTP

以下加密方法得到支持

  • false — 禁用加密
  • ssl — 使用 SSL
  • tls — 使用 TLS
  • starttls — 使用 STARTTLS (TLS 的别称) (仅限旧版)
  • notls — 使用 NoTLS (仅限旧版)

详细的 config/imap.php 配置

  • default — 使用默认账户。如果默认账户缺少参数,则将使用软件包默认值。如果默认账户缺少参数,请将此功能禁用。
  • accounts — 所有可用账户
    • default — 账户标识符(在这种情况下为 default,但也可以为 fooBar 等)。
      • host — imap 主机
      • port — imap 端口
      • encryption — 希望的加密方法
      • validate_cert — 决定您是否想要验证证书
      • username — imap 账户用户名
      • password — imap 账户密码
      • authentication — imap 认证方法。使用 oauth 来使用 Google 等的 OAuth。
  • date_format — 默认日期格式用于将给定的 Carbon::class 对象转换为有效的日期字符串。(d-M-Yd-M-yd M y
  • options — 额外的获取选项
    • delimiter — 可以使用任何支持的字符,例如 "。" 或 "/" 等。
    • fetchIMAP::FT_UID(通过获取消息正文标记为已读)或 IMAP::FT_PEEK(获取消息不设置“已读”标志)。
    • fetch_body — 如果设置为 false,则所有消息将获取不带正文和任何潜在附件。
    • fetch_flags — 如果设置为 false,则所有消息将获取不带任何标志。
    • message_key — 消息键标识选项。
    • fetch_order — 消息获取顺序。
    • common_folders — 如果未提供,则假定默认文件夹位置和路径。
    • open — 对 imap_open() 的特殊配置。
      • DISABLE_AUTHENTICATOR — 禁用身份验证属性。
    • decoder — 目前只能设置消息和附件解码器。
    • events — 默认事件处理配置。
    • masks — 默认遮罩配置。
      • message — 默认消息遮罩。
      • attachment — 默认附件遮罩。

用法

基本用法示例

这是一个基本示例,它将回显所有imap文件夹中的邮件,并将每条消息移入INBOX.read。请注意,这不应该在实际生活中进行测试,只是为了让您了解事物是如何工作的。

use Webklex\PHPIMAP\ClientManager;
use Webklex\PHPIMAP\Client;

$cm = new ClientManager('path/to/config/imap.php');

// or use an array of options instead
$cm = new ClientManager($options = []);

/** @var \Webklex\PHPIMAP\Client $client */
$client = $cm->account('account_identifier');

// or create a new instance manually        
$client = $cm->make([
    'host'          => 'somehost.com',
    'port'          => 993,
    'encryption'    => 'ssl',
    'validate_cert' => true,
    'username'      => 'username',
    'password'      => 'password',
    'protocol'      => 'imap'
]);

//Connect to the IMAP Server
$client->connect();

//Get all Mailboxes
/** @var \Webklex\PHPIMAP\Support\FolderCollection $folders */
$folders = $client->getFolders();

//Loop through every Mailbox
/** @var \Webklex\PHPIMAP\Folder $folder */
foreach($folders as $folder){

    //Get all Messages of the current Mailbox $folder
    /** @var \Webklex\PHPIMAP\Support\MessageCollection $messages */
    $messages = $folder->messages()->all()->get();
    
    /** @var \Webklex\PHPIMAP\Message $message */
    foreach($messages as $message){
        echo $message->getSubject().'<br />';
        echo 'Attachments: '.$message->getAttachments()->count().'<br />';
        echo $message->getHTMLBody();
        
        //Move the current Message to 'INBOX.read'
        if($message->move('INBOX.read') == true){
            echo 'Message has ben moved';
        }else{
            echo 'Message could not be moved';
        }
    }
}

文件夹 / 邮箱

列出所有可用文件夹。

/** @var \Webklex\PHPIMAP\Client $client */

/** @var \Webklex\PHPIMAP\Support\FolderCollection $folders */
$folders = $client->getFolders();

获取特定文件夹。

/** @var \Webklex\PHPIMAP\Client $client */

/** @var \Webklex\PHPIMAP\Folder $folder */
$folder = $client->getFolder('INBOX.name');

oAuth

请参阅维基文章以获取gmail / google mail的设置。

基本oAuth示例。

use Webklex\PHPIMAP\Clientmanager;

$cm = new Clientmanager();

/** @var \Webklex\PHPIMAP\Client $client */
$client = $cm->make([
    'host' => 'imap.gmail.com',
    'port' => 993,
    'encryption' => 'ssl',
    'validate_cert' => true,
    'username' => 'example@gmail.com',
    'password' => 'ACCESS-TOKEN',
    'authentication' => "oauth",
    'protocol' => 'imap'
]);

//Connect to the IMAP Server
$client->connect();

IDLE

每次收到新消息时,服务器将通知客户端并返回新消息。

/** @var \Webklex\PHPIMAP\Folder $folder */
$folder->idle(function($message){
    echo $message->subject."\n";
});

搜索邮件。

搜索特定电子邮件。

/** @var \Webklex\PHPIMAP\Folder $folder */

//Get all messages
/** @var \Webklex\PHPIMAP\Support\MessageCollection $messages */
$messages = $folder->query()->all()->get();

//Get all messages from example@domain.com
/** @var \Webklex\PHPIMAP\Support\MessageCollection $messages */
$messages = $folder->query()->from('example@domain.com')->get();

//Get all messages since march 15 2018
/** @var \Webklex\PHPIMAP\Support\MessageCollection $messages */
$messages = $folder->query()->since('15.03.2018')->get();

//Get all messages within the last 5 days
$messages = $folder->query()->since(\Carbon\Carbon::now()->subDays(5))->get();

//Get all messages containing "hello world"
/** @var \Webklex\PHPIMAP\Support\MessageCollection $messages */
$messages = $folder->query()->text('hello world')->get();

//Get all unseen messages containing "hello world"
/** @var \Webklex\PHPIMAP\Support\MessageCollection $messages */
$messages = $folder->query()->unseen()->text('hello world')->get();

//Extended custom search query for all messages containing "hello world" 
//and have been received since march 15 2018
/** @var \Webklex\PHPIMAP\Support\MessageCollection $messages */
$messages = $folder->query()->text('hello world')->since('15.03.2018')->get();
$messages = $folder->query()->Text('hello world')->Since('15.03.2018')->get();
$messages = $folder->query()->whereText('hello world')->whereSince('15.03.2018')->get();

// Build a custom search query
/** @var \Webklex\PHPIMAP\Support\MessageCollection $messages */
$messages = $folder->query()
->where([['TEXT', 'Hello world'], ['SINCE', \Carbon\Carbon::parse('15.03.2018')]])
->get();

//!EXPERIMENTAL!
//Get all messages NOT containing "hello world"
/** @var \Webklex\PHPIMAP\Support\MessageCollection $messages */
$messages = $folder->query()->notText('hello world')->get();
$messages = $folder->query()->not_text('hello world')->get();
$messages = $folder->query()->not()->text('hello world')->get();

//Get all messages by custom search criteria
/** @var \Webklex\PHPIMAP\Support\MessageCollection $messages */
$messages = $folder->query()->where(["CUSTOM_FOOBAR" => "fooBar"]])->get();

用于更好地阅读代码的可用搜索别名。

// Folder::search() is just an alias for Folder::query()
/** @var \Webklex\PHPIMAP\Support\MessageCollection $messages */
$messages = $folder->search()->text('hello world')->since('15.03.2018')->get();

// Folder::messages() is just an alias for Folder::query()
/** @var \Webklex\PHPIMAP\Support\MessageCollection $messages */
$messages = $folder->messages()->text('hello world')->since('15.03.2018')->get();

所有可用的查询/搜索方法可以在以下位置找到: Query::class

可用的搜索标准。

  • ALL — 返回所有符合其他标准条件的消息。
  • ANSWERED — 匹配设置了 \ANSWERED 标志的消息。
  • BCC "字符串" — 匹配Bcc:字段中包含"字符串"的消息。
  • BEFORE "日期" — 匹配Date:日期在"日期"之前的消息。
  • BODY "字符串" — 匹配正文包含"字符串"的消息。
  • CC "字符串" — 匹配Cc:字段中包含"字符串"的消息。
  • DELETED — 匹配已删除的消息。
  • FLAGGED — 匹配设置了 \FLAGGED(有时称为Important或Urgent)标志的消息。
  • FROM "字符串" — 匹配From:字段中包含"字符串"的消息。
  • KEYWORD "字符串" — 匹配包含"字符串"作为关键字的消息。
  • NEW — 匹配新消息。
  • NOT — 不匹配。
  • OLD — 匹配旧消息。
  • ON "日期" — 匹配Date:日期匹配"日期"的消息。
  • RECENT — 匹配设置了 \RECENT 标志的消息。
  • SEEN — 匹配已读的消息(已设置 \SEEN 标志)。
  • SINCE "日期" — 匹配Date:日期在"日期"之后的消息。
  • SUBJECT "字符串" — 匹配Subject中包含"字符串"的消息。
  • TEXT "字符串" — 匹配包含文本"字符串"的消息。
  • TO "字符串" — 匹配To中包含"字符串"的消息。
  • UNANSWERED — 匹配未回答的消息。
  • UNDELETED — 匹配未删除的消息。
  • UNFLAGGED — 匹配未标记的消息。
  • UNKEYWORD "字符串" — 匹配不包含关键字"字符串"的消息。
  • UNSEEN — 匹配尚未阅读的消息

更多信息

结果限制

限制请求邮件

/** @var \Webklex\PHPIMAP\Folder $folder */

//Get all messages for page 2 since march 15 2018 where each page contains 10 messages
/** @var \Webklex\PHPIMAP\Support\MessageCollection $messages */
$messages = $folder->query()->since('15.03.2018')->limit(10, 2)->get();

计数消息

计算所有符合当前搜索条件的可用消息数量

/** @var \Webklex\PHPIMAP\Folder $folder */

//Count all messages
/** @var \Webklex\PHPIMAP\Support\MessageCollection $messages */
$count = $folder->query()->all()->count();

//Count all messages since march 15 2018
$count = $folder->query()->since('15.03.2018')->count();

分页

分页查询

/** @var \Webklex\PHPIMAP\Folder $folder */

/** @var \Illuminate\Pagination\LengthAwarePaginator $paginator */
$paginator = $folder->query()->since('15.03.2018')->paginate();

分页消息集合

/** @var \Webklex\PHPIMAP\Support\MessageCollection $messages */

/** @var \Illuminate\Pagination\LengthAwarePaginator $paginator */
$paginator = $messages->paginate();

查看分页列表的示例

/** @var \Webklex\PHPIMAP\Folder $folder */

/** @var \Illuminate\Pagination\LengthAwarePaginator $paginator */
$paginator = $folder->search()
->since(\Carbon\Carbon::now()->subDays(14))->get()
->paginate($perPage = 5, $page = null, $pageName = 'imap_blade_example');
<table>
    <thead>
    <tr>
        <th>UID</th>
        <th>Subject</th>
        <th>From</th>
        <th>Attachments</th>
    </tr>
    </thead>
    <tbody>
        <?php if($paginator->count() > 0): ?>
            <?php foreach($paginator as $message): ?>
            <tr>
                <td><?php echo $message->getUid(); ?></td>
                <td><?php echo $message->getSubject(); ?></td>
                <td><?php echo $message->getFrom()[0]->mail; ?></td>
                <td><?php echo $message->getAttachments()->count() > 0 ? 'yes' : 'no'; ?></td>
            </tr>
            <?php endforeach; ?>
        <?php else: ?>
            <tr>
                <td colspan="4">No messages found</td>
            </tr>
        <?php endif; ?>
    </tbody>
</table>

<?php echo $paginator->links(); ?>

您还可以对文件夹、附件或FlagCollection实例进行分页。

查看示例

您可以在 /examples 下找到一些blade示例。

获取特定消息

通过uid获取特定消息(请注意,uid不是唯一的,可能会更改)

/** @var \Webklex\PHPIMAP\Folder $folder */

/** @var \Webklex\PHPIMAP\Message $message */
$message = $folder->query()->getMessage($msgn = 1);

消息标志

标记或“取消标记”消息

/** @var \Webklex\PHPIMAP\Message $message */
$message->setFlag(['Seen', 'Spam']);
$message->unsetFlag('Spam');

在获取时将所有消息标记为“已读”

/** @var \Webklex\PHPIMAP\Folder $oFolder */
/** @var \Webklex\PHPIMAP\Support\MessageCollection $aMessage */
$aMessage = $oFolder->query()->text('Hello world')->markAsRead()->get();

在获取时不要将所有消息标记为“已读”

/** @var \Webklex\PHPIMAP\Folder $oFolder */
/** @var \Webklex\PHPIMAP\Support\MessageCollection $aMessage */
$aMessage = $oFolder->query()->text('Hello world')->leaveUnread()->get();

附件

保存消息附件

/** @var \Webklex\PHPIMAP\Message $message */

/** @var \Webklex\PHPIMAP\Support\AttachmentCollection $attachments */
$attachments = $message->getAttachments();

$attachments->each(function ($attachment) {
    /** @var \Webklex\PHPIMAP\Attachment $attachment */
    $attachment->save("/some/path/");
});

高级获取

获取不带正文获取的消息(减少负载)

/** @var \Webklex\PHPIMAP\Folder $folder */

/** @var \Webklex\PHPIMAP\Support\MessageCollection $messages */
$messages = $folder->query()->whereText('Hello world')->setFetchBody(false)->get();

/** @var \Webklex\PHPIMAP\Support\MessageCollection $messages */
$messages = $folder->query()->whereAll()->setFetchBody(false)->get();

获取不带正文、标记和附件获取的消息(减少负载)

/** @var \Webklex\PHPIMAP\Folder $folder */

/** @var \Webklex\PHPIMAP\Support\MessageCollection $messages */
$messages = $folder->query()->whereText('Hello world')
->setFetchFlags(false)
->setFetchBody(false)
->get();

/** @var \Webklex\PHPIMAP\Support\MessageCollection $messages */
$messages = $folder->query()->whereAll()
->setFetchFlags(false)
->setFetchBody(false)
->get();

更改消息获取顺序

/** @var \Webklex\PHPIMAP\Folder $folder */

/** @var \Webklex\PHPIMAP\Support\MessageCollection $messages */
$messages = $folder->query()->whereText('Hello world')
->setFetchOrder('asc')
->get();

/** @var \Webklex\PHPIMAP\Support\MessageCollection $messages */
$messages = $folder->query()->whereAll()
->setFetchOrderAsc()
->get();

/** @var \Webklex\PHPIMAP\Support\MessageCollection $messages */
$messages = $folder->query()->whereAll()
->fetchOrderAsc()
->get();

/** @var \Webklex\PHPIMAP\Support\MessageCollection $messages */
$messages = $folder->query()->whereText('Hello world')
->setFetchOrder('desc')
->get();

/** @var \Webklex\PHPIMAP\Support\MessageCollection $messages */
$messages = $folder->query()->whereAll()
->setFetchOrderDesc()
->get();

/** @var \Webklex\PHPIMAP\Support\MessageCollection $messages */
$messages = $folder->query()->whereAll()
->fetchOrderDesc()
->get();

事件

以下事件可用

  • Webklex\PHPIMAP\Events\MessageNewEvent($message) — 可由 Folder::idle 触发
  • Webklex\PHPIMAP\Events\MessageDeletedEvent($message) — 由 Message::delete 触发
  • Webklex\PHPIMAP\Events\MessageRestoredEvent($message) — 由 Message::restore 触发
  • Webklex\PHPIMAP\Events\MessageMovedEvent($old_message, $new_message) — 由 Message::move 触发
  • Webklex\PHPIMAP\Events\MessageCopiedEvent($old_message, $new_message) — 由 Message::copy 触发
  • Webklex\PHPIMAP\Events\FlagNewEvent($flag) — 由 Message::setFlag 触发
  • Webklex\PHPIMAP\Events\FlagDeletedEvent($flag) — 由 Message::unsetFlag 触发
  • Webklex\PHPIMAP\Events\FolderNewEvent($folder) — 可由 Client::createFolder 触发
  • Webklex\PHPIMAP\Events\FolderDeletedEvent($folder) — 由 Folder::delete 触发
  • Webklex\PHPIMAP\Events\FolderMovedEvent($old_folder, $new_folder) — 由 Folder::move 触发

创建并注册您自己的自定义事件

class CustomMessageNewEvent extends Webklex\PHPIMAP\Events\MessageNewEvent {

    /**
     * Create a new event instance.
     * @var \Webklex\PHPIMAP\Message[] $messages
     * @return void
     */
    public function __construct($messages) {
        $this->message = $messages[0];
        echo "New message: ".$this->message->subject."\n";
    }
}

/** @var \Webklex\PHPIMAP\Client $client */
$client->setEvent("message", "new", CustomMessageNewEvent::class);

或将其设置在您的配置文件中的 events.message.new 下。

掩码

PHP-IMAP 已经带有两个默认掩码 MessageMask::classAttachmentMask::class

掩码实例必须手动调用,并设计用于添加自定义功能。

您可以通过调用无参数的掩码方法来调用默认掩码。

/** @var \Webklex\PHPIMAP\Message $message */
$mask = $message->mask();

有几种方法可以设置默认掩码

/** @var \Webklex\PHPIMAP\Client $client */
/** @var \Webklex\PHPIMAP\Message $message */

$message_mask = \Webklex\PHPIMAP\Support\Masks\MessageMask::class;

$client->setDefaultMessageMask($message_mask);
$message->setMask($message_mask);
$mask = $message->mask($message_mask);

最后一个不会设置掩码,而是使用提供的掩码生成一个掩码实例。

您还可以在 config/imap.php 文件中的 masks 下设置默认掩码。

您还可以在 附件 上应用掩码

/** @var \Webklex\PHPIMAP\Client $client */
/** @var \Webklex\PHPIMAP\Attachment $attachment */
$attachment_mask = \Webklex\PHPIMAP\Support\Masks\AttachmentMask::class;

$client->setDefaultAttachmentMask($attachment_mask);
$attachment->setMask($attachment_mask);
$mask = $attachment->mask($attachment_mask);

如果您想实现自己的掩码,请扩展 MessageMask::classAttachmentMask::classMask::class 并实现您想要的逻辑

/** @var \Webklex\PHPIMAP\Message $message */
class CustomMessageMask extends \Webklex\PHPIMAP\Support\Masks\MessageMask {

    /**
     * New custom method which can be called through a mask
     * @return string
     */
    public function token(){
        return implode('-', [$this->message_id, $this->uid, $this->message_no]);
    }
}

$mask = $message->mask(CustomMessageMask::class);

echo $mask->token().'@'.$mask->uid;

更多示例可以在这里找到

特殊

找到包含消息的文件夹

/** @var \Webklex\PHPIMAP\Message $message */
$folder = $message->getFolder();

支持

如果您遇到任何问题或发现错误,请不要犹豫,创建一个新的 问题。然而,请注意,可能需要一些时间才能得到回答。不相关、粗鲁或侮辱性的问题将被无通知删除。

如果您需要即时商业支持,请随时给我发送邮件至 github@webklex.com

注意事项

如果您在问题中编写源代码,请考虑正确格式化。这会让阅读变得更轻松,人们也更可能进行评论并提供帮助 :)

``` php

echo '您的PHP代码...';

```

将变为

echo 'your php code...';

功能与pull请求

每个人都可以为这个项目做出贡献。每个pull请求都会被考虑,但也有可能被拒绝。为了避免不必要的劳动,如果您计划进行较大的更改,请首先考虑创建一个功能问题。当然,如果您只是希望增加一个功能,也可以创建一个新的功能问题 ;)

文档

Client::class

Message::class

Folder::class

Query::class

Attachment::class

Mask::class

MessageMask::class

AttachmentMask::class

MessageCollection::class

扩展 Illuminate\Support\Collection::class

FlagCollection::class

扩展 Illuminate\Support\Collection::class

AttachmentCollection::class

扩展 Illuminate\Support\Collection::class

FolderCollection::class

扩展 Illuminate\Support\Collection::class

已知问题

变更日志

请参阅CHANGELOG以获取有关最近更改的更多信息。

安全

如果您发现任何安全相关的问题,请发送电子邮件至github@webklex.com而不是使用问题跟踪器。

致谢

许可证

MIT许可(MIT)。请参阅许可文件以获取更多信息。