3

IMAPメールサーバーに簡単に接続できます。

 use Mail::IMAPClient;
 use MIME::Base64;
 use MIME::Parser;

  my $imap = Mail::IMAPClient->new(
    Server   => '192.168.2.2',
    User     => 'xxxxxx',
    Password => 'yyyyyy',
    Ssl      => 1,
    Uid      => 1,
  );

  my $folders = $imap->folders
    or die "List folders error: ", $imap->LastError, "\n";
  print "Folders: @$folders\n";

$sfolder="INBOX.2012";

$imap->select( $sfolder )
    or die "Select '$Opt{sfolder}' error: ", $imap->LastError, "\n";

my @msgs = $imap->messages or die "Could not messages: $@\n";

ただし、次のようなコードが原因で、必要なテキストとhtmlを簡単に解析できません。

Content-Transfer-Encoding:base64
Content-Type:text/html; charset=utf-8
Content-Transfer-Encoding:base64
Content-Type:text/html; charset=utf-8
Content-Transfer-Encoding:
Content-Type:multipart/mixed; boundary="----------=_4F0F4830.7079357A"
Multipart
Content-Transfer-Encoding:
Content-Type:multipart/mixed;   boundary="----=_Part_4487195_1184536749.1326753403034"
Multipart
Content-Transfer-Encoding:
Content-Type:multipart/alternative; boundary=--boundary_164442_d184e417-739f-
46d6-824a-6ea1846e79de
Multipart
Content-Transfer-Encoding:
Content-Type:multipart/mixed;   boundary="----=_Part_3882878_23916831.1326509484032"
Multipart
Content-Transfer-Encoding:

私はこれを試しましたが、それはごく少数の異なるエンコーディングでしか機能しません。

if  ($imap->get_header($msg,"Content-Transfer-Encoding")=~ /base64/i) {
print "\nMatch base64";
        if    ($imap->get_header($msg,"Content-Type")=~m/text/i )   {
         push(@mail,decode_base64($imap->body_string($msg)));
        }
        elsif ($imap->get_header($msg,"Content-Type")=~m/image/i )
        { print "\nImage detected"; }
        elsif ($imap->get_header($msg,"Content-Type")=~m/application/i )
        { print "\nApplication detected"; }

後で使用したいhtmlまたはテキストを含む7ビットおよび8ビットのバリアントと他のエンコード方法があります。私はdecode_base64()を使用してbase64をデコードすることに成功しました。デコードするのが悪いのは、マルチパートコードを含むものです。私は車輪の再発明をしているような気がします、そして私のためにすべての重労働を行うことができるライブラリまたはモジュールがなければなりません。.jpg、.gif、.pdfなどの他のコンテンツタイプは単に無視する必要があります。マルチパートの電子メールには、私が興味を持っている部分が少なくとも1つ含まれていますが、多くは私には役に立たないものです。

さらに調査した後、この構造には必要な情報がいくつかありますが、それを効率的に取り出す方法がわからないのは別の問題です。

Dumping:$VAR1 = bless( {
                 'bodyparms' => {
                                  'boundary' =>     '----=_NextPart_002_BC64_7D688C1F.A2FF9BE0'
                                },
                 'bodyextra' => undef,
                 '_top' => 1,
             'bodydisp' => 'NIL',
             '_id' => 'HEAD',
             'bodysubtype' => 'mixed',
             'PartsIndex' => {
                               '1.3' => bless( {
                                                 'bodyparms' => 'NIL',
                                                 'bodyid' => '<d9e26cc0-019c-4ac0-9b1e-9c9ac8424f52>',
                                                 'bodyextra' => 'NIL',
                                                 'bodydisp' => 'NIL',
                                                 '_id' => '1.3',
                                                 'bodysubtype' => 'jpeg',
                                                 '_prefix' => '1.3',
                                                 'bodysize' => '4808',
                                                 'bodytype' => 'image',
                                                 'bodyMD5' => 'NIL',
                                                 'bodylang' => 'NIL',
                                                 'bodydesc' => 'NIL',
                                                 'bodyenc' => 'base64'
                                               }, 'Mail::IMAPClient::BodyStructure' ),
                               '1.1' => bless( {
                                                 'bodyparms' => {
                                                                  'boundary' => '----=_NextPart_000_36AE_880DDD08.0A776E35'
                                                                },
                                                 'bodyextra' => undef,
                                                 'bodydisp' => 'NIL',
                                                 '_id' => '1.1',
                                                 'bodysubtype' => 'alternative',
                                                 '_prefix' => '1.1',
                                                 'bodytype' => 'MULTIPART',
                                                 'bodystructure' => [
                                                                      bless( {
                                                                               'bodyparms' => {
                                                                                                'charset' => 'utf-8'
                                                                                              },
                                                                               'bodyextra' => 'NIL',
                                                                               'bodyid' => 'NIL',
                                                                               'bodydisp' => 'NIL',
                                                                               '_id' => '1.1.1',
                                                                               'bodysubtype' => 'PLAIN',
                                                                               '_prefix' => '1.1.1',
                                                                               'bodysize' => '1971',
                                                                               'bodytype' => 'TEXT',
                                                                               'bodyMD5' => 'NIL',
                                                                               'textlines' => '74',
                                                                               'bodylang' => 'NIL',
                                                                               'bodydesc' => 'NIL',
                                                                               'bodyenc' => 'quoted-printable'
                                                                             }, 'Mail::IMAPClient::BodyStructure' ),
                                                                      bless( {
                                                                               'bodyparms' => {
                                                                                                'charset' => 'utf-8'
                                                                                              },
                                                                               'bodyextra' => 'NIL',
                                                                               'bodyid' => 'NIL',
                                                                               'bodydisp' => 'NIL',
                                                                               '_id' => '1.1.2',
                                                                               'bodysubtype' => 'HTML',
                                                                               '_prefix' => '1.1.2',
                                                                               'bodysize' => '23364',
                                                                               'bodytype' => 'TEXT',
                                                                               'bodyMD5' => 'NIL',
                                                                               'textlines' => '331',
                                                                               'bodylang' => 'NIL',
                                                                               'bodydesc' => 'NIL',
                                                                               'bodyenc' => 'quoted-printable'
                                                                             }, 'Mail::IMAPClient::BodyStructure' )
                                                                    ],
                                                 'bodyloc' => 'NIL',
                                                 'bodylang' => 'NIL'
                                               }, 'Mail::IMAPClient::BodyStructure' ),
                               '1' => bless( {
                                               'bodyparms' => {
                                                                'boundary' => '----=_NextPart_001_EA96_2BF8DEDE.32622D51'
                                                              },
                                               'bodyextra' => undef,
                                               'bodydisp' => 'NIL',
                                               '_id' => 1,
                                               'bodysubtype' => 'related',
                                               '_prefix' => 1,
                                               'bodytype' => 'MULTIPART',
                                               'bodystructure' => [
                                                                    $VAR1->{'PartsIndex'}{'1.1'},
                                                                    bless( {
                                                                             'bodyparms' => 'NIL',
                                                                             'bodyid' => '<5dff39db-e81c-4410-be75-8662564fd328>',
                                                                             'bodyextra' => 'NIL',
                                                                             'bodydisp' => 'NIL',
                                                                             '_id' => '1.2',
                                                                             'bodysubtype' => 'jpeg',
                                                                             '_prefix' => '1.2',
                                                                             'bodysize' => '14406',
                                                                             'bodytype' => 'image',
                                                                             'bodyMD5' => 'NIL',
                                                                             'bodylang' => 'NIL',
                                                                             'bodydesc' => 'NIL',
                                                                             'bodyenc' => 'base64'
                                                                           }, 'Mail::IMAPClient::BodyStructure' ),
                                                                    $VAR1->{'PartsIndex'}{'1.3'},
                                                                    bless( {
                                                                             'bodyparms' => 'NIL',
                                                                             'bodyid' => '<717f2ef4-f795-4d1c-87cc-283c9b0a59b0>',
                                                                             'bodyextra' => 'NIL',
                                                                             'bodydisp' => 'NIL',
                                                                             '_id' => '1.4',
                                                                             'bodysubtype' => 'gif',
                                                                             '_prefix' => '1.4',
                                                                             'bodysize' => '2912',
                                                                             'bodytype' => 'image',
                                                                             'bodyMD5' => 'NIL',
                                                                             'bodylang' => 'NIL',
                                                                             'bodydesc' => 'NIL',
                                                                             'bodyenc' => 'base64'
                                                                           }, 'Mail::IMAPClient::BodyStructure' )
                                                                  ],
                                               'bodyloc' => 'NIL',
                                               'bodylang' => 'NIL'
                                             }, 'Mail::IMAPClient::BodyStructure' ),
                               '1.2' => $VAR1->{'PartsIndex'}{'1'}{'bodystructure'}[1],
                               '1.1.2' => $VAR1->{'PartsIndex'}{'1.1'}{'bodystructure'}[1],
                               '2' => bless( {
                                               'bodyparms' => {
                                                                'name' => 'BKD-7361945220.pdf'
                                                              },
                                               'bodyid' => 'NIL',
                                               'bodyextra' => 'NIL',
                                               'bodydisp' => {
                                                               'attachment' => {
                                                                                 'filename' => 'BKD-7361945220.pdf'
                                                                               }
                                                             },
                                               '_id' => 2,
                                               'bodysubtype' => 'octetstream',
                                               '_prefix' => 2,
                                               'bodysize' => '47540',
                                               'bodytype' => 'application',
                                               'bodyMD5' => 'NIL',
                                               'bodystructure' => [],
                                               'bodylang' => 'NIL',
                                               'bodydesc' => 'NIL',
                                               'bodyenc' => 'base64'
                                             }, 'Mail::IMAPClient::BodyStructure' ),
                               '1.4' => $VAR1->{'PartsIndex'}{'1'}{'bodystructure'}[3],
                               '1.1.1' => $VAR1->{'PartsIndex'}{'1.1'}{'bodystructure'}[0]
                             },
             '_prefix' => 'HEAD',
             'PartsList' => [
                              1,
                              '1.1',
                              '1.1.1',
                              '1.1.2',
                              '1.2',
                              '1.3',
                              '1.4',
                              2
                            ],
             'bodytype' => 'MULTIPART',
             'bodystructure' => [
                                  $VAR1->{'PartsIndex'}{'1'},
                                  $VAR1->{'PartsIndex'}{'2'}
                                ],
             'bodyloc' => 'NIL',
             'bodylang' => 'NIL'
           }, 'Mail::IMAPClient::BodyStructure' );

ご覧のとおり、PartsIndexのすべての部分の一部であることが保証されている値はなく、一部の値はネストされています。

各PartsIndexアイテムの対象となる変数:bodytype bodysubtype bodyenc

4

3 に答える 3

1

Courrielを使用してメールメッセージを解析します。

use strictures;
use Mail::IMAPClient qw();
use Courriel qw();

sub walk_parts {
    my ($obj, $callback) = @_;
    if ($obj->is_multipart) {
        for my $part ($obj->parts) {
            walk_parts($part, $callback);
        }
    } else {
        $callback->($obj);
    }
}

my $imap = Mail::IMAPClient->new(
    …
) or die $@;

my $folders = $imap->folders
    or die $imap->LastError;

$imap->select('INBOX')
    or die $imap->LastError;

my @messages = $imap->messages
    or die $imap->LastError;

for my $id (@messages) {
    my $raw = $imap->message_string($id)
        or die $imap->LastError;
    my $email = Courriel->parse(text => $raw);
    walk_parts $email, sub {
        my ($part) = @_;
        my $content = $part->content;
        my $type = $part->mime_type;
    }
}
于 2012-07-01T22:04:23.413 に答える
1

いくつかのビルド済みモジュールを使用してみましたが、依存関係が多すぎて操作が困難でした。このソリューションは、元のソリューション以外の依存関係を追加しません。また、libMagicの依存関係にも問題がありました。上記を参照してください。また、私のプログラムを使用する人にもその問題に対処する必要はありませんでした。

メインの親に対して1回、子ごとに1回、decodeを2回呼び出す必要があります。この$imap->get_bodystructure($ msg);以降 必要な情報がすべて含まれているので、必要のない場所に依存関係を追加する必要があります。手動でデコードする方法を理解するのに何時間もかかりましたが、それだけの価値がありました。

必要なデコーダーをdecode()サブルーチンに追加できます。text/htmlとbase64でエンコードされたバージョンをデコードするだけで済みます。IMAPClient関数は、すべての親と子のリストを提供するため、自分でリストを作成する必要はありません。トリッキーな部分は、それぞれに任意の数の子を持つ任意の数の親を持つことができますが、有用なデータが含まれているのは子だけです。親の値の多くは空白、undef、または「NIL」(文字通り)であるため、親は無視できます。実際、膨大な数の変数が「NIL」の値を持っています。bodyMD5やbodylangのように、電子メールクライアントがユーザーに対して応答できた可能性があるものでさえ、通常は「NIL」に等しくなります。'NIL'の構文解析と他のフィールドの使用が圧倒的に多いため、無駄になる可能性があります。

さらに質問がある場合はコメントを残してください。

 use Mail::IMAPClient;
 use MIME::Base64;
 use MIME::Parser;

sub decode  {
($process, $imap) =@_;
if ($process->bodytype eq "TEXT") {
   print "\n Text SubType:".$process->bodysubtype;
   if ($process->bodyenc eq "base64") {
        return decode_base64($imap->bodypart_string($msg,$process->id));
        }
   elsif (index(" -7bit- -8bit- -quoted-printable- ",lc($process->bodyenc)) !=-1  ) {
        return $imap->bodypart_string($msg,$process->id);
        }
print "\n==========Insert new decoder here============";
print "\n".$imap->bodypart_string($msg,$process->id);
print "\n=================================================";

}

return "";
}

#insert your login code with credentials here


$imap->select( $sfolder )
or die "Select '$Opt{sfolder}' error: ", $imap->LastError, "\n";

my @msgs = $imap->messages or die "Could not messages: $@\n";


foreach $msg (@msgs) {


my $raw = $imap->message_string($msg)
    or die $imap->LastError;

$struct = $imap->get_bodystructure($msg);


#MULTIPART is a container designation and does not contain anything useful by itself.
#However it will still process all of the children that have content
if ($struct->bodytype ne "MULTIPART") { print "\n BodyEnc:".$struct->bodyenc();}

$rDecode=decode($struct,$imap);
#do not insert blanks.
if ($rDecode ne "" && (length($rDecode)>2)) {push(@mail,$rDecode); }


foreach $dumpme ($struct->bodystructure()) {
if ($dumpme->bodytype() eq "MULTIPART") {next;}

$rDecode="";
$rDecode=decode($dumpme,$imap);
#do not insert blanks.
if (($rDecode ne "") && (length($rDecode)>2) ) {
push(@mail,$rDecode); }


}

}
于 2012-07-08T04:02:23.587 に答える
0

MIMEパーサーが必要です。残念ながら、それでも、MIMEで同じデータを表す方法は複数あるため、独自の正規化が必要になります。

于 2012-07-01T07:15:54.593 に答える