重複メール削除自動化No.40315
ちーとあー さん 11/04/06 12:49
 
こんにちは、いつもお世話になります。

重複メールの削除を自動化できるマクロなどありましたら、ご教示頂けると幸いです。

現在アカウントを2つ設定していますが、
アカウント1では、メールアドレスAとB宛に届いたメールを受信し、
アカウント2では、メールアドレスBに届いたメールを受信する
設定にしています。

アカウント1は、自己ドメインでGoogle Appsを利用しているために
メインアドレスAをfromアドレスとして送信するとメーリングリストで自分自身に配
信されません。そこでそのメーリングリストには配信先としてメールアドレスBも登
録しています。それによって自分がMLに送信したメールも自分に配信されるようにし
ています。

ただメールアドレスBは振り分けフォルダーが多いので、
アカウント1の中では最低限のフォルダーに留め、
アカウント2の中で、フルに振り分けフォルダーを設定しています。

こうした理由で、冒頭のような一見妙な設定をしています。
当然アカウント間で重複メールが生じますが、毎回「既読」にする
と「重複を削除する」の繰り返し作業が必要で、回避策を求めています。

どうぞよろしくお願い致します。




[ ]
RE:40315 重複メール削除自動化No.40318
秀まるお2 さん 11/04/06 17:54
 
 単純に「重複メールのチェック」をマクロで自動実行すればいいということで
したら、例えば「テストアカウント」の「テストフォルダ」の中に対してそれを
実行するならば、

    loaddll "tkinfo.dll";
    $account = dllfuncstr("CurrentAccount");
    $folder = dllfuncstr("CurrentFolder");
    #n = dllfunc("SelectFolder", "テストアカウント", "テストフォルダ");
    #n = dllfunc("CheckDuplication", "batch");
    #n = dllfunc("SelectFolder", $account, $folder);

 ってなマクロでいいんじゃないかと思います。

 重複メールのチェックをしたいフォルダが複数ある場合は、SelectFolderして
からCheckDuplicationするってことを、フォルダの数だけ並べて書いてやればい
いと思います。

 ということでどうでしょ?


[ ]
RE:40318 重複メール削除自動化No.40319
ちーとあー さん 11/04/07 12:56
 
ありがとうございます。

>例えば「テストアカウント」の「テストフォルダ」の中に対

テストアカウント以下のフォルダーは全て重複削除し、
テストアカウント2以下も同様に全てのフォルダー対象としたいのですが、それらを
一気にマクロで実行することは出来るでしょうか?

よろしくお願い致します。


[ ]
RE:40319 重複メール削除自動化No.40320
秀まるお2 さん 11/04/07 15:18
 
 アカウント配下全部ということであれば、CheckDuplication関数の第1パラ
メータに"under"を指定すればいいです。

 アカウントを選択して実行したらいいかと思います。

 例:

    loaddll "tkinfo.dll";
    $account = dllfuncstr("CurrentAccount");
    $folder = dllfuncstr("CurrentFolder");
    #n = dllfunc("SelectFolder", "テストアカウント", "");
    #n = dllfunc("CheckDuplication", "under");
    #n = dllfunc("SelectFolder", "テストアカウント2", "");
    #n = dllfunc("CheckDuplication", "under");
    #n = dllfunc("SelectFolder", $account, $folder);

 確認メッセージが出てしまうのですけとも、そこでは「すべてはい」を押して
やれば一応一気に行くと思います。

 ということでどうでしょ?

[ ]
RE:40320 重複メール削除自動化No.40321
秀まるお2 さん 11/04/07 15:41
 
 確認メッセージに自動で「はい」を押すようには出来ました。

 「すべてはい」を押すようにはちょっと出来ないのですけども。

 例:

    loaddll "tkinfo.dll";
    $account = dllfuncstr("CurrentAccount");
    $folder = dllfuncstr("CurrentFolder");
    #n = dllfunc("SelectFolder", "テストアカウント", "");
    #n = dllfunc("SetAutoPushTimerEver", hidemaruhandle(0), "" );
    #n = dllfunc("CheckDuplication", "under");
    #n = dllfunc("SelectFolder", "テストアカウント2", "");
    #n = dllfunc("CheckDuplication", "under");
    #n = dllfunc("SelectFolder", $account, $folder);
    #n = dllfunc("StopAutoPushTimer");

[ ]
RE:40321 重複メール削除自動化No.40332
ちーとあー さん 11/04/09 15:25
 
有り難うございました。
随分楽になりました。

お手数おかけしました。今後ともよろしくお願いいたします。


[ ]
RE:40332 重複メール削除自動化No.41590
hajimet さん 11/09/30 18:44
 
いつも便利に秀丸メールを活用させていただいております
本件に関連してもう少しわがままな事例ですが

アカウント1(多くのフォルダに振り分けされている)
      (アカウント2に来たメールをGmailに転送している)
アカウント2(すべて「受信」のフォルダに入っている)

という状況です。
アカウント2は、万が一のためのバックアップと位置づけています。
アカウント1は、Gmailで直接ゴミ箱行きのフィルタがかかったものや、
Gmailの判定でSPAM(迷惑)とされたモノは受信されていません。
普段は主にこちらでメール授受をしています。

さて、PCのハードウェアの余裕が限界に近づいてきたので、
アカウント2の内容を整理(つまり、削除)しようかと思ったのですが、
もしかしたら、アカウント1には存在しないが、重要なメールがアカウ
ント2に紛れているやもとおもい、思い立ったのが、重複メール削除の
自動化です。

すなわち、上述のような状況で、
(ゴミ箱を含む)アカウント1にあるメールは、
アカウント2からすべて削除したいのですが、
マクロで自動処理することは可能でしょうか。

あるいは、他の方法でアプローチするのでもかまいません。
何かご助言いただければ幸いです。

[ ]
RE:41590 重複メール削除自動化No.41591
Iranoan さん 11/09/30 21:58
 
 hajimetさん今日は、Iranoan です。
> (ゴミ箱を含む)アカウント1にあるメールは、
> アカウント2からすべて削除したいのですが、
> マクロで自動処理することは可能でしょうか。
 可能かどうか? と言う点にしては可能です。
 流れとしては、どちらかのアカウントを基準として
(1) Message-ID を取得
(2) もう一方のアカウントで、取得した ID で「Message-ID検索」を実行
    (実施には、SetFindPack() を使ったと、FindDownInclude() を使う)
(3) ヒットするメールがあれば削除
    (一つとは限らないので、FindDownInclude() が false となるまで繰り返し)
(4) 元のアカウントに移動
(5) 次のメールを選択
を最後のメールまで繰り返し、になると思います。

 問題は、
・非常に長い時間がかかる
・元のサーバの問題で、別のメールなのに、Message-ID が同じであったり、
  その逆に同じ内容で、別の Message-ID の場合がある
点です。後者については、ここのメールを本文だけでファイル保存するなどし
て、チェックサムを使う方法で回避できますが、必要になる時間、ファイル容
量共に増加します。

[ ]
RE:41591 重複メール削除自動化No.41592
hajimet さん 11/10/01 13:45
 
Iranoanさん
早速のご指摘、ありがとうございました
非常に、というのがどれ位の単位か、によりますが
2万件の程度のメールだと、1日くらいでおわりますかね。。

おそらく、削除される側が、1フォルダなので、
こちらを基準として、古いメールエントリから、順番に、
チェックしていくという手順が一番私には分かり易いです。

(1)削除される側のフォルダ(唯一)のメールリストから
   順にMessage-ID を取得
(2)普段使っているアカウント全体(ゴミ箱含む)を
   対象に「Message-ID検索」を実行
(3)検索結果がヒットであれば、(1)のエントリを削除
の繰り返し、でどうでしょう。
アカウントの移動とそれに伴うマクロの動作のあたりが
分かっていないので、もしかしたら、駄目かもですが。

[ ]
RE:41592 重複メール削除自動化No.41593
Iranoan さん 11/10/01 15:38
 
 hajimetさん今日は、Iranoan です。
> の繰り返し、でどうでしょう。
 おそらくこれでOKだと思います。

[ ]
RE:41593 重複メール削除自動化No.41616
秀まるお2 さん 11/10/03 16:34
 
 マクロ作ってみました。

 間違って動作すると大事なメールが無くなってしまうのでくれぐれも注意して
動作テストお願いします。

 安全のためにquestion文が入れてありますが、自動化するためにはその辺修正
が必要です。



    $account1 = "テストアカウント";
    $account2 = "テストアカウント2";
    loaddll "tkinfo.dll";

    #n = dllfunc("SelectFolder", $account1, "");

    #deletecount = 0;

    while(1) {
        $next = dllfuncstr("GetNextFolder", "", "");
        $nextfolderaccout = leftstr( $next, strstr( $next, "\\" ) );
        if( $nextfolderaccout != $account1 ) {
            break;
        }
        $nextfolder = midstr( $next, strstr( $next, "\\" ) + 1, );
        if( $nextfolder == "受信ログ"
         || $nextfolder == "送信ログ" ) {
            break;
        }
        #n = dllfunc("SelectFolder", $account1, $nextfolder);
        if( dllfunc("ViewArea") != 0 ) {
            #n = dllfunc("SetViewArea", 0);
        }
        if( dllfunc("IsThreadView") ) {
            #n = dllfunc("SetThreadView", 0);
        }
        #count = dllfunc("MailCount");
        #i = 0;
        while( #i < #count ) {
            #n = dllfunc("SetMailIndex", #i);
            $messageid = dllfuncstr("CurrentHeader", "Message-Id");
            if( leftstr($messageid, 1) == "<"
             && rightstr($messageid, 1) == ">" ) {
                $messageid = midstr( $messageid, 1, strlen($messageid) - 2 );
            }
            if( $messageid != "" ) {
                $messageid = dllfuncstr("YenEncode", $messageid);
                #n = dllfunc("SelectFolder", $account2, "");
                #n = dllfunc("SetFindPack", "(\"" + $messageid + "\", casese
nse, word, target=person), messageidtarget=messageid, inmail=2");
                #n = dllfunc("FindDownInclude");
                if( #n == 1 ) {
                    question( "このメールは" + $account1 + "に存在してます。
削除してもいいですか?" );
                    if( result == yes ) {
                        #n = dllfunc("Delete", 1);
                        #deletecount = #deletecount + 1;
                    } else {
                        message "マクロを中断します。";
                        endmacro;
                    }
                }
                #n = dllfunc("SelectFolder", $account1, $nextfolder);
            } else {
                //message "このメールにはmessage-id:ヘッダがありません。";
            }
            #i = #i + 1;
        }
    }
    message str(#deletecount) + " 通のメールを削除しました。";

[ ]
RE:41616 重複メール削除自動化No.41641
hajimet さん 11/10/11 01:46
 
マクロ作成大変ありがたく存じます。
Iranoanさんの最初のご提案のように、
なんどかアカウントを切り替えないと
当初の目的が達成できないことがわかりました。
その部分含め幾箇所か修正して使っています。
エントリの削除に時間がかかるようで、
削除が終わる前にマクロが進行してしまうと、
エントリナンバーに「ズレ」が生じて、
処理漏れが起こるの難点がありますので、
何度か繰り返し、マクロを実行する必要があります。
一部描画を抑制していますが、
これで、ある程度進捗がモニタできます。
#描画抑制しないと画面が散乱して、
 進捗が目視できなくなってしまいます。

反復処理終了の出口に、受信ログ、送信ログを使っているようですが、
表示を抑制していてもこれで上手く行くんでしょうか。
何となく、無限ループに嵌ったようになることもあるのですが、
それは、マクロのせいではないのかも知れませんし・・・・


    $account1 = "アカウント名1";//削除される方
    $account2 = "アカウント名2";//残される方
    loaddll "tkinfo.dll";

    #n = dllfunc("SelectFolder", $account1, "");

    #deletecount = 0;

    while(1) {
        $next = dllfuncstr("GetNextFolder", "", "");
        $nextfolderaccout = leftstr( $next, strstr( $next, "\\" ) );
        if( $nextfolderaccout != $account1 ) {
            break;
        }
        $nextfolder = midstr( $next, strstr( $next, "\\" ) + 1, );
        if( $nextfolder == "受信ログ"
         || $nextfolder == "送信ログ" ) {
            break;
        }
        #n = dllfunc("SelectFolder", $account1, $nextfolder);
        if( dllfunc("ViewArea") != 0 ) {
            #n = dllfunc("SetViewArea", 0);
        }
        if( dllfunc("IsThreadView") ) {
            #n = dllfunc("SetThreadView", 0);
        }
        #count = dllfunc("MailCount");
        #i = 0;
        while( #i < #count ) {
            #n = dllfunc("SetMailIndex", #i);
            #n = dllfunc("DisableDraw", 0);
            $messageid = dllfuncstr("CurrentHeader", "Message-Id");
            if( leftstr($messageid, 1) == "<"
             && rightstr($messageid, 1) == ">" ) {
                $messageid = midstr( $messageid, 1, strlen($messageid) - 2 );
            }
            if( $messageid != "" ) {
                $messageid = dllfuncstr("YenEncode", $messageid);
                #n = dllfunc("SelectFolder", $account2, "");
                #n = dllfunc("SetFindPack", "(\"" + $messageid + "\", casese
nse, word, target=person), messageidtarget=messageid, inmail=2");
                #n = dllfunc("FindDownInclude");
                if( #n == 1 ) {
                    #n = dllfunc("SelectFolder", $account1, "");
                    #n = dllfunc("SetFindPack", "(\"" + $messageid + "\", ca
sesense, word, target=person), messageidtarget=messageid, inmail=2");
                    #n = dllfunc("FindDownInclude");
                    if( #n == 1 ) {
                        #n = dllfunc( "Delete", 1 );
                       
                        #deletecount = #deletecount + 1;
                    } else {
                message "元のメールの位置への復帰に失敗しました";
                    }
                }
            #n = dllfunc("SelectFolder", $account1, $nextfolder);
            #n = dllfunc("EnableDraw");
            }
        #i = #i + 1;
        }
    }
    message str(#deletecount) + " 通のメールを削除しました。";

[ ]
RE:41641 重複メール削除自動化No.41646
秀まるお2 さん 11/10/11 15:31
 
 僕の作ったマクロだと、Message-Idが同じメールが複数あったとしても、1つ
しか見つけてくれないです。なので、マクロを複数回実行しないと削除されない
ということでしたら、つまりMessage-Idが同じメールが複数あるってことではな
いかと思います。

> 反復処理終了の出口に、受信ログ、送信ログを使っているようですが、
> 表示を抑制していてもこれで上手く行くんでしょうか。

 表示を抑制してても動作は同じになるはずです。

[ ]
RE:41646 重複メール削除自動化No.41652
hajimet さん 11/10/12 12:25
 
> 表示を抑制してても動作は同じになるはずです。
ありがとうございました。

> 僕の作ったマクロだと、Message-Idが同じメールが複数あったとしても、1つ
>しか見つけてくれないです。なので、マクロを複数回実行しないと削除されない
>ということでしたら、つまりMessage-Idが同じメールが複数あるってことではな
>いかと思います。
これはどうもそういうことではなくて、単純に
削除したら次のエントリがスルーされるということが
時折あるようです。
もしかして、
メールエントリを削除すると、
SetMailIndexで特定されるメールエントリがずれるので、
エントリを削除した場合には、
エントリナンバーをインクリメントせず、
もう一度ループを回す、
削除しなかった場合には、
エントリナンバーをインクリメントして、ループを回す、
という処理が必要ってことではないでしょうか。
#プログラミング素人の発想です。
 的外れの可能性高いです。寛恕願いたく。


[ ]
RE:41652 重複メール削除自動化No.41653
秀まるお2 さん 11/10/13 15:51
 
 マクロを見た限りでは、#i = #i + 1 でループしてるだけなので、メールを飛
ばして検索してしまうようなことは無いはずだと思います。

 削除した時だけ飛ばしてるようでしたら、とりあえず削除を実行した時に限っ
て#iの値を-1するとか…

                        #n = dllfunc( "Delete", 1 );

 の後ろに、

                        #i = #i - 1;

 を入れたらそうなると思います。

[ ]
RE:41653 重複メール削除自動化No.41665
hajimet さん 11/10/15 01:21
 
エントリ数が小さい方を基準にループ処理して、そちらを削除する方が
処理が早く済むので、削除する側のアカウントでループ処理するように
修正しました。
ので、やはり、メールエントリの番号がずれていくのが問題でした。
また、無限ループっぽい状態になるのも同じ原因でした。
(エントリ数が減っても、反復数が減らないので、最後がおかしくなる)
素人のマクロ改造ではこんなミスも生じます。削除した場合には、
                        #i = #i - 1;
                        #count = #count - 1;
という処理をかませて、削除による値の減少に対処しました。
これで、快適に、複数のアカウントをまたがったメールの、
重複メール削除の自動化ができました。
大変ありがとうございました。

どなたかの参考になるやもと思い、最終版以下に掲載します:

    $account1 = "アカウント1";//削除される方
    $account2 = "アカウント2";//残される方
    loaddll "tkinfo.dll";

    #n = dllfunc("SelectFolder", $account1, "");

    #deletecount = 0;

    while(1) {
        $next = dllfuncstr("GetNextFolder", "", "");
        $nextfolderaccout = leftstr( $next, strstr( $next, "\\" ) );
        if( $nextfolderaccout != $account1 ) {
            break;
        }
        $nextfolder = midstr( $next, strstr( $next, "\\" ) + 1, );
        if( $nextfolder == "受信ログ"
         || $nextfolder == "送信ログ" ) {
            break;
        }
        #n = dllfunc("SelectFolder", $account1, $nextfolder);
        if( dllfunc("ViewArea") != 0 ) {
            #n = dllfunc("SetViewArea", 0);
        }
        if( dllfunc("IsThreadView") ) {
            #n = dllfunc("SetThreadView", 0);
        }
        #count = dllfunc("MailCount");
        #i = 0;
        while( #i < #count ) {
            #n = dllfunc("SetMailIndex", #i);
            #n = dllfunc("DisableDraw", 0);
            $messageid = dllfuncstr("CurrentHeader", "Message-Id");
            if( leftstr($messageid, 1) == "<"
             && rightstr($messageid, 1) == ">" ) {
                $messageid = midstr( $messageid, 1, strlen($messageid) - 2 );
            }
            if( $messageid != "" ) {
                $messageid = dllfuncstr("YenEncode", $messageid);
                #n = dllfunc("SelectFolder", $account2, "");
                #n = dllfunc("SetFindPack", "(\"" + $messageid + "\", casese
nse, word, target=person), messageidtarget=messageid, inmail=2");
                #n = dllfunc("FindDownInclude");
                if( #n == 1 ) {
                    #n = dllfunc("SelectFolder", $account1, "");
                    #n = dllfunc("SetFindPack", "(\"" + $messageid + "\", ca
sesense, word, target=person), messageidtarget=messageid, inmail=2");
                    #n = dllfunc("FindDownInclude");
                    if( #n == 1 ) {
                        #n = dllfunc( "Delete", 1 );
                        #i = #i - 1;
                        #count = #count - 1;
                        #deletecount = #deletecount + 1;
                    } else {
                message "元のメールの位置への復帰に失敗しました";
                    }
                }
            #n = dllfunc("SelectFolder", $account1, $nextfolder);
            #n = dllfunc("EnableDraw");
            }
        #i = #i + 1;
        }
    }
    message str(#deletecount) + " 通のメールを削除しました。";

[ ]