Ниже приведена простая программа, которая делает то, что вы хотите.
#! /usr/bin/perl
use warnings;
use strict;
Минимальная версия для Email::MIME
предназначена для введения walk_parts
.
use Email::MIME 1.901;
use IO::Socket::SSL;
use Mail::IMAPClient;
use POSIX qw/ strftime /;
use Term::ReadKey;
Вы не хотите жестко кодировать пароль в своей программе?
sub read_password {
local $| = 1;
print "Enter password: ";
ReadMode "noecho";
my $password = <STDIN>;
ReadMode "restore";
die "$0: unexpected end of input"
unless defined $password;
print "\n";
chomp $password;
$password;
}
Подключение с использованием SSL. Мы должны быть в состоянии сделать это с помощью простого параметра Ssl
для конструктора, но некоторые поставщики решили разбить его в своих пакетах.
my $pw = read_password;
my $imap = Mail::IMAPClient->new(
#Debug => 1,
User => "you\@domain.com",
Password => $pw,
Uid => 1,
Peek => 1, # don't set \Seen flag
Socket => IO::Socket::SSL->new(
Proto => 'tcp',
PeerAddr => 'imap.domain.com',
PeerPort => 993,
),
);
die "$0: connect: $@" if defined $@;
Если вам нужна папка, отличная от папки «Входящие», измените ее.
$imap->select("INBOX")
or die "$0: select INBOX: ", $imap->LastError, "\n";
Используя поиск по IMAP, мы ищем все сообщения, темы которых содержат сегодняшнюю дату в формате ГГГГММДД. Дата может быть где угодно в теме, поэтому, например, тема «foo bar baz 20100316» будет соответствовать сегодня.
my $today = strftime "%Y%m%d", localtime $^T;
my @messages = $imap->search(SUBJECT => $today);
die "$0: search: $@" if defined $@;
Для каждого такого сообщения записывать его вложения в файлы в текущем каталоге. Мы пишем самый внешний слой вложений и не копаем вложенные вложения. Часть с параметром имени в его типе содержимого (как в image/jpeg; name="foo.jpg"
) считается вложением, и мы игнорируем все остальные части. Имя сохраненного вложения - это следующие компоненты, разделенные -
: сегодняшняя дата, идентификатор сообщения IMAP, индекс позиции в сообщении и его имя на основе единицы.
foreach my $id (@messages) {
die "$0: funky ID ($id)" unless $id =~ /\A\d+\z/;
my $str = $imap->message_string($id)
or die "$0: message_string: $@";
my $n = 1;
Email::MIME->new($str)->walk_parts(sub {
my($part) = @_;
return unless ($part->content_type =~ /\bname=([^"]+)/
or $part->content_type =~ /\bname="([^"]+)"/); # " grr...
my $name = "./$today-$id-" . $n++ . "-$1";
print "$0: writing $name...\n";
open my $fh, ">", $name
or die "$0: open $name: $!";
print $fh $part->content_type =~ m!^text/!
? $part->body_str
: $part->body
or die "$0: print $name: $!";
close $fh
or warn "$0: close $name: $!";
});
}