[Mew-dist 1663] IM-63 IMAP (Re: )

若宮賢二 wkenji at example.com
1997年 8月 26日 (火) 19:47:54 JST


若宮@富士通研です。

// "motonori" = motonori at example.com (Motonori Nakamura) 氏談:

motonori> UID を使ってないところも使うようにしたのと、
motonori> imls %folder last:3 のように書くこともできるようにしました。

  どうも有難うございます。ところで、UID FETCH の場合でも FETCH レスポ
  ンスの `*' の直後は UID ではなく Sequence Number ということなので、
  /^\* $num FETCH \(UID \d+ … の $num と \d+ は逆になりますよね?

  あと、うちでは WU 版と Sun 版の IMAP サーバで試しているのですが、Sun 
  の方は UID FETCH へのレスポンスに含まれる UID 属性が、レスポンスの先
  頭ではなく最後に付いてきます;-)。さすがに他の属性に混ぜて途中に入れ
  てくるサーバはないと信じたいですが…。Cyrus などはどうでしょうか?

  この二つへの対応と、
    - imap_scan_folder で、`ラストUID+1'-last を指定され、かつ新着が
      ない場合に last の行をもう一度表示していたバグを除去。
    - RFC822 以外の FETCH ではおまけ FLAGS 属性は付いてこないので、
      そのチェックを除去。
    - imap_process 内の for ループを全 UID をなめる foreach に変更。
    - imap_get、imap_head、imap_from で、指定されたメッセージが
      なかった場合に 1 を返すように (元は imcat 向け)。
    - imcat で、"$msg not found" を imap_get の返り値を見て表示する
      ように。
  といった変更をしてみました。UID が飛び飛びの %inbox に対して imls や 
  imcat、imget --mode=from などを試してみたところ、一応使えています。

  [Mew-dist 1603]、[Mew-dist 1604] のパッチが当たった IM-63 へのパッチ
  として添付させて頂きます。

motonori> # imls のときに、本文の先頭が見られないのが残念ですね。

  IMAP4rev1 対応のサーバに限ればですが、ボディのうち指定したオクテット
  分だけを FETCH できますよね。でも IM は先頭の引用などを取り除いて表
  示するようになっているので、あれ用に予めどのくらい FETCH しておけば
  よいのか、その見積りが難しそうです…。

// Kenji    | mailto:wkenji at example.com (office)
// Wakamiya | mailto:wkenji at example.com (private)
-------------- next part --------------
--- Imap.pm.in.orig	Tue Aug 26 18:19:41 1997
+++ Imap.pm.in	Tue Aug 26 18:30:33 1997
@@ -193,8 +193,8 @@
     im_notice("getting message $num.\n");
     my $resp = &send_command(\*IMAPd, "im$seq UID FETCH $num RFC822", '');
     my $failed = 0;
-    if ($resp =~ /^\* $num FETCH \(UID \d+ RFC822 \{(\d+)\}/i) {
-	my $size = $1;
+    if ($resp =~ /^\* \d+ FETCH \((UID $num )?RFC822 \{(\d+)\}/i) {
+	my $size = $2;
 	while (<IMAPd>) {
 	    $size -= length($_);
 	    s/\r\n$/\n/;
@@ -203,10 +203,13 @@
 	    last if ($size <= 0);
 	}
 	$resp = &next_response(\*IMAPd);
-	return (-1, 0) if ($resp !~ /^\)/ && $resp !~ /^ FLAGS \(.*\)\)/);
+	return (-1, 0) if ($resp !~ /^\)/ &&
+			   $resp !~ /^( FLAGS \(.*\)| UID $num)+\)/);
+    } elsif ($resp =~ /^im$seq OK/) {
+	return (1, 0);
     } else {
 	$failed = 1;
-	im_warn("FETCH command failed.\n");
+	im_warn("UID FETCH command failed.\n");
     }
     $resp = &next_response(\*IMAPd);
     return (-1, 0) if ($resp !~ /^im$seq OK/);
@@ -224,8 +227,8 @@
     local (%head);
     undef %head;
     if ($resp =~
-      /^\* $num FETCH \(UID \d+ RFC822.SIZE (\d+) RFC822.HEADER \{(\d+)\}/i) {
-	my ($size, $len) = ($1, $2);
+    /^\* \d+ FETCH \((UID $num )?RFC822.SIZE (\d+) RFC822.HEADER \{(\d+)\}/i) {
+	my ($size, $len) = ($2, $3);
 	my $field = '';
 	while (<IMAPd>) {
 	    $len -= length($_);
@@ -250,10 +253,12 @@
 #	$head{'bytes:'} = $size;
 	$head{'kbytes:'} = int(($size + 1023) / 1024);
 	$resp = &next_response(\*IMAPd);
-	return (-1, 0) if ($resp !~ /^\)/ && $resp !~ /^ FLAGS \(.*\)\)/);
+	return (-1, 0) if ($resp !~ /^\)/ && $resp !~ /^ UID $num\)/);
+    } elsif ($resp =~ /^im$seq OK/) {
+	return (1, 0);
     } else {
 	$failed = 1;
-	im_warn("FETCH command failed.\n");
+	im_warn("UID FETCH command failed.\n");
     }
     $resp = &next_response(\*IMAPd);
     return (-1, 0) if ($resp !~ /^im$seq OK/);
@@ -270,8 +275,8 @@
 #     "im$seq UID FETCH $num RFC822.HEADER.LINES (From Date Subject)", '');
     my $resp = &send_command(\*IMAPd,
       "im$seq UID FETCH $num RFC822.HEADER.LINES (From)", '');
-    if ($resp =~ /^\* $num FETCH \(UID \d+ RFC822.* \{(\d+)\}/i) {
-	my $size = $1;
+    if ($resp =~ /^\* \d+ FETCH \((UID $num )?RFC822.* \{(\d+)\}/i) {
+	my $size = $2;
 	my $found = 0;
 	my $f;
 	while (<IMAPd>) {
@@ -292,10 +297,12 @@
 	$f = '(sender unknown)' unless ($f);
 	print "From $f\n";
 	$resp = &next_response(\*IMAPd);
-	return -1 if ($resp !~ /^\)/ && $resp !~ /^ FLAGS \(.*\)\)/);
+	return (-1, 0) if ($resp !~ /^\)/ && $resp !~ /^ UID $num\)/);
+    } elsif ($resp =~ /^im$seq OK/) {
+	return 1;
     } else {
 	$failed = 1;
-	im_warn("FETCH command failed.\n");
+	im_warn("UID FETCH command failed.\n");
     }
     $resp = &next_response(\*IMAPd) if ($resp !~ /^im$seq/);
     return -1 if ($resp !~ /^im$seq OK/);
@@ -313,8 +320,8 @@
     while ($resp !~ /^im$seq/) {
 	if ($resp =~ /^\* NO/i) {
 	    $failed = 1;
-	} elsif ($resp =~
-	  /^\*\s+$num\s+FETCH\s+\(UID \d+ FLAGS\s+\((.*)\)\)/i) {
+	} elsif ($resp =~ /^\* \d+ FETCH \(UID $num FLAGS \((.*)\)\)/i ||
+		 $resp =~ /^\* \d+ FETCH \(FLAGS \((.*)\) UID $num\)/i) {
 	    $flags = $1;
 	}
 	$resp = &next_response(\*IMAPd);
@@ -470,7 +477,7 @@
 # imap_process(how, host, src, dst)
 sub imap_process ($$$$) {
     my ($how, $host, $src, $dst) = @_;
-    my ($msgs, $i);
+    my ($msgs);
     return -1 if (($msgs = &imap_select($src, 1)) < 0);
     if ($how eq 'check') {
 	if ($msgs > 0) {
@@ -480,7 +487,9 @@
 	}
     } elsif ($how eq 'from') {
 	if ($msgs > 0) {
-	    for ($i = 1; $i <= $msgs; $i++) {
+	    my @alluids = &imap_all_uids();
+	    return -1 if ($alluids[0] < 0);
+	    foreach $i (@alluids) {
 		return -1 if (&imap_from($i) < 0);
 	    }
 	    im_info("$msgs message(s) at $host.\n");
@@ -490,7 +499,9 @@
     } elsif ($how eq 'get') {
 	if ($msgs > 0) {
 	    im_info("Getting new messages from $host into $dst....\n");
-	    for ($i = 1; $i <= $msgs; $i++) {
+	    my @alluids = &imap_all_uids();
+	    return -1 if ($alluids[0] < 0);
+	    foreach $i (@alluids) {
 		my ($rc, $message) = &imap_get($i);
 		return -1 if ($rc < 0);
 		return -1 if (&store_message($message, $dst) < 0);
@@ -592,13 +603,14 @@
     my $uid, $size, $len;
 
     my $msgset = &imap_range2set(@ranges);
+    return  0 if !$msgset;
     return -1 if ($msgset < 0);
     my $seq = $ImapSeq++;
     my $resp = &send_command(\*IMAPd,
-	"im$seq UID FETCH $msgset (UID RFC822.SIZE RFC822.HEADER)", '');
+	"im$seq UID FETCH $msgset (RFC822.SIZE RFC822.HEADER)", '');
     while ($resp =~
-    /^\* \d+ FETCH \(UID (\d+) RFC822.SIZE (\d+) RFC822\.HEADER \{(\d+)\}/i) {
-	($uid, $size, $len) = ($1, $2, $3);
+  /^\* \d+ FETCH \((UID (\d+) )?RFC822.SIZE (\d+) RFC822\.HEADER \{(\d+)\}/i) {
+	($uid, $size, $len) = ($2, $3, $4);
 	my @hdr;
 	while (<IMAPd>) {
 	    $len -= length;
@@ -608,7 +620,12 @@
 	    last if ($len <= 0);
 	}
 	$resp = &next_response(\*IMAPd);
-	return -1 if ($resp !~ /^\)/);
+	if (!$uid) {
+	    return -1 if ($resp !~ /^ UID (\d+)\)/);
+	    $uid = $1;
+	} else {
+	    return -1 if ($resp !~ /^\)/);
+	}
 
 	my %Head;
 	&store_header(\%Head, join('', @hdr));
@@ -627,7 +644,7 @@
 	$resp = &next_response(\*IMAPd);
     }
     if ($resp !~ /^im$seq OK/) {
-	im_warn("FETCH command failed.\n");
+	im_warn("UID FETCH command failed.\n");
 	return -1;
     }
     return 0;
@@ -635,7 +652,7 @@
 
 sub imap_range2set (@) {
     my @ranges = @_;
-    my (@uids, $fromuid, $touid, $dir);
+    my (@uids, $fromuid, $dir);
 
     my @alluids = &imap_all_uids();
     return -1 if ($alluids[0] < 0);
@@ -646,8 +663,11 @@
     foreach (@ranges) {
 	if (/^(\d+|first|last)-(\d+|first|last)$/) {
 	    $fromuid = &imap_message_number($min, $max, $1);
-	    $touid   = &imap_message_number($min, $max, $2);
-	    $_ = "$fromuid:$touid";
+	    if ($fromuid > $max) {
+		$_ = '';
+	    } else {
+		$_ = "$fromuid:" . &imap_message_number($min, $max, $2);
+	    }
 	} elsif (/^(\d+|last|first):([+-]?)(\d+)$/) {
 	    if ($1 eq 'last') {
 		$dir = ($2 eq '+') ? +1 : -1;
@@ -664,10 +684,15 @@
 	    }
 	    $_ = join(',', @uids);
 	} elsif (/^(\d+|first|last)$/) {
-	    $_ = &imap_message_number($min, $max, $1);
+	    $fromuid = &imap_message_number($min, $max, $1);
+	    if ($fromuid > $max) {
+		$_ = '';
+	    } else {
+		$_ = $fromuid;
+	    }
 	}
     }
-    return join(',', @ranges);
+    return join(',', grep($_, @ranges));
 }
 
 sub imap_all_uids () {
@@ -678,7 +703,7 @@
     if ($resp =~ /^\* SEARCH (\d+( +\d+)*)/i) {
 	@uids = split(' ', $1);
     } else {
-	im_warn("SEARCH command failed.\n");
+	im_warn("UID SEARCH command failed.\n");
     }
     $resp = &next_response(\*IMAPd);
     return (-1) if ($resp !~ /^im$seq OK/);
-------------- next part --------------
--- imcat.in.orig	Tue Aug 19 21:00:05 1997
+++ imcat.in	Tue Aug 26 15:13:00 1997
@@ -143,7 +143,7 @@
     foreach (@$art) {
 	print;
     }
-} elsif ($opt_src =~ /^%(.*)/) {
+} elsif ($opt_src =~ /^(%.*)/) {
     # IMAP folder (%folder[:[user[/auth]]@server])
     require IM::Imap && import IM::Imap;
     require IM::GetPass && import IM::GetPass;
@@ -164,14 +164,13 @@
     if ($msgs < 0) {
 	&imap_close;
 	im_warn("can't access to $folder\n");
-    } elsif ($msgs < $msg) {
-	&imap_close;
-	im_warn("message $msg not found in \%$folder\n");
     } else {
 	my ($rc, $message) = &imap_get($msg);
 	&imap_close;
 	if ($rc < 0) {
 	    im_die("can't access to message $msg in \%$folder.\n");
+	} elsif ($rc > 0) {
+	    im_warn("message $msg not found in \%$folder\n");
 	}
 	foreach (@$message) {
 	    print;


Mew-dist メーリングリストの案内