perl - 如何在 IMAP 邮件主题中搜索非 ASCII 文本

标签 perl search substring imap

这是 MWE:

#!/usr/bin/perl

use utf8;
use strict;
use warnings;
use Net::IMAP::Client;
use Encode qw/decode/;
use open ':std', ':encoding(UTF-8)';

my $user = 'my-user@gmail.com';
my $pwd = 'secret';

my $imap = Net::IMAP::Client->new(
    server          => 'imap.gmail.com',
    user            => $user,
    pass            => $pwd,
    ssl             => 1,      # (use SSL? default no)
    ssl_verify_peer => 1,      # (use ca to verify server, default yes)
    port            => 993
) or die "Could not connect to IMAP server: $!";

$imap->login or die('Login failed: ' . $imap->last_error);

# all the incoices from my telephone company
$imap->select('INBOX');
my $messages = $imap->search({
    from    => 'invoice@mgts.ru',
    #subject => '2020',
});

unless(defined($messages))
{
    $imap->logout();
    die "no messages";
}

foreach my $id (@$messages)
{
    my $summary = $imap->get_summaries([$id])->[0];

    my $subject = $summary->subject;
    $subject = decode('MIME-Header', $subject);
    print $subject."\n";
}

这会在邮箱中输出来自 invoice@mgts.ru 的所有发票:

Счёт за услуги ПАО МГТС за Июнь 2017 г.
Счёт за услуги ПАО МГТС за Июль 2017 г.
Счёт за услуги ПАО МГТС за Август 2017 г.
Счёт за услуги ПАО МГТС за Ноябрь 2017 г.
Счёт за услуги ПАО МГТС за Декабрь 2017 г.
Счёт за услуги ПАО МГТС за Ноябрь 2018 г.
Счёт за услуги ПАО МГТС за Декабрь 2018 г.
Счёт за услуги ПАО МГТС за Декабрь 2019 г.
Счёт за услуги ПАО МГТС за Март 2020 г.
Счёт за услуги ПАО МГТС за Апрель 2020 г.

一切都是正确的。

现在我添加新条件,取消注释:

#subject => '2020',

我得到了 2020 年的所有发票:

Счёт за услуги ПАО МГТС за Март 2020 г.
Счёт за услуги ПАО МГТС за Апрель 2020 г.

但是当我在搜索中添加单词“Апрель”(四月)时:

subject => 'Апрель 2020',

尽管事实上该子字符串存在于邮箱中 1 封电子邮件的主题中,但我收到“没有消息”。

电子邮件中的主题如下所示:

Subject: =?utf-8?Q?=D0=A1=D1=87=D1=91=D1=82=20?=

出了什么问题以及如何解决?

最佳答案

  1. Net::IMAP::Client 似乎不支持 IMAP4rev1涵盖 UTF-8 编码的字符串。

  2. 根据 Gmail 文档,您可以使用 X-GM-RAW属性以获取与 Gmail 网络界面相同的结果。

如果我必须使用 Net::IMAP::Client,我会添加一个新方法来执行 X-GM-RAW:

#!/usr/bin/perl

use utf8;
use strict;
use warnings;
use Net::IMAP::Client;
use Encode qw/decode/;
use IO::Socket qw(:crlf);
use open ':std', ':encoding(UTF-8)';

my $user = 'my-user@gmail.com';
my $pwd = 'secret';

my $imap = Net::IMAP::Client->new(
    server          => 'imap.gmail.com',
    user            => $user,
    pass            => $pwd,
    ssl             => 1,      # (use SSL? default no)
    ssl_verify_peer => 1,      # (use ca to verify server, default yes)
    port            => 993
) or die "Could not connect to IMAP server: $!";

$imap->login or die('Login failed: ' . $imap->last_error);

# Add search_gmail method to Net::IMAP::Client
sub Net::IMAP::Client::search_gmail {
    my ($self, $criteria) = @_;

    my @crit;
    for my $key (keys %{$criteria}) {
        push @crit, join ":", $key, $criteria->{$key};
    }

    my $crit_str = join q{ }, @crit;

    my ($ok, $lines);
    ($ok, $lines) = $self->_tell_imap('SEARCH' => "CHARSET UTF-8 X-GM-RAW " . do {
        use bytes;
        sprintf qq{{%d}%s%s}, length($crit_str), $CRLF, $crit_str;
    });

    return unless $ok;

    for my $line (@{$lines->[1]}) {
        if ($line =~ s/^\*\s+SEARCH\s+//ig) {
            $line =~ s/\s*$//g;
            return [ map { $_ + 0 } split(/\s+/, $line) ];
        }
    }
}

# all the incoices from my telephone company
$imap->select('INBOX');
my $messages = $imap->search_gmail({
    from    => 'invoice@mgts.ru',
    #subject => '2020',
});

unless(defined($messages))
{
    $imap->logout();
    die "no messages";
}

foreach my $id (@$messages)
{
    my $summary = $imap->get_summaries([$id])->[0];

    my $subject = $summary->subject;
    $subject = decode('MIME-Header', $subject);
    print $subject."\n";
}

关于perl - 如何在 IMAP 邮件主题中搜索非 ASCII 文本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62783448/

相关文章:

perl - 如何使用 mod_perl 正确减少冗余请求的数量?

perl - 如何让一个 Perl 脚本查看另一个 Perl 脚本中的变量?

javascript - 具有动态经度和纬度的 Algolia 地理搜索 - 距离不正确

php - MySQL 全文找不到行

php - 选择相同列值以字符串开头的行,2 个问题

perl - 在 Perl 中迭代哈希

perl - 如何不匹配字符串?

regex - Graylog 搜索包含字符串

Java - 获取输入字符串的各个子字符串

algorithm - 最大比例子串