[Mew-dist 3178] IMAP refile, rm

若宮賢二 wkenji at example.com
1997年 12月 15日 (月) 11:49:22 JST


若宮@富士通研です。

遅い遅いと言いつつ:)、Mew を IMAP 対応にすべくチビチビいじってきました
が、取り敢えず refile と rm も IMAP 経由で行なえるようになりましたので 
Mew-1.92.4、IM-76 に反映したものをポストしておきます。

refile は、ローカル−リモート間、リモート−リモート間 (複数サーバ対応) 
にも対応しています。が、このため、Imap.pm 内の各ルーチンをファイルハン
ドル (typeglob) 付きで呼び出すように変更してしまいました。また、Mew か
らの immv の呼出しを start-process にしました (新規アクセス用 IMAP パ
スワードの送り込みのため)。一応、process-status を見て終了まで待つよう
にしています。imcat、imrm の呼出しではパスワードのやりとりを考慮してい
ません。impwagent を前提にしています (Win32 でも動くようになったので)。
その他、impath に不完全な IMAP フォルダ名 (%inbox など) を渡したときに
完全な名前 (%inbox:foo/AUTH at example.com) を返す機能を追加しました。

IMAP フォルダの存在確認は、単純に .mew-cache 用ディレクトリ 
(@server#user という形式にしてます) の有無を基準にしています。
goto-folder 時に cache-dir がなければ、"cache-dir がないよ、作る?" と
だけ聞きます。ユーザはそこで示されたフォルダ名が間違いだと気づけばやめ
ればよいし、フォルダ本体はあるはずだと思えば y で進めばよいです。実際
には存在しないのに y で進んでもエラーにはならず、空のサマリが表示され
て、意味のない cache-dir ができます。n と答えた場合は、No such folder 
のメッセージが表示されて終りです。

新規に IMAP フォルダが作られるのは、refile 先としてまだ存在しない IMAP 
フォルダを指定した時のみです。この場合、"cache-dir がないから多分 IMAP 
フォルダ自体もないよ、作る?" と聞いて、y なら進んで immv に IMAP フォ
ルダを作らせます。

やはり遅いですが(^^;、IMAP フォルダを使用しなければ普通の Mew/IM と同
じように使えると思いますので、興味のある方はパッチして試してみて下さい。

# UsePwAgent=yes と PwAgentPort=6543 をお忘れなく。
# ImapAccount も設定しておいたほうが楽です。

// Kenji    | mailto:wkenji at example.com (office)
// Wakamiya | mailto:wkenji at example.com (private)
-------------- next part --------------
diff -aruN im-76-/IM.in/Imap.pm.in im-76/IM.in/Imap.pm.in
--- im-76-/IM.in/Imap.pm.in	Fri Oct 24 18:53:59 1997
+++ im-76/IM.in/Imap.pm.in	Fri Nov 28 15:13:02 1997
@@ -34,7 +34,8 @@
     imap_open imap_close imap_select imap_head imap_from imap_get imap_put
     imap_delete imap_copy imap_flags
     imap_list_folder imap_create_folder imap_delete_folder imap_rename_folder
-    imap_get_msg imap_process imap_spec imap_scan_folder
+    imap_get_msg imap_process imap_spec imap_range2set imap_range2msgs
+    imap_folder_regname imap_folder_name imap_folder_acct imap_scan_folder 
 );
 
 =head1 NAME
@@ -47,7 +48,7 @@
 
 =cut
 
-use vars qw(*IMAPd $ImapSeq);
+use vars qw($ImapSeq);
 ########################
 # IMAP access routines #
 ########################
@@ -61,15 +62,16 @@
     my ($auth, $host, $user, $pass) = @_;
     my ($data, $seq, $errmsg);
     my (@host_list) = ($host);
+    my $HANDLE;
 
     $pass = '*' unless ($pass);
     $ImapSeq = 100 unless ($ImapSeq);
     $seq = $ImapSeq++;
     im_notice("opening IMAP session\n");
     &tcp_logging(0);
-    *IMAPd = &connect_server(\@host_list, 'imap', 0);
-    return -1 unless ($IMAPd);
-    my $resp = &send_command(\*IMAPd, '', '');
+    $HANDLE = &connect_server(\@host_list, 'imap', 0);
+    return -1 unless ($HANDLE);
+    my $resp = &send_command($HANDLE, '', '');
     if ($resp !~ /^\* OK/i) {
 	im_warn($resp);
 	return -1;
@@ -81,18 +83,18 @@
 	    $pw =~ s/([\\"])/\\$1/g;	# escape specials
 	    $pw = "\"$pw\"";		# quote it
 	}
-	$resp = &send_command(\*IMAPd, "im$seq LOGIN $user $pw",
+	$resp = &send_command($HANDLE, "im$seq LOGIN $user $pw",
 	  "im$seq LOGIN $user PASSWORD");
 	while ($resp !~ /^im$seq/) {
 	    if ($resp =~ /^\* NO/i) {
 #		$failed = 1;
 		$errmsg = $resp;
 	    }
-	    $resp = &next_response(\*IMAPd);
+	    $resp = &next_response($HANDLE);
 	}
     } else {
 	require IM::EncDec && import IM::EncDec;
-	$resp = &send_command(\*IMAPd, "im$seq AUTHENTICATE LOGIN", '');
+	$resp = &send_command($HANDLE, "im$seq AUTHENTICATE LOGIN", '');
 	if ($resp =~ /^\+ (.*)/) {
 	    $data = &b_decode_string($1);
 	    im_debug("got \"$data\"\n") if (&debug('imap') || &verbose);
@@ -104,7 +106,7 @@
 	    $data = &b_encode_string($user);
 	    im_debug("sending $user with base64 encoding.\n")
 	      if (&debug('imap') || &verbose);
-	    $resp = &send_command(\*IMAPd, $data,
+	    $resp = &send_command($HANDLE, $data,
 	      "Base64-encoded-username($user)");
 	    if ($resp =~ /^\+ (.*)/) {
 		$data = &b_decode_string($1);
@@ -118,14 +120,14 @@
 	    $data = &b_encode_string($pass);
 	    im_debug("sending PASSWORD with base64 encoding.\n")
 	      if (&debug('imap') || &verbose);
-	    $resp = &send_command(\*IMAPd, $data, "Base64-encoded-password");
+	    $resp = &send_command($HANDLE, $data, "Base64-encoded-password");
 	}
 	while ($resp !~ /^im$seq/) {
 	    if ($resp =~ /^\* NO/i) {
 #		$failed = 1;
 		$errmsg = $resp;
 	    }
-	    $resp = &next_response(\*IMAPd);
+	    $resp = &next_response($HANDLE);
 	}
     }
     if ($resp !~ /^im$seq OK/) {
@@ -135,18 +137,19 @@
 	return -1
     }
     return -1 if ($failed);
-    return 0;
+    return (0, $HANDLE);
 }
 
-sub imap_close () {
+sub imap_close ($) {
+    my ($HANDLE) = @_;
     my ($seq) = $ImapSeq++;
     my $failed = 0;
-    if (0) {
+    if (1) {
 	im_notice("closing IMAP session.\n");
-	my $resp = &send_command(\*IMAPd, "im$seq CLOSE", '');
+	my $resp = &send_command($HANDLE, "im$seq CLOSE", '');
 	while ($resp !~ /^im$seq/) {
 	    $failed = 1 if ($resp =~ /^\* NO/i);
-	    $resp = &next_response(\*IMAPd);
+	    $resp = &next_response($HANDLE);
 	}
 	return -1 if ($resp !~ /^im$seq OK/);
 #	return -1 if ($failed);
@@ -154,27 +157,27 @@
 	$failed = 0;
     }
     my $resp;
-    $resp = &send_command(\*IMAPd, "im$seq LOGOUT", '');
+    $resp = &send_command($HANDLE, "im$seq LOGOUT", '');
     while ($resp !~ /^im$seq/) {
 	$failed = 1 if ($resp =~ /^\* NO/i);
-	$resp = &next_response(\*IMAPd);
+	$resp = &next_response($HANDLE);
     }
     return -1 if ($resp !~ /^im$seq OK/);
 #   return -1 if ($failed);
-    close(IMAPd);
+    close($HANDLE);
     return 0;
 }
 
-sub imap_select ($$) {
-    my ($mbox, $select) = @_;
+sub imap_select ($$$) {
+    my ($HANDLE, $mbox, $select) = @_;
     my ($seq) = $ImapSeq++;
     my ($resp, @field);
     if ($select) {
 	im_notice("select mbox $mbox and getting number of message.\n");
-	$resp = &send_command(\*IMAPd, "im$seq SELECT $mbox", '');
+	$resp = &send_command($HANDLE, "im$seq SELECT $mbox", '');
     } else {
 	im_notice("examine mbox $mbox and getting number of message.\n");
-	$resp = &send_command(\*IMAPd, "im$seq EXAMINE $mbox", '');
+	$resp = &send_command($HANDLE, "im$seq EXAMINE $mbox", '');
     }
     my $msgs = -1;
     my $failed = 0;
@@ -188,27 +191,28 @@
 	    $msgs = $field[1];
 	} elsif ($field[2] =~ /^recent$/i) {
 	}
-	$resp = &next_response(\*IMAPd);
+	$resp = &next_response($HANDLE);
     }
-    return -1 if ($resp !~ /^im$seq OK \[READ-WRITE\]/i);
+    return -1 if ($select && $resp !~ /^im$seq OK \[READ-WRITE\]/i);
+    return -1 if (!$select && $resp !~ /^im$seq OK \[READ-ONLY\]/i);
 #   return -1 if ($failed);
     return -1 if ($msgs < 0);
     im_notice("$msgs message(s) found.\n");
     return $msgs;
 }
 
-sub imap_get ($) {
-    my ($num) = @_;
+sub imap_get ($$) {
+    my ($HANDLE, $num) = @_;
     my ($seq) = $ImapSeq++;
     my (@message);
     im_notice("getting message $num.\n");
-    my $resp = &send_command(\*IMAPd, "im$seq UID FETCH $num RFC822", '');
+    my $resp = &send_command($HANDLE, "im$seq UID FETCH $num RFC822", '');
     my $failed = 0;
     if ($resp =~ /^\* \d+ FETCH \((UID $num )?RFC822 \{(\d+)\}/i) {
 	my $size = $2;
 	alarm(20) unless win95p();
 	$! = 0;
-	while (<IMAPd>) {
+	while (<$HANDLE>) {
 	    unless (win95p()) {
 		alarm(0);
 		if ($!) {   # may be channel truoble
@@ -223,7 +227,7 @@
 	    last if ($size <= 0);
 	}
 	alarm(0) unless win95p();
-	$resp = &next_response(\*IMAPd);
+	$resp = &next_response($HANDLE);
 	return (-1, 0) if ($resp !~ /^\)/ &&
 			   $resp !~ /^( FLAGS \(.*\)| UID $num)+\)/);
     } elsif ($resp =~ /^im$seq OK/) {
@@ -232,17 +236,17 @@
 	$failed = 1;
 	im_warn("UID FETCH command failed.\n");
     }
-    $resp = &next_response(\*IMAPd);
+    $resp = &next_response($HANDLE);
     return (-1, 0) if ($resp !~ /^im$seq OK/);
 #   return (-1, 0) if ($failed);
     return (0, \@message);
 }
 
-sub imap_head ($) {
-    my ($num) = @_;
+sub imap_head ($$) {
+    my ($HANDLE, $num) = @_;
     my ($seq) = $ImapSeq++;
     im_notice("getting header of message $num.\n");
-    my $resp = &send_command(\*IMAPd,
+    my $resp = &send_command($HANDLE,
       "im$seq UID FETCH $num (RFC822.SIZE RFC822.HEADER)", '');
     my $failed = 0;
     my (%head);
@@ -253,7 +257,7 @@
 	my $field = '';
 	alarm(20) unless win95p();
 	$! = 0;
-	while (<IMAPd>) {
+	while (<$HANDLE>) {
 	    unless (win95p()) {
 		alarm(0);
 		if ($!) {   # may be channel truoble
@@ -283,7 +287,7 @@
 	alarm(0) unless win95p();
 #	$head{'bytes:'} = $size;
 	$head{'kbytes:'} = int(($size + 1023) / 1024);
-	$resp = &next_response(\*IMAPd);
+	$resp = &next_response($HANDLE);
 	return (-1, 0) if ($resp !~ /^\)/ && $resp !~ /^ UID $num\)/);
     } elsif ($resp =~ /^im$seq OK/) {
 	return (1, 0);
@@ -291,20 +295,20 @@
 	$failed = 1;
 	im_warn("UID FETCH command failed.\n");
     }
-    $resp = &next_response(\*IMAPd);
+    $resp = &next_response($HANDLE);
     return (-1, 0) if ($resp !~ /^im$seq OK/);
 #   return (-1, 0) if ($failed);
     return (0, \%head);
 }
 
-sub imap_from ($) {
-    my ($num) = @_;
+sub imap_from ($$) {
+    my ($HANDLE, $num) = @_;
     my $seq = $ImapSeq++;
     my $failed = 0;
     im_notice("getting sender information of message $num.\n");
-#   my $resp = &send_command(\*IMAPd,
+#   my $resp = &send_command($HANDLE,
 #     "im$seq UID FETCH $num RFC822.HEADER.LINES (From Date Subject)", '');
-    my $resp = &send_command(\*IMAPd,
+    my $resp = &send_command($HANDLE,
       "im$seq UID FETCH $num RFC822.HEADER.LINES (From)", '');
     if ($resp =~ /^\* \d+ FETCH \((UID $num )?RFC822.* \{(\d+)\}/i) {
 	my $size = $2;
@@ -312,7 +316,7 @@
 	my $f;
 	alarm(20) unless win95p();
 	$! = 0;
-	while (<IMAPd>) {
+	while (<$HANDLE>) {
 	    unless (win95p()) {
 		alarm(0);
 		if ($!) {   # may be channel truoble
@@ -337,7 +341,7 @@
 	$f =~ s/\n[ \t]*/ /g;
 	$f = '(sender unknown)' unless ($f);
 	print "From $f\n";
-	$resp = &next_response(\*IMAPd);
+	$resp = &next_response($HANDLE);
 	return -1 if ($resp !~ /^\)/ && $resp !~ /^ UID $num\)/);
     } elsif ($resp =~ /^im$seq OK/) {
 	return 1;
@@ -345,19 +349,19 @@
 	$failed = 1;
 	im_warn("UID FETCH command failed.\n");
     }
-    $resp = &next_response(\*IMAPd) if ($resp !~ /^im$seq/);
+    $resp = &next_response($HANDLE) if ($resp !~ /^im$seq/);
     return -1 if ($resp !~ /^im$seq OK/);
 #   return -1 if ($failed);
     return 0;
 }
 
-sub imap_flags ($) {
-    my ($num) = @_;
+sub imap_flags ($$) {
+    my ($HANDLE, $num) = @_;
     my $seq = $ImapSeq++;
     my ($flags);
     im_notice("getting flags for $num.\n");
     my $failed = 0;
-    my $resp = &send_command(\*IMAPd, "im$seq UID FETCH $num FLAGS", '');
+    my $resp = &send_command($HANDLE, "im$seq UID FETCH $num FLAGS", '');
     while ($resp !~ /^im$seq/) {
 	if ($resp =~ /^\* NO/i) {
 	    $failed = 1;
@@ -365,34 +369,35 @@
 		 $resp =~ /^\* \d+ FETCH \(FLAGS \((.*)\) UID $num\)/i) {
 	    $flags = $1;
 	}
-	$resp = &next_response(\*IMAPd);
+	$resp = &next_response($HANDLE);
     }
     return '' if ($resp !~ /^im$seq OK/);
     return '' if ($failed);
     return $flags;
 }
 
-sub imap_delete ($) {
-    my ($num) = @_;
+sub imap_delete ($$) {
+    my ($HANDLE, $num) = @_;
     my $seq = $ImapSeq++;
     my $failed = 0;
     im_notice("deleting message $num.\n");
-    my $resp = &send_command(\*IMAPd,
+    my $resp = &send_command($HANDLE,
 	"im$seq UID STORE $num +FLAGS (\\Deleted)", '');
     while ($resp !~ /^im$seq/) {
 	$failed = 1 if ($resp =~ /^\* NO/i);
-	$resp = &next_response(\*IMAPd);
+	$resp = &next_response($HANDLE);
     }
     return -1 if ($resp !~ /^im$seq OK/);
 #   return -1 if ($failed);
     return 0;
 }
 
-sub imap_list_folder () {
+sub imap_list_folder ($) {
+    my ($HANDLE) = @_;
     my $seq = $ImapSeq++;
     my $failed = 0;
     im_notice("listing folders.\n");
-    my $resp = &send_command(\*IMAPd, "im$seq LIST \"\" *", '');
+    my $resp = &send_command($HANDLE, "im$seq LIST \"\" *", '');
     my (@folders) = ();
     while ($resp !~ /^im$seq/) {
 	$failed = 1 if ($resp =~ /^\* NO/i);
@@ -401,87 +406,88 @@
             push(@folders, $3)
               if (grep('\\NoInferiors' eq $_, split(' ', $1)));
         }
-	$resp = &next_response(\*IMAPd);
+	$resp = &next_response($HANDLE);
     }
     return -1 if ($resp !~ /^im$seq OK/);
 #   return -1 if ($failed);
     return @folders;
 }
 
-sub imap_create_folder ($) {
-    my ($folder) = @_;
+sub imap_create_folder ($$) {
+    my ($HANDLE, $folder) = @_;
     my $seq = $ImapSeq++;
     my $failed = 0;
     im_notice("creating folder $folder.\n");
-    my $resp = &send_command(\*IMAPd, "im$seq CREATE $folder", '');
+    my $resp = &send_command($HANDLE, "im$seq CREATE $folder", '');
     while ($resp !~ /^im$seq/) {
 	$failed = 1 if ($resp =~ /^\* NO/i);
-	$resp = &next_response(\*IMAPd);
+	$resp = &next_response($HANDLE);
     }
     return -1 if ($resp !~ /^im$seq OK/);
 #   return -1 if ($failed);
     return 0;
 }
 
-sub imap_delete_folder ($) {
-    my ($folder) = @_;
+sub imap_delete_folder ($$) {
+    my ($HANDLE, $folder) = @_;
     my $seq = $ImapSeq++;
     my $failed = 0;
     im_notice("deleting folder $folder.\n");
-    my $resp = &send_command(\*IMAPd, "im$seq DELETE $folder", '');
+    my $resp = &send_command($HANDLE, "im$seq DELETE $folder", '');
     while ($resp !~ /^im$seq/) {
 	$failed = 1 if ($resp =~ /^\* NO/i);
-	$resp = &next_response(\*IMAPd);
+	$resp = &next_response($HANDLE);
     }
     return -1 if ($resp !~ /^im$seq OK/);
 #   return -1 if ($failed);
     return 0;
 }
 
-sub imap_rename_folder ($$) {
-    my ($old, $new) = @_;
+sub imap_rename_folder ($$$) {
+    my ($HANDLE, $old, $new) = @_;
     my $seq = $ImapSeq++;
     my $failed = 0;
     im_notice("rename folder from $old to $new.\n");
-    my $resp = &send_command(\*IMAPd, "im$seq RENAME $old $new", '');
+    my $resp = &send_command($HANDLE, "im$seq RENAME $old $new", '');
     while ($resp !~ /^im$seq/) {
 	$failed = 1 if ($resp =~ /^\* NO/i);
-	$resp = &next_response(\*IMAPd);
+	$resp = &next_response($HANDLE);
     }
     return -1 if ($resp !~ /^im$seq OK/);
 #   return -1 if ($failed);
     return 0;
 }
 
-sub imap_copy ($$$) {
-    my ($srcmsg, $dstfolder, $moveflag) = @_;
+sub imap_copy ($$$$) {
+    my ($HANDLE, $srcmsg, $dstfolder, $moveflag) = @_;
     im_notice("copying message $srcmsg to $dstfolder.\n");
-    my $resp = &imap_select($dstfolder, 0);
-    if ($resp < 0) {
-        $resp = &imap_create_folder($dstfolder);
-	if ($resp < 0) {
-	    im_err("can't create folder $dstfolder.\n");
-	    return -1;
-	}
-    }
+#    my $resp = &imap_select($HANDLE, $dstfolder, 0);
+#    if ($resp < 0) {
+#        $resp = &imap_create_folder($HANDLE, $dstfolder);
+#	if ($resp < 0) {
+#	    im_err("can't create folder $dstfolder.\n");
+#	    return -1;
+#	}
+#    }
     my $seq = $ImapSeq++;
     my $failed = 0;
-    $resp = &send_command(\*IMAPd, "im$seq UID COPY $srcmsg $dstfolder", '');
+    my $resp = &send_command($HANDLE,
+			     "im$seq UID COPY $srcmsg $dstfolder", '');
     while ($resp !~ /^im$seq/) {
 	$failed = 1 if ($resp =~ /^\* NO/i);
-	$resp = &next_response(\*IMAPd);
+	$resp = &next_response($HANDLE);
     }
     return -1 if ($resp !~ /^im$seq OK/);
 #   return -1 if ($failed);
     if ($moveflag) {
-	$resp = &imap_delete($srcmsg);
+	$resp = &imap_delete($HANDLE, $srcmsg);
     }
     return -1 if ($resp < 0);
     return 0;
 }
 
-sub imap_put ($$) {
-    my ($folder, $Msg) = @_;
+sub imap_put ($$$) {
+    my ($HANDLE, $folder, $Msg) = @_;
     my $seq = $ImapSeq++;
     my $failed = 0;
     im_notice("appending a new message to $folder.\n");
@@ -490,36 +496,36 @@
 	s/\r?\n?$/\r\n/;
 	$size += length($_);
     }
-    my $resp = &send_command(\*IMAPd,
+    my $resp = &send_command($HANDLE,
       "im$seq APPEND $folder (\\Seen) {$size}", '');
     if ($resp =~ /^\+/) {	# + Ready for argument
 	foreach (@$Msg) {
-	    send_data(\*IMAPd, $_, '');
+	    send_data($HANDLE, $_, '');
 	}
-	send_data(\*IMAPd, '', '');
+	send_data($HANDLE, '', '');
     }
     while ($resp !~ /^im$seq/) {
 	$failed = 1 if ($resp =~ /^\* NO/i);
-	$resp = &next_response(\*IMAPd);
+	$resp = &next_response($HANDLE);
     }
     $failed = 1 if ($resp !~ /^im$seq OK/);
     # synchronize
     $seq = $ImapSeq++;
-    $resp = &send_command(\*IMAPd, "im$seq NOOP", '');
+    $resp = &send_command($HANDLE, "im$seq NOOP", '');
     while ($resp !~ /^im$seq/) {
 	$failed = 1 if ($resp =~ /^\* NO/i);
-	$resp = &next_response(\*IMAPd);
+	$resp = &next_response($HANDLE);
     }
     $failed = 1 if ($resp !~ /^im$seq OK/);
 #   return -1 if ($failed);
     return 0;
 }
 
-# imap_process(how, host, src, dst)
-sub imap_process ($$$$) {
-    my ($how, $host, $src, $dst) = @_;
+# imap_process(handle, how, host, src, dst)
+sub imap_process ($$$$$) {
+    my ($HANDLE, $how, $host, $src, $dst) = @_;
     my ($msgs);
-    return -1 if (($msgs = &imap_select($src, 1)) < 0);
+    return -1 if (($msgs = &imap_select($HANDLE, $src, 1)) < 0);
     if ($how eq 'check') {
 	if ($msgs > 0) {
 	    im_msg("$msgs message(s) at $host.\n");
@@ -528,11 +534,11 @@
 	}
     } elsif ($how eq 'from') {
 	if ($msgs > 0) {
-	    my @alluids = &imap_all_uids();
+	    my @alluids = &imap_all_uids($HANDLE);
 	    return -1 if ($alluids[0] < 0);
 	    my $i;
 	    foreach $i (@alluids) {
-		return -1 if (&imap_from($i) < 0);
+		return -1 if (&imap_from($HANDLE, $i) < 0);
 	    }
 	    im_info("$msgs message(s) at $host.\n");
 	} else {
@@ -541,16 +547,16 @@
     } elsif ($how eq 'get') {
 	if ($msgs > 0) {
 	    im_info("Getting new messages from $host into $dst....\n");
-	    my @alluids = &imap_all_uids();
+	    my @alluids = &imap_all_uids($HANDLE);
 	    return -1 if ($alluids[0] < 0);
 	    my $i;
 	    foreach $i (@alluids) {
-		my ($rc, $message) = &imap_get($i);
+		my ($rc, $message) = &imap_get($HANDLE, $i);
 		return -1 if ($rc < 0);
 		return -1 if (&store_message($message, $dst) < 0);
 		&exec_getsbrfile($dst);
 		unless ($main::opt_keep) {
-		    return -1 if (&imap_delete($i) < 0);
+		    return -1 if (&imap_delete($HANDLE, $i) < 0);
 		}
 	    }
 	    im_info("$msgs message(s).\n");
@@ -585,14 +591,15 @@
     }
 
     im_notice("accessing IMAP/$auth:$user\@$host for $how\n");
-    if (&imap_open($auth, $host, $user, $pass) == 0) {
+    my ($rc, $HANDLE) = &imap_open($auth, $host, $user, $pass);
+    if ($rc == 0) {
 	&savepass('imap', $auth, $host, $user, $pass)
 	    if ($pass ne '' && $interact && &usepwagent());
-	my $msgs = &imap_process($how, $host, $folder, $dst);
+	my $msgs = &imap_process($HANDLE, $how, $host, $folder, $dst);
 	if ($msgs < 0) {
 	    im_warn("IMAP processing error.\n");
 	}
-	&imap_close();
+	&imap_close($HANDLE);
 	return $msgs;
     } else {
 	im_err("IMAP connection was not established.\n");
@@ -649,79 +656,11 @@
     return ($folder, $auth, $user, $host);
 }
 
-############################################
-##
-## For imls
-##
-
-sub imap_scan_folder ($@) {
-    my ($folder, @ranges) = @_;
-    my ($uid, $size, $len);
-
-    my $msgset = &imap_range2set(@ranges);
-    return  0 if !$msgset;
-    return -1 if ($msgset < 0);
-    my $count = 0;
-    my $seq = $ImapSeq++;
-    my $resp = &send_command(\*IMAPd,
-	"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) = ($2, $3, $4);
-	my @hdr;
-	alarm(20) unless win95p();
-	$! = 0;
-	while (<IMAPd>) {
-	    unless (win95p()) {
-		alarm(0);
-		if ($!) {   # may be channel truoble
-		    im_warn("lost connection for FETCH(scan).\n");
-		    return -1;
-		}
-	    }
-	    $len -= length;
-	    s/\r?\n$/\n/;
-	    im_warn($_) if (&debug('imap'));
-	    push(@hdr, $_);
-	    last if ($len <= 0);
-	}
-	alarm(0) unless win95p();
-	$resp = &next_response(\*IMAPd);
-	if (!$uid) {
-	    return -1 if ($resp !~ /^ UID (\d+)\)/);
-	    $uid = $1;
-	} else {
-	    return -1 if ($resp !~ /^\)/);
-	}
-
-	my %Head;
-	&store_header(\%Head, join('', @hdr));
-#	$Head{'bytes:'} = $size;
-	$Head{'kbytes:'} = int(($size + 1023) / 1024);
-	$Head{'number'} = $uid;
-	$Head{'folder'} = "\%$folder";
-	parse_header(\%Head);
-
-	if ($main::opt_thread) {
-	    &make_thread(%Head);
-	} else {
-	    &disp_msg(\%Head);
-	    $count++;
-	}
-	$resp = &next_response(\*IMAPd);
-    }
-    if ($resp !~ /^im$seq OK/) {
-	im_warn("UID FETCH command failed.\n");
-	return -1;
-    }
-    return $count;
-}
-
-sub imap_range2set (@) {
-    my @ranges = @_;
+sub imap_range2set ($@) {
+    my ($HANDLE, @ranges) = @_;
     my (@uids, $fromuid, $dir);
 
-    my @alluids = &imap_all_uids();
+    my @alluids = &imap_all_uids($HANDLE);
     return -1 if ($alluids[0] < 0);
     my ($min, $max) = ($alluids[0], $alluids[$#alluids]);
 
@@ -762,17 +701,70 @@
     return join(',', grep($_, @ranges));
 }
 
-sub imap_all_uids () {
+sub imap_range2msgs ($@) {
+    my ($HANDLE, @ranges) = @_;
+    my ($seq, $set, $resp, @uids);
+
+    $set = &imap_range2set($HANDLE, @ranges);
+    $seq = $ImapSeq++;
+    $resp = &send_command($HANDLE, "im$seq UID SEARCH UID $set", '');
+    if ($resp =~ /^\* SEARCH (\d+( +\d+)*)/i) {
+	@uids = split(' ', $1);
+    } else {
+	im_warn("UID SEARCH command failed.\n");
+	return (-1);
+    }
+    $resp = &next_response($HANDLE);
+    return (-1) if ($resp !~ /^im$seq OK/);
+    return @uids;
+}
+
+sub imap_folder_regname ($) {
+    my $folder = shift;		# %...
+    my ($auth, $user, $host);
+
+    if ($folder !~ /[:\@]/) {
+	# Use ImapAccount spec, unless user or host is specified.
+	(my $dummy, $auth, $user, $host) = imap_spec('');
+    } else {
+	($folder, $auth, $user, $host) = imap_spec($folder);
+	$folder =~ s/^/%/;
+    }
+    return "$folder:$user/$auth\@$host"; # may be appended '/port'
+}
+
+sub imap_folder_name ($) {
+    my $folder = shift;
+
+    if ($folder =~ /^%([^:\@]+)/) {
+	return $1;		# folder without '%'
+    }
+    return '';
+}
+
+sub imap_folder_acct ($) {
+    my $folder = shift;
+
+    $folder = imap_folder_regname($folder);
+    if ($folder =~ /^%([^:]+):([^\/]+)\/([^\@]+)\@([^\/]+).*$/) {
+	return "$2\@$4";	# user at example.com
+    }
+    return '';
+}
+
+sub imap_all_uids ($) {
+    my ($HANDLE) = @_;
     my ($seq, $resp, @uids);
 
     $seq = $ImapSeq++;
-    $resp = &send_command(\*IMAPd, "im$seq UID SEARCH 1:*", '');
+    $resp = &send_command($HANDLE, "im$seq UID SEARCH 1:*", '');
     if ($resp =~ /^\* SEARCH (\d+( +\d+)*)/i) {
 	@uids = split(' ', $1);
     } else {
 	im_warn("UID SEARCH command failed.\n");
+	return (-1);
     }
-    $resp = &next_response(\*IMAPd);
+    $resp = &next_response($HANDLE);
     return (-1) if ($resp !~ /^im$seq OK/);
     return @uids;
 }
@@ -784,6 +776,74 @@
     return $min if $num =~ /^first$/;
     return $max if $num =~ /^last$/;
     return '';
+}
+
+############################################
+##
+## For imls
+##
+
+sub imap_scan_folder ($$@) {
+    my ($HANDLE, $folder, @ranges) = @_;
+    my ($uid, $size, $len);
+
+    my $msgset = &imap_range2set($HANDLE, @ranges);
+    return  0 if !$msgset;
+    return -1 if ($msgset < 0);
+    my $count = 0;
+    my $seq = $ImapSeq++;
+    my $resp = &send_command($HANDLE,
+	"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) = ($2, $3, $4);
+	my @hdr;
+	alarm(20) unless win95p();
+	$! = 0;
+	while (<$HANDLE>) {
+	    unless (win95p()) {
+		alarm(0);
+		if ($!) {   # may be channel truoble
+		    im_warn("lost connection for FETCH(scan).\n");
+		    return -1;
+		}
+	    }
+	    $len -= length;
+	    s/\r?\n$/\n/;
+	    im_warn($_) if (&debug('imap'));
+	    push(@hdr, $_);
+	    last if ($len <= 0);
+	}
+	alarm(0) unless win95p();
+	$resp = &next_response($HANDLE);
+	if (!$uid) {
+	    return -1 if ($resp !~ /^ UID (\d+)\)/);
+	    $uid = $1;
+	} else {
+	    return -1 if ($resp !~ /^\)/);
+	}
+
+	my %Head;
+	&store_header(\%Head, join('', @hdr));
+#	$Head{'bytes:'} = $size;
+	$Head{'kbytes:'} = int(($size + 1023) / 1024);
+	$Head{'number'} = $uid;
+	$Head{'folder'} = "\%$folder";
+	parse_header(\%Head);
+
+	if ($main::opt_thread) {
+	    &make_thread(%Head);
+	} else {
+	    &disp_msg(\%Head);
+	    $count++;
+	}
+	$resp = &next_response($HANDLE);
+    }
+    if ($resp !~ /^im$seq OK/) {
+	im_warn("UID FETCH command failed.\n");
+	return -1;
+    }
+    return $count;
 }
 
 1;
diff -aruN im-76-/imcat.in im-76/imcat.in
--- im-76-/imcat.in	Wed Oct 22 13:27:21 1997
+++ im-76/imcat.in	Fri Nov 28 15:12:30 1997
@@ -156,8 +156,16 @@
     # IMAP folder (%folder[:[user[/auth]]@server])
     require IM::Imap && import IM::Imap;
     require IM::GetPass && import IM::GetPass;
-
-    my ($folder, $auth, $user, $host) = &imap_spec($1);
+    my ($folder, $auth, $user, $host);
+    
+    $folder = $1;
+    if ($folder !~ /[:\@]/) {
+	# Use ImapAccount spec, unless user or host is specified.
+	(my $dummy, $auth, $user, $host) = imap_spec('');
+	$folder =~ s/^%//;
+    } else {
+	($folder, $auth, $user, $host) = imap_spec($folder);
+    }
 
     my $pass = '';
     my $agtfound = 0;
@@ -176,7 +184,8 @@
 
     im_warn("accessing IMAP/$auth:$user\@$host\n") if (&verbose);
 
-    if (&imap_open($auth, $host, $user, $pass) < 0) {
+    my ($rc, $HANDLE) = &imap_open($auth, $host, $user, $pass);
+    if ($rc < 0) {
 	im_warn("IMAP connection was not established.\n")
 	  if (&debug('imap') || &verbose);
 	&savepass('imap', $auth, $host, $user, '')
@@ -185,17 +194,17 @@
     }
     &savepass('imap', $auth, $host, $user, $pass)
 	if ($interact && $pass ne '' && &usepwagent());
-    my $msgs = &imap_select($folder, 1);
+    my $msgs = &imap_select($HANDLE, $folder, 1);
     if ($msgs < 0) {
-	&imap_close;
-	im_warn("can't access to $folder\n");
+	&imap_close($HANDLE);
+	im_die("can't access to $folder\n");
     } else {
-	my ($rc, $message) = &imap_get($msg);
-	&imap_close;
+	my ($rc, $message) = &imap_get($HANDLE, $msg);
+	&imap_close($HANDLE);
 	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");
+	    im_die("message $msg not found in \%$folder\n");
 	}
 	foreach (@$message) {
 	    print;
diff -aruN im-76-/imls.in im-76/imls.in
--- im-76-/imls.in	Wed Oct 22 13:27:21 1997
+++ im-76/imls.in	Fri Nov 28 15:12:30 1997
@@ -451,9 +451,10 @@
 
 sub imap_messages ($@) {
     my ($folder, @ranges) = @_;
-    my ($host, $user, $auth);
+    my ($auth, $user, $host);
 
     if ($folder !~ /[:\@]/) {
+	# Use ImapAccount spec, unless user or host is specified.
 	(my $dummy, $auth, $user, $host) = imap_spec('');
 	$folder =~ s/^%//;
     } else {
@@ -477,7 +478,8 @@
 
 #   im_warn("accessing IMAP/$auth:$user\@$host\n") if (&verbose);
 
-    if (&imap_open($auth, $host, $user, $pass) < 0) {
+    my ($rc, $HANDLE) = &imap_open($auth, $host, $user, $pass);
+    if ($rc < 0) {
 #	im_warn("IMAP connection was not established.\n")
 #	  if (&debug("imap") || &verbose);
 	&savepass('imap', $auth, $host, $user, '')
@@ -487,21 +489,21 @@
     }
     &savepass('imap', $auth, $host, $user, $pass)
 	if ($interact && $pass ne '' && &usepwagent());
-    my $exists = &imap_select($folder, 1);
+    my $exists = &imap_select($HANDLE, $folder, 1);
     if ($exists < 0) {
-	&imap_close;
+	&imap_close($HANDLE);
 	im_warn("can't select $folder\@$host.\n");
 	$scan_count = -1;
 	return -1;
     }
     if ($exists > 0) {
-	if (($scan_count = &imap_scan_folder($folder, @ranges)) < 0) {
-	    &imap_close;
+	if (($scan_count = &imap_scan_folder($HANDLE, $folder, @ranges)) < 0) {
+	    &imap_close($HANDLE);
 	    im_warn("IMAP folder scanning error.\n");
 	    return -1;
 	}
     }
-    &imap_close;
+    &imap_close($HANDLE);
     return 0;
 }
 
diff -aruN im-76-/immv.in im-76/immv.in
--- im-76-/immv.in	Tue Sep  9 14:31:51 1997
+++ im-76/immv.in	Fri Nov 28 15:12:30 1997
@@ -25,6 +25,9 @@
 use IM::Config;
 use IM::Folder;
 use IM::File;
+use IM::MsgStore;
+use IM::Imap;
+use IM::GetPass;
 use integer;
 use strict;
 use vars qw($Prog $EXPLANATION @OptConfig
@@ -37,6 +40,7 @@
 ##
 
 my %NewMsgCache = ();
+my %ImapHandleCache = ();
 
 $EXPLANATION = "
 $Prog :: Internet Message Move
@@ -88,14 +92,65 @@
     my ($src, $dsts, $msgs) = @_;
     my @msg_paths;
 
-    chk_folder_existance($src, @{$dsts});   # not return in case false.
-    chk_msg_existance($src, @{$msgs});      # not return in case false.
+    chk_folder_existance($src, @{$dsts}); # ignore IMAP folders
+    open_imap_folders(0, $src);
+    open_imap_folders(1, @{$dsts});
+
+    if ($src !~ /^%/) {
+	chk_msg_existance($src, @{$msgs});
+    } else {
+	my ($HANDLE, $srcacct, $srcset);
+	my ($getbox, $link) = ('+inbox', 0);
+	my $link_1st;
+
+	$srcacct = imap_folder_acct($src);
+	$HANDLE = $ImapHandleCache{$srcacct};
+	if (imap_select($HANDLE, imap_folder_name($src), 1) < 0) {
+	    im_warn("can't select $src source folder.\n");
+	    close_imap_folders();
+	    exit($EXIT_ERROR);
+	}
+	$srcset = imap_range2set($HANDLE, @{$msgs});
 
-    @msg_paths = impath($src, @{$msgs});
+	for (my $i = 0; $i < @{$dsts}; $i++) {
+	    if (imap_folder_acct(${$dsts}[$i]) eq $srcacct) {
+		my $dst = splice(@{$dsts}, $i, 1); $i--;
+		if (imap_copy($HANDLE,
+			      $srcset,
+			      imap_folder_name($dst), 0) < 0) {
+		    im_warn("can't copy to $dst folder.\n");
+		    close_imap_folders();
+		    exit($EXIT_ERROR);
+		}
+	    } elsif (!$link && ${$dsts}[$i] =~ /^\+/) {
+		($getbox, $link) = (splice(@{$dsts}, $i, 1), 1); $i--;
+		($link_1st) = (impath($getbox, 'new') =~ m|([^/]+)$|);
+		get_imap_messages($HANDLE, $getbox, @{$msgs});
+	    }
+	}
+	unless (@{$dsts}) {
+	    imap_delete($HANDLE, $srcset) unless ($opt_link);
+	    close_imap_folders();
+	    return 0;
+	}
+
+	unless ($link) {
+	    ($link_1st) = (impath($getbox, 'new') =~ m|([^/]+)$|);
+	    get_imap_messages($HANDLE, $getbox, @{$msgs});
+	}
+	imap_delete($HANDLE, $srcset) unless ($opt_link);
+
+	$src = $getbox;
+	$opt_link = $link;
+	$msgs = ["$link_1st-last"];
+    }
 
+    @msg_paths = impath($src, @{$msgs});
     foreach (@msg_paths){
 	refile_one($_, $dsts);
     }
+    close_imap_folders();
+    return 0;
 }
 
 sub refile_one ($$) {
@@ -103,25 +158,36 @@
     my ($dst_path, $link_it);
 
     foreach (@{$dsts}){
-
-	if (defined $NewMsgCache{$_}){
-	    $NewMsgCache{$_} =~ s|([^/]+)$|$1+1|e; # increment cache
-	    $dst_path = $NewMsgCache{$_};
+	unless (/^%/) {
+	    if ($NewMsgCache{$_}){
+		$NewMsgCache{$_} =~ s|([^/]+)$|$1+1|e; # increment cache
+		$dst_path = $NewMsgCache{$_};
+	    } else {
+		$dst_path = $NewMsgCache{$_}
+		= impath($_, 'new');
+	    }
+	    if ($opt_link){
+		im_link($src_path, $dst_path) || die $@;      # XXX
+	    } elsif ($link_it){
+		im_link($link_it, $dst_path) || die $@;       # XXX
+	    } else {
+		im_rename($src_path, $dst_path) || die $@;    # XXX
+		$link_it = $dst_path;
+	    }
+	    touch_folder($dst_path) unless ($opt_noharm);
 	} else {
-	    $dst_path = $NewMsgCache{$_}
-	    = impath($_, 'new');
-	}
-	if ($opt_link){
-	    im_link($src_path, $dst_path) || die $@;      # XXX
-	} elsif ($link_it){
-	    im_link($link_it, $dst_path) || die $@;       # XXX
-	} else {
-	    im_rename($src_path, $dst_path) || die $@;    # XXX
-	}
-	if (! $link_it){
-	    $link_it = $dst_path;
+	    my $HANDLE = $ImapHandleCache{imap_folder_acct($_)};
+	    my $idst = imap_folder_name($_);
+
+	    if ($link_it){
+		put_imap_message($HANDLE, $idst, $link_it);
+	    } else {
+		put_imap_message($HANDLE, $idst, $src_path);
+	    }
 	}
-	touch_folder($dst_path) unless $opt_noharm;
+    }
+    if (!$opt_link && !$link_it) {
+	im_unlink($src_path);
     }
 }
 
@@ -135,6 +201,7 @@
     im_debug("chk_folder_existance: folder: @folders\n") if (&debug('all'));
 
     foreach (@folders){
+	next if /^%/;		# skip IMAP folders
 	$path = impath($_);
 
 	im_die "no folder $_. (Nothing was refiled.)\n"
@@ -178,6 +245,115 @@
 	$hash{$_} = $_;
     }
     return keys(%hash);
+}
+
+##
+## IMAP subroutines
+##
+
+sub get_imap_messages ($$@) {
+    my ($HANDLE, $dst, @ranges) = @_;
+    my @msgs = imap_range2msgs($HANDLE, @ranges);
+
+    if ($msgs[0] < 0) {
+	im_warn("can't find source message(s).\n");
+	close_imap_folders();
+	exit($EXIT_ERROR);
+    }
+    foreach (@msgs) {
+	my ($rc, $msgref) = imap_get($HANDLE, $_);
+	if ($rc < 0) {
+	    im_warn("can't get msg $_ from source folder.\n");
+	    close_imap_folders();
+	    exit($EXIT_ERROR);
+	}
+	local $main::opt_noscan = 1; # for quiet store_message
+	if (store_message($msgref, $dst) < 0) {
+	    im_warn("can't store msg $_ to $dst folder.\n");
+	    close_imap_folders();
+	    exit($EXIT_ERROR);
+	}
+    }
+}
+
+sub put_imap_message ($$$) {
+    my ($HANDLE, $dst, $src_path) = @_;
+    my @Message;
+    local (*SRC);
+
+    unless (open(SRC, "<$src_path")) {
+	im_warn("can't open local message $src_path.\n");
+	close_imap_folders();
+	exit($EXIT_ERROR);
+    }
+    local $_;
+    while (<SRC>) {
+	push(@Message, $_);
+    }
+    if (imap_put($HANDLE, $dst, \@Message) < 0) {
+	im_warn("can't store msg $src_path to $dst folder.\n");
+	close(SRC);
+	close_imap_folders();
+	exit($EXIT_ERROR);
+    }
+    close(SRC);
+}
+
+sub open_imap_folders ($@) {
+    my ($create, @folders) = @_;
+
+    foreach (@folders) {
+	if (/^%/) {
+	    my $acct = imap_folder_acct($_);
+	    my $ifld = imap_folder_name($_);
+	    my ($rc, $HANDLE);
+
+	    unless ($HANDLE = $ImapHandleCache{$acct}) {
+		my ($pass, $agtfound, $interact) = ('', 0, 0);
+		my ($dummy, $auth, $user, $host)
+		    = imap_spec(imap_folder_regname($_));
+
+		if (usepwagent()) {
+		    $pass = loadpass('imap', $auth, $host, $user);
+		    $agtfound = 1 if ($pass ne '');
+		}
+		if ($pass eq '' && usepwfiles()) {
+		    $pass = findpass('imap', $auth, $host, $user);
+		}
+		if ($pass eq '') {
+		    $pass = getpass("Password for $acct: ");
+		    $interact = 1;
+		}
+
+		($rc, $HANDLE) = imap_open($auth, $host, $user, $pass);
+		if ($rc < 0) {
+		    im_warn("can't open IMAP connection to $host.\n");
+		    savepass('imap', $auth, $host, $user, '')
+			if ($agtfound && usepwagent());
+		    close_imap_folders();
+		    exit($EXIT_ERROR);
+		}
+		savepass('imap', $auth, $host, $user, $pass)
+		    if ($interact && $pass ne '' && usepwagent());
+		$ImapHandleCache{$acct} = $HANDLE;
+	    }
+
+	    if ((imap_select($HANDLE, $ifld, 1) < 0) && $create) {
+		if (imap_create_folder($HANDLE, $ifld) < 0) {
+		    im_warn("can't create $_ folder.\n");
+		    close_imap_folders();
+		    exit($EXIT_ERROR);
+		}
+	    }
+	}
+    }
+}
+
+sub close_imap_folders () {
+    foreach (keys(%ImapHandleCache)) {
+	imap_close($ImapHandleCache{$_});
+    }
+    %ImapHandleCache = ();
 }
 
 ### Local Variables:
diff -aruN im-76-/impath.in im-76/impath.in
--- im-76-/impath.in	Tue Sep  9 14:31:36 1997
+++ im-76/impath.in	Fri Nov 28 15:12:30 1997
@@ -24,6 +24,7 @@
 
 use IM::Config;
 use IM::Folder;
+use IM::Imap;
 use integer;
 use strict;
 use vars qw($Prog $EXPLANATION @OptConfig
@@ -86,14 +87,18 @@
 my @msgs;
 
 foreach (@ARGV) {
-    if (/^[+=]/) {
+    if (/^[+=%]/) {
 	$folder = $_;
     } else {
 	push(@msgs, $_);
     }
 }
 
-impath($folder, @msgs);
+if ($folder =~ /^%/) {
+    print imap_folder_regname($folder), "\n";
+} else {
+    impath($folder, @msgs);
+}
 
 exit $EXIT_SUCCESS;
 
diff -aruN im-76-/imrm.in im-76/imrm.in
--- im-76-/imrm.in	Tue Sep  9 14:30:54 1997
+++ im-76/imrm.in	Fri Nov 28 15:12:30 1997
@@ -77,26 +77,88 @@
 
 sub imrm ($@) {
     my ($folder, @msgs) = @_;
-    my @paths = get_message_paths($folder, @msgs);
-    my $i = 0;
+    my (@paths, $set, $HANDLE);
 
-    if (scalar(@paths) == 0) {
-	im_warn("no msgs in $folder\n");
-	return;
+    if ($folder !~ /^%/) {
+	@paths = get_message_paths($folder, @msgs);
+	if (scalar(@paths) == 0) {
+	    im_warn("no msgs in $folder\n");
+	    return;
+	}
+    } else {
+	# IMAP folder (%folder[:[user[/auth]]@server])
+	require IM::Imap && import IM::Imap;
+	require IM::GetPass && import IM::GetPass;
+	my ($ifld, $auth, $user, $host);
+
+	$ifld = $folder;
+	if ($ifld !~ /[:\@]/) {
+	    # Use ImapAccount spec, unless user or host is specified.
+	    (my $dummy, $auth, $user, $host) = imap_spec('');
+	    $ifld =~ s/^%//;
+	} else {
+	    ($ifld, $auth, $user, $host) = imap_spec($ifld);
+	}
+
+	my $pass = '';
+	my $agtfound = 0;
+	my $interact = 0;
+	if (&usepwagent()) {
+	    $pass = &loadpass('imap', $auth, $host, $user);
+	    $agtfound = 1 if ($pass ne '');
+	}
+	if ($pass eq '' && &usepwfiles()) {
+	    $pass = &findpass('imap', $auth, $host, $user);
+	}
+	if ($pass eq '') {
+	    $pass = &getpass('Password: ');
+	    $interact = 1;
+	}
+
+	im_warn("accessing IMAP/$auth:$user\@$host\n") if (&verbose);
+
+	(my $rc, $HANDLE) = imap_open($auth, $host, $user, $pass);
+	if ($rc < 0) {
+	    im_warn("IMAP connection was not established.\n")
+		if (&debug('imap') || &verbose);
+	    &savepass('imap', $auth, $host, $user, '')
+		if ($agtfound && &usepwagent());
+	    exit $EXIT_ERROR;
+	}
+	&savepass('imap', $auth, $host, $user, $pass)
+	    if ($interact && $pass ne '' && &usepwagent());
+	my $exists = imap_select($HANDLE, $ifld, 1);
+	if ($exists < 0) {
+	    imap_close($HANDLE);
+	    im_die("can't access to $folder\n");
+	} elsif ($exists == 0) {
+	    imap_close($HANDLE);
+	    im_warn("no msgs in $folder\n");
+	    return;
+	}
+	$set = imap_range2set($HANDLE, @msgs);
     }
 
     print "unlinking msgs in $folder ... " unless ($opt_noharm || $opt_quiet);
     flush('STDOUT') unless $opt_noharm;
 
-    foreach (@paths) {
-	im_die("invalid message specification (unlinked $i message(s))\n")
-	    if (!-f $_);
-	im_unlink($_);
-	$i++;
+    if ($folder !~ /^%/) {
+	my $i = 0;
+	foreach (@paths) {
+	    im_die("invalid message specification (unlinked $i message(s))\n")
+		if (!-f $_);
+	    im_unlink($_);
+	    $i++;
+	}
+    } else {
+	imap_delete($HANDLE, $set);
+	imap_close($HANDLE);
     }
 
     print "done\n" unless ($opt_noharm || $opt_quiet);
-    touch_folder($folder) unless $opt_noharm;
+    if ($folder !~ /^%/) {
+	touch_folder($folder) unless $opt_noharm;
+    }
 }
 
 ### Local Variables:
-------------- next part --------------
diff -aruN mew-1.92.4-/mew-decode.el mew-1.92.4/mew-decode.el
--- mew-1.92.4-/mew-decode.el	Wed Nov 19 11:04:44 1997
+++ mew-1.92.4/mew-decode.el	Thu Nov 20 18:50:18 1997
@@ -293,7 +293,7 @@
   (if (and mew-temacs-p mew-mule-p) (setq mc-flag nil))
   (mew-erase-buffer)
   (cond
-   ((mew-folder-newsp fld)
+   ((or (mew-folder-newsp fld) (mew-folder-imapp fld))
     (mew-piolet mew-cs-noconv-eol mew-cs-noconv
       (call-process mew-prog-imcat nil t nil (format "--src=%s" fld) msg)))
    (t
diff -aruN mew-1.92.4-/mew-func.el mew-1.92.4/mew-func.el
--- mew-1.92.4-/mew-func.el	Sat Oct 25 14:23:13 1997
+++ mew-1.92.4/mew-func.el	Fri Nov 28 10:56:03 1997
@@ -292,6 +292,10 @@
   (string-match "^=" folder)
   )
 
+(defun mew-folder-imapp (folder)
+  (string-match "^%" folder)
+  )
+
 (defun mew-folder-to-dir (folder)
   (if (string-match "^[+=]" folder)
       (substring folder 1 nil)
@@ -307,12 +311,44 @@
       (setq dir (expand-file-name subdir mew-mail-path)))
      ((char-equal prefix-char ?=)
       (setq dir (expand-file-name subdir mew-news-path)))
-     )
+     ((char-equal prefix-char ?%)
+      (let ((rfold (mew-folder-impath folder)))
+	(string-match
+	 "^%\\([^:]+\\):\\([^/]+\\)/\\([^@]+\\)@\\([^/]+\\).*$" rfold)
+	(setq dir
+	      (expand-file-name
+	       (concat "@" (substring rfold (match-beginning 4) (match-end 4))
+		       "#" (substring rfold (match-beginning 2) (match-end 2))
+		       mew-path-separator
+		       (substring rfold (match-beginning 1) (match-end 1)))
+	       mew-mail-path))
+	)))
     (if message
 	(expand-file-name message dir)
       dir)
     ))
 
+(defun mew-folder-impath (folder)
+  "impath command outputs regularized folder-name for IMAP folders."
+  (save-excursion
+    (mew-set-buffer-tmp)
+    (call-process mew-prog-impath nil t nil folder)
+    (buffer-substring (point-min) (1- (point-max)))
+    ))
+
+(defun mew-folder-regularize (arg)
+  "Especially about IMAP folder(s), regularize it using mew-folder-impath."
+  (if (listp arg)
+      (let ((folders arg))
+	(while folders
+	  (if (mew-folder-imapp (car folders))
+	      (setcar folders (mew-folder-impath (car folders))))
+	  (setq folders (cdr folders)))
+	arg)
+    (if (mew-folder-imapp arg)
+	(mew-folder-impath arg)
+      arg)))
+
 (defun mew-folder-check (folder)
   "A function to see if FOLDER exists.
 Return t if exists or created. Otherwise, return nil."
@@ -325,7 +361,11 @@
 	    (message "%s is a file" folder)
 	    nil ;; exists but a file
 	    )
-	(if (not (mew-y-or-n-p "%s does not exist. Create it? " folder))
+	(if (if (mew-folder-imapp folder)
+		(not (y-or-n-p
+		      (format
+      "Maybe %s doesn't exist (cache-dir not found). Create it? " folder)))
+	      (not (mew-y-or-n-p "%s does not exist. Create it? " folder)))
 	    nil ;; not created
 	  (mew-make-directory absdir)
 	  (setq mew-folder-list (cons folder mew-folder-list))
diff -aruN mew-1.92.4-/mew-mark.el mew-1.92.4/mew-mark.el
--- mew-1.92.4-/mew-mark.el	Thu Nov  6 16:16:03 1997
+++ mew-1.92.4/mew-mark.el	Thu Nov 27 13:30:30 1997
@@ -491,7 +491,8 @@
   (condition-case nil
       (let* ((msgs (mew-summary-mark-collect mew-mark-refile beg end))
 	     (dels (mew-summary-mark-collect mew-mark-delete beg end))
-	     (src (buffer-name))
+	     (src (mew-folder-regularize (buffer-name)))
+	     (trash (mew-folder-regularize mew-trash-folder))
 	     refal folder folder-list tmp msg rm-it)
 	(if (not (mew-summary-exclusive-p))
 	    ()
@@ -510,7 +511,8 @@
 	      (setq msg (car msgs))
 	      (setq msgs (cdr msgs))
 	      (if (setq folder-list
-			(cdr (assoc msg mew-summary-buffer-refile)))
+			(mew-folder-regularize
+			 (cdr (assoc msg mew-summary-buffer-refile))))
 		  ;; first, remove current folder from folder-list
 		  (if (mew-folder-member src folder-list)
 		      (save-excursion
@@ -521,19 +523,11 @@
 			;; if folder-list still have folders, refile to the
 			;; folders using "-link" option
 			(if (> (length folder-list) 0)
-			    (apply (function call-process)
-				   mew-prog-immv nil nil nil
-				   (format "--src=%s" src)
-				   "--link"
-				   (append folder-list (list msg))
-				   ))
+			    (mew-summary-exec-immv src folder-list msg 'link))
 			) ;; end of save-excursion
 		    ;; if multi-refile, I must refile one by one. -- nom
 		    (if (nth 1 folder-list)
-			(apply (function call-process)
-			       mew-prog-immv nil nil nil
-			       (format "--src=%s" src)
-			       (append folder-list (list msg)))
+			(mew-summary-exec-immv src folder-list msg)
 		      ;; else (folder-list has only one folder)
 		      (setq folder (car folder-list))
 		      (if (setq tmp (assoc folder refal))
@@ -545,12 +539,8 @@
 	    ;; refile at once
 	    ;;
 	    (while refal
-	      (apply (function call-process)
-		     mew-prog-immv nil nil nil
-		     (format "--src=%s" src)
-		     (car (car refal))
-		     (cdr (car refal)))
-	      (setq refal (cdr refal))) ;; end of while
+	      (mew-summary-exec-immv src (car (car refal)) (cdr (car refal)))
+	      (setq refal (cdr refal)))
 	    (setq mew-summary-buffer-refile nil)
 	    ;;
 	    ;; delete at once
@@ -561,10 +551,11 @@
 	       ((equal mew-msg-rm-policy 'always)
 		(setq rm-it t))
 	       ((equal mew-msg-rm-policy 'trashonly)
-		(if (equal src mew-trash-folder)
+		(if (equal src trash)
 		    (setq rm-it t)))
 	       ((equal mew-msg-rm-policy 'uselist)
-		(if (mew-member-match src mew-msg-rm-folder-list)
+		(if (mew-member-match
+		     src (mew-folder-regularize mew-msg-rm-folder-list))
 		    (setq rm-it t)))
 	       )
 	      (if rm-it
@@ -573,7 +564,7 @@
 			 (format "--src=%s" src)
 			 "--quiet=on"
 			 dels)
-		(if (string-equal src mew-trash-folder)
+		(if (equal src trash)
 		    (let ((regex (concat mew-summary-message-regex
 					 (regexp-quote (char-to-string
 							mew-mark-delete)))))
@@ -582,12 +573,8 @@
 			(while (re-search-forward regex nil t)
 			  (mew-summary-undo-one))
 			))
-		  (apply (function call-process)
-			 mew-prog-immv nil nil nil
-			 (format "--src=%s" src)
-			 "--link=no"
-			 mew-trash-folder
-			 dels)))) ;; end of if (null dels)
+		  (mew-summary-exec-immv src mew-trash-folder dels)
+		  ))) ;; end of if (null dels)
 	    ;;
 	    ;; ending...
 	    ;;
@@ -615,6 +602,58 @@
      (message "Refiling and deleting ... imcompletely done")
      )) ;; end of condision-case
   )
+
+(defun mew-summary-exec-immv (src dsts msgs &optional link)
+  (or (listp dsts) (setq dsts (list dsts)))
+  (or (listp msgs) (setq msgs (list msgs)))
+  (if link
+      (dsts (cons "--link" dsts)))
+  (setq mew-summary-buffer-string nil)
+  (setq mew-summary-buffer-process
+	(apply (function start-process)
+	       mew-prog-immv nil
+	       mew-prog-immv
+	       (format "--src=%s" src)
+	       (append dsts msgs)))
+  (set-process-filter
+   mew-summary-buffer-process 'mew-summary-immv-filter)
+  (set-process-sentinel
+   mew-summary-buffer-process 'mew-summary-immv-sentinel)
+  ;; I'm in at the finish.
+  (while (eq (process-status mew-summary-buffer-process) 'run)
+    (accept-process-output mew-summary-buffer-process)))
+
+(defun mew-summary-immv-filter (process string)
+  (save-excursion
+    (setq mew-summary-buffer-string
+	  (concat mew-summary-buffer-string string))
+    (if (string-match "^Password for \\(.+\\):" mew-summary-buffer-string)
+	(let ((userhost (mew-match 1 mew-summary-buffer-string)))
+	  (setq mew-summary-buffer-string "")
+	  (process-send-string
+	   process
+	   (format "%s\n"
+		   (mew-read-passwd
+		    (format "Enter password (%s) : " userhost))))
+	  ))
+    ))
+
+(defun mew-summary-immv-sentinel (process event)
+  (save-excursion
+    (let ((prog (process-name process)))
+      (if (not mew-summary-buffer-string)
+	  ()
+	(cond
+	 ((string-match (format "^%s: \\([^\n]*\\)" prog)
+			mew-summary-buffer-string)
+	  (message "Refile error: %s"
+		   (mew-match 1 mew-summary-buffer-string)))
+	 ))
+      ;; If process was killed, we can't clear the sentinel.
+      ;;(set-process-sentinel mew-summary-buffer-process nil)
+      (setq mew-summary-buffer-process nil)
+      (setq mew-summary-buffer-string nil)
+      )))
 
 ;;;
 ;;; Clean up marks!
diff -aruN mew-1.92.4-/mew-scan.el mew-1.92.4/mew-scan.el
--- mew-1.92.4-/mew-scan.el	Sat Oct 25 14:27:03 1997
+++ mew-1.92.4/mew-scan.el	Thu Nov 20 19:44:49 1997
@@ -58,8 +58,8 @@
 	(setq mew-clean-up-buffers (cons folder mew-clean-up-buffers)))
     (if (or (interactive-p)
 	    (mew-folder-newsp folder)
+	    (mew-folder-imapp folder)
 	    (and mew-summary-cache-use
-		 (not (mew-folder-newsp folder))
 		 (mew-summary-folder-dir-newp)))
 	(let ((range (mew-input-range folder)))
 	  (or arg (goto-char (point-max)))
@@ -153,7 +153,8 @@
 	    (concat mew-summary-buffer-string string)) ;; nil can concat
       (cond
        ;; just for imls
-       ((string-match mew-prog-imget (process-name process))
+       ((or (string-match mew-prog-imget (process-name process))
+	    (string-match mew-prog-imls  (process-name process)))
 	(if (string-match "^Password" mew-summary-buffer-string)
 	    (progn
 	      (setq mew-summary-buffer-string "")
@@ -204,7 +205,10 @@
 	    (setq msg (concat (mew-match 1 mew-summary-buffer-string) 
 			      " message(s)")))
 	   (t
-	    (setq msg (format "Getting %s ... done" folder)))
+	    (if (mew-folder-imapp folder)
+		(setq msg (format "Getting %%%s ... done" folder))
+	      (setq msg (format "Getting %s ... done" folder)))
+	    )
 	   ))
 	 ((string-match mew-prog-imls prog)
 	  (cond
@@ -214,7 +218,11 @@
 	   ((string-match (format "^%s: ERROR: \\([^\n]*\\)" prog)
 			  mew-summary-buffer-string)
 	    (message "List error: %s" (mew-match 1 mew-summary-buffer-string)))
-	   (t (setq msg (format "Listing %s ... done" folder)))
+	   (t
+	    (if (mew-folder-imapp folder)
+		(setq msg (format "Listing %%%s ... done" folder))
+	      (setq msg (format "Listing %s ... done" folder)))
+	    )
 	   ))
 	 )
 	(if msg
diff -aruN mew-1.92.4-/mew-summary.el mew-1.92.4/mew-summary.el
--- mew-1.92.4-/mew-summary.el	Sat Oct 25 14:27:44 1997
+++ mew-1.92.4/mew-summary.el	Thu Nov 27 12:07:30 1997
@@ -508,13 +508,20 @@
   (let* ((folder (mew-input-folder mew-inbox-folder))
 	 (dir (mew-expand-folder folder))
 	 new-folder)
+    (if (and (mew-folder-imapp folder) (not (file-directory-p dir)))
+	(if (y-or-n-p
+	     (format
+	      "Cache directory for %s does not exist. Create it? " folder))
+	    (mew-make-directory dir)))
     (if (not (or (mew-folder-newsp folder) (file-directory-p dir)))
-        (message "No such folder %s" folder)
+	(message "No such folder %s" folder)
       (if (get-buffer folder)
 	  (switch-to-buffer folder)
 	(mew-summary-folder-create folder)
 	(setq new-folder t))
-      (if (and mew-summary-trace-directory (not (mew-folder-newsp folder)))
+      (if (and mew-summary-trace-directory
+	       (not (mew-folder-newsp folder))
+	       (not (mew-folder-imapp folder)))
 	  (cd dir))
       (mew-summary-ls t new-folder)
       )))
@@ -786,7 +793,9 @@
     (mew-current-set 'cache nil)
     (setq mew-decode-result nil)
     (setq mew-decode-syntax nil)
-    (if (not (or (file-exists-p file) (mew-folder-newsp fld)))
+    (if (not (or (file-exists-p file)
+		 (mew-folder-newsp fld)
+		 (mew-folder-imapp fld)))
 	(message "File does not exist.")
       (cond
        ((equal fld mew-draft-folder)
@@ -794,12 +803,18 @@
        ((and (not analysis)
 	     (not (mew-folder-newsp fld)) ;; xxx
 	     (or (not mew-analysis)
-		 (and (> (mew-file-size file) mew-file-max-size)
+		 (and (not (mew-folder-imapp fld))
+		      (> (mew-file-size file) mew-file-max-size)
 		      (null (mew-cache-hit (cons fld msg))))))
-	(insert-file-contents file)
+	(if (mew-folder-imapp fld)
+	    (mew-piolet mew-cs-autoconv mew-cs-noconv
+			(call-process mew-prog-imcat nil t nil
+				      (format "--src=%s" fld) msg))
+	  (insert-file-contents file))
 	(mew-header-arrange nodisplay)
 	(setq mew-message-citation 'header)
-	(if (> (mew-file-size file) mew-file-max-size)
+	(if (and (not (mew-folder-imapp fld))
+		 (> (mew-file-size file) mew-file-max-size))
 	    (message 
 	     (concat
 	      "Too large, MIME analysis was skipped. "


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