このページは福井県立大学の田中求之が2006年1月まで運用していた Mac のサーバ運用に関する会議室 「Web Scripter's Meeting」の記録です。情報が古くなっている可能性がありますのでご注意ください。

mboxerのカスタマイズとスクリプト記述の質問

発言者:まさまさ
( Date Monday, June 05, 2000 11:55:02 )


メール送信された内容を自動的にWEBにて公開する方法を考えています.
mboxerを使って実現しようとして,RBのプロジェクトその他を勉強中です.
一応,メールをmboxerのconvert to HTML,make HTML indexでHTML化
できたのですが,初心者なのでわからないことも多く質問させて頂きました.

一つ目は実行するASの事なのですが,post processor の使い方が不慣れなので
よくわかりません.POPからダウンロードする部分とHTMLに仕立てる部分と
インデックスを作成する部分を一連で処理するプログラムは可能なのでしょうか?
取込が非同期で行われるので,現在はプログラムを2つに分けて,時間差を
付けて実行するようにしないとうまくいきません.
二つ目は,make HTML index で作成されるページのカスタマイズなのですが
私には,このHTMLに仕立てる部分がどこにあるのかわかりません.作成された
ページを仕立て直すしか方法はないのでしょうか?

あとは,送信メールに含まれてくる添付ファイルの問題です.添付書類部分を削除する方法は,なんとなくヘッダーの内容を分析してテキストを処理できそうな
気もするのですが,出来ればリンクを埋め込んで添付ファイルを開くように
したいと考えています(無謀な挑戦でしょうか?)

これらの内容についてヒントを下さるとありがたいのですが.

田中求之 さんからのコメント
( Monday, June 05, 2000 16:02:12 )

お尋ねの点について、順にお答えしていきます。

>POPからダウンロードする部分とHTMLに仕立てる部分と
>インデックスを作成する部分を一連で処理するプログラムは可能なのでしょうか?

可能です。この場合は、

1:スクリプトを StayOpen (「実行後、終了しない」)タイプの
  アプレットにすること
2: post processor パラメータを使って終了を検知すること
3:プロパティを使って動作状態を識別していくこと

という3点がポイントになります。

たとえば、メールをダウンロードして、それを HTML に展開し、Index 
を作るという処理の場合は、以下のようなスクリプトを使います。
(このスクリプトを「実行後、終了しない」アプリケーションにして走
らせます)

==== ここから ====

property myStatus : ""
property tgFldr : "Macintosh HD:mySofts:mboxers:htmls:" -- HTML のフォルダ

on run
    set myStatus to "down"
    tell application "mboxer PPC"
        activate
        download in POP server "myPOP.server" user "UU" password "PP" post processor (path to me) with deleting
    end tell
    
end run

on mboxer notified msg
    if msg = "error" then
        set myStatus to ""
        quit
    end if
    
    --- 以下、myStatus の内容によって処理を切り替え
    if myStatus = "down" then
        
        if msg = "0" then
            set myStatus to ""
            quit
        end if
        
        set myStatus to "HTML"
        tell application "mboxer PPC"
            activate
            convert to HTML to file tgFldr post processor (path to me)
        end tell
        
    else if myStatus = "HTML" then
        
        set myStatus to ""
        tell application "mboxer PPC"
            activate
            make HTML index file tgFldr
        end tell
        quit
        
    end if
end mboxer notified

=== ここまで ===


次に

>二つ目は,make HTML index で作成されるページのカスタマイズなのですが

の点についてですが、基本的にカスタマイズはできません。いわばおま
けとして作ったコマンドですので、もし自分なりの Index を作りたいと
いうことであれば、スクリプトをご自分で組んでください。

>出来ればリンクを埋め込んで添付ファイルを開くように
>したいと考えています(無謀な挑戦でしょうか?)

不可能とは言いませんが、決して楽ではないですよ。以下のような処理
を行うことになります。

1:MIME のマルチパートを、メッセージと添付(複数の場合もあり)に
切り分ける。

2:添付部分のエンコード(最近では base64 が多いとは思いますが)
を調べたうえで、添付データをバイナリにデコードする。

3:デコードされたものがダウンロードできるようにリンクなどを生成
する。

メール添付の仕組みについて、きちんと理解しておく必要があります。
探せば、AppleScript でコントロールできるデコードツールも見つかる
かもしれません。

挑戦しがいのあるテーマだとは思いますが…

まさまさ さんからのコメント
( Monday, June 05, 2000 17:25:29 )

田中先生 早速の回答ありがとうございます.

ひとつめの回答はとてもよく理解できました.
現状ではメールが着信していなくてdownload inを実行しスプールファイル
がなくなった状態でconvert to HTML を実行しても動いてくれましたが,
メールがない場合には post processor にエラーではなく"0"が
返ってくるのですね.また,プロパティでの監視など apple scriptは文法
だけ知っててもなかなか使いこなすのが難しいと感じます.
(英語力のなさが,足をひっぱるのでしょうか)

ふたつめは,先生のお書きになられた 「realbasicでCGIを作る」という
文献で,HTML をRBのメソッドとして組み立てる例が載っていましたので
HTMLをこのように組立てているのであればこれを応用できるのかと勘違い
しました.
apple script側で対応するように工夫してみます.

添付ファイルの処理は,やはり やりがい のある作業のようです.
今回,添付ファイルありのデータがHTMLにコンバートされたのを見て
初めて添付ファイルの送信構造を目にして欲がでました.これから
まだよく意味のわかっていないマルチパートMIMEを調べてみようと思います.

では,またよろしくお願いします


田中求之 さんからのコメント
( Monday, June 05, 2000 17:41:36 )

>まだよく意味のわかっていないマルチパートMIMEを調べてみようと思います.

頑張って下さい。RFC と呼ばれるインターネットの取り決めの提案書の一群
の中に資料があるのですが、英語で、それも読みやすいものではないんです
よね。mboxer にも、いずれは実装したいとは思っていますが…


なお、mboxer の HTML 変換についてですが、ドキュメントに記載するのを
忘れていた特徴(というか制約事項)があります。

それは、「50K を越えるサイズのメールは HTML には変換しない」という
ものです。ですから、巨大な添付ファイルが含まれるメールなどは、
convert to HTML の処理の際に、HTML のページには展開されません。

これは、HTML への変換をメモリー上で行っていますので、あまりに
大きなメールにぶつかった場合には、メモリー不足のエラーで落ちる
可能性があることを考えた仕様です。

Web メールを組む場合には、この点には注意して下さい。

まさまさ さんからのコメント
( Friday, June 09, 2000 12:44:39 )

だいぶ時間かかりましたが,RFC 読みました.
いやあ,私には難解で理解したとこまでいってないでしょうが,
仕組みについては 一応解釈できました.

それと,mboxer の HTML化 のサイズが 50Kまでというのも
つらい制限です.
利用状況を考えると,添付ファイルがあれば大多数のメールが
越えてきてしまいそうです.

applescript で制御出来そうなbase64デコードもなかなか探しきれません
ひとつ,macperl でみつけましたが,スクリプト言語を2つ駆使して
作業なんて,とてもとても...

tanaka's OSAX にbase64デコードのコマンドがありますが実装は
むずかしいのでしょうか?


そこで,姑息な手段かもしれませんが,

1.mboxerでpopとアクセスする.
2.マルチパートをboundaryの値で切り分ける
3.添付ファイルの場合メールヘッダをHTMLヘッダに変換し
  データはbase64のまま保存しておく

これで,本文側のリンクからCGIを走らせ,保存された添付ファイル
の内容をそのままブラウザーに送ったら

と,考えたのですが,だめでしょうか?



田中求之 さんからのコメント
( Friday, June 09, 2000 20:23:16 )

>tanaka's OSAX にbase64デコードのコマンドがありますが実装は
>むずかしいのでしょうか?

Base64 の部分を単純に解凍するだけなら使えますが、Tanaka's osax の
場合も、解凍するデータはメモリー上になければなりませんので、サイズが
大きな添付の解凍をスクリプトに行わせるのは危険でしょう。

それと、Base64 の解凍が無事に行えたとしても、解凍したデータを元の
形に戻す(ファイル名や、Mac のファイルの場合にはタイプとクリエータの
情報がヘッダに記載されていることがあります)処理がありますし、さらに
それをブラウザでダウンロードできるデータに変換するという処理も必要に
なりますね。

>保存された添付ファイル
>の内容をそのままブラウザーに送ったら

ブラウザの側でテキストデータとしてうけ取って、それを MIME デコード用
ツール(Mpack など、StuffIx Expander の最新版も解凍できると思う)
などで処理するというのは、ひとつの方法としては可能だと思います。

ただ、AppleSingle, AppleDouble などの Mac 特有の形式になっていた
時、あるいは Binhex が使われていたときなど、けっこう考えないといけ
ない処理は多そうな気がします。


mboxer の HTML 展開のサイズ制限を取り払うには、根本的な部分で
書き換えを行う必要がありますので、すみませんが、当分、この仕様は
残ると思って下さい(mboxer の本格的な改良に取り組む時間は当分
とれそうもないので)。

HTML の変換も含めて、ご自分でスクリプトを書かれたほうが、結果的には
細かな処理が可能になると思います。ただ、ここでも、サイズの大きなファイル
を以下に扱うかがポイントになりそうですが。

さんからのコメント
( Tuesday, June 20, 2000 15:25:11 )

とても便利にmboxer使わせていただいています。
さて、このmboxerの作業を定期的に自動で行わせるようにmboxerに命令する事は
可能ですか?
それとも別のscriptからコントロールする事になる・・?
上記のスクリプトは、一度終了しなければ単なるopenでは動きませんね?

初歩的な事ですみません

田中先生が確か、定期的に作業させていたと書かれていたような・・

さんからのコメント
( Tuesday, June 20, 2000 15:54:58 )

あと、まさまささんが書かれた事と重複するかも知れませんが・・
indexが自動生成されますが、数が増えた場合には
「新着順に表示」する事ができればと思いますが、RBではどの部分が
それをコントロールしているのでしょうか?
上から書き足してゆくか、下へ書きたすかが自分で変更できればいいなぁ
と思ったわけです

田中求之 さんからのコメント
( Tuesday, June 20, 2000 16:21:43 )

>それとも別のscriptからコントロールする事になる・・?

別のスクリプトというか、スケジュールソフトからメッセージを送って
コントロールします。私が出張の際に動かす Web Mail システムの
場合は、UVJ Mailer を使って1時間に2回、メールの取り込みと
HTML 展開、それにバックアップアカウントへの転送を行っています。
… Web Mail の作り方の説明は、UVJ Mailer 2.0 正式版のリリース後に
行いますね。


>「新着順に表示」する事ができればと思いますが

mboxer の Index 機能では無理ですので、AppleScript で Index を作る
スクリプトを組みます。MT BBS List osax を使ってやれば、けっこう高
速に Index をそのつど作れますよ。

mboxer の Index 機能は、まぁ、おまけですので、あまり多くのことを
望まれても困るのですが、逆順(結果的に新着順になる)での作成ぐらい
でしたら、簡単に追加できますので、追加してもいいですよ。

さんからのコメント
( Tuesday, June 20, 2000 16:35:52 )

早速レス、ありがとうございます

> 別のスクリプトというか、スケジュールソフトからメッセージを送って
> コントロールします。
> … Web Mail の作り方の説明は、UVJ Mailer 2.0 正式版のリリース後に
行いますね。

そうだったのですか・・
私もCronを使って定期的にでも作業させるか、例のメールでscriptを動かす
ソフト(繋がらなかった)でも使おうかと思っていたのです
いつもありがとうございます

> mboxer の Index 機能では無理ですので、AppleScript で Index を作る
> スクリプトを組みます。MT BBS List osax を使ってやれば、けっこう高
> 速に Index をそのつど作れますよ。

例のEasyBBS高速化のあれですね?

> mboxer の Index 機能は、まぁ、おまけですので、あまり多くのことを
> 望まれても困るのですが、逆順(結果的に新着順になる)での作成ぐらい
> でしたら、簡単に追加できますので、追加してもいいですよ。

何度も何度もすみません...
ただ、メールのデータベースを作る側からではなく、見る側からするときっと
こういう要望がくるだろうな、と思ったんです
現在は、MacPerlのacgiを上のフレームに(下にはmboxerのdefault.html)を
おいて使っていますが、できるととっても便利になります。
お願いしてよろしいですか?

あ、ちなみに上に先生が書かれたスクリプトですが、しっかりindexの処理は
してくれますが、StayOpenにしても終了してしまいます
何だろ? ScriptEditorは1.4.3です

田中求之 さんからのコメント
( Tuesday, June 20, 2000 18:21:10 )

>あ、ちなみに上に先生が書かれたスクリプトですが、しっかりindexの処理は
>してくれますが、StayOpenにしても終了してしまいます

そりゃ、終了するようにスクリプト書いてますから (^_^;
途中でエラーが起きたときにも終了するようになってます。

quit を削れば終了しなくなります。

さんからのコメント
( Tuesday, June 20, 2000 18:36:40 )

> そりゃ、終了するようにスクリプト書いてますから (^_^;

あ・・・(T_T)
すみません、単純なことでした

さんからのコメント
( Tuesday, June 20, 2000 23:26:16 )

> そりゃ、終了するようにスクリプト書いてますから (^_^;

quitさせるように戻して、普段使っているCronではなく、UVJMailerに
launchをお願いする事にしました (^^)

エディ さんからのコメント
( Wednesday, October 25, 2000 18:17:29 )

mboxer を使わせていただいております。

先生の書かれた、上のスクリプトは理解できたのですが、複数のアカウントについて
順次処理させようとあれこれスクリプトを書いてみたものの、ことごとく失敗しました。(^_^;
run ハンドラの中で myStatus をチェックすれば処理の進行状況がわかると思ったのですが、
処理が進まなくなってしまいうまく行きませんでした。

何か良いヒントをいただけませんでしょうか。

田中求之 さんからのコメント
( Saturday, October 28, 2000 16:50:04 )

複数のアカウントを切り替える場合には、おっしゃるように、プロパティを
うまく使うのがポイントです。

簡単なサンプルであれば書きますが、複数のアカウントのメールを順次ダウン
ロードするといったものでよいですか?

エディ さんからのコメント
( Monday, October 30, 2000 09:33:52 )

田中先生、いつもお世話になります。

> 複数のアカウントのメールを順次ダウンロードするといったものでよいですか?

はい。ただ、対象となるアカウントとその個数は毎回変わります。

よろしくお願いします。

田中求之 さんからのコメント
( Sunday, November 05, 2000 23:52:30 )

遅くなってしまいましたが、複数のアカウントのメールを連続してダウンロー
ドするスクリプトのサンプルです。

説明のために、以下の3つのアカウントのメールを連続してダウンロードす
ることにします(それぞれ、User 名_spool という名前のスプールファイル
にメールをダウンロードすることにします。このスプールは、スクリプトと
同じフォルダーの中に作らせることにします)。

User:tanaka    Password:xxx   Server:g3.tanaka
User:motoyuki  Password:yyy   Server:g3.tanaka
User:test      Password:test  Server:shared.tanaka

ただし、

>対象となるアカウントとその個数は毎回変わります。

ということですので、スクリプトは「アカウント情報のリストを受け取って、
そのリストにあるものをすべて処理する」というものにします。そして、別
のスクリプトから、アカウントの情報をメッセージとして送って処理させる
ようにします(run ハンドラーの中でダウンロードの処理は行わない)。

以下のような、{User, Password, Server} からなる情報リストをリストに
したものをパラメータとして受け取って、処理を行うスクリプトを書きます。

{{"tanaka", "xxx", "g3.tanaka"}, {"motoyuki", "yyy", "g3.tanaka"}, {"test", "test", "shared.tanaka"}}

スクリプトの基本形は以下のようになります。

property status : ""
property myJob : {}
property tgSpool : ""

on downLoad(jobList)
    set myJob to jobList
    set status to "start"
    startDown()
end downLoad


on startDown()
    
    if myJob = {} then
        set status to ""
        return
    end if
    
    copy item 1 of myJob to {tgUser, tgPass, tgServer}
    set myJob to rest of myJob
    set tgSpool to ((":" as alias) as string) & tgUser & "_spool"
    set myPath to path to me
    set status to "down"
    
    tell application "mboxer PPC"
        activate
        download in file tgSpool POP server tgServer user tgUser password tgPass post processor myPath with deleting
    end tell
    
end startDown


on mboxer notified tgMsg
    if tgMsg is not "error" then
        --- ダウンロードしたメールの処理が必要な場合は
        --- ここで処理を行う
    end if
    set status to "start"
    startDown()
end mboxer notified

で、このスクリプトを StayOpen のアプリとしてセーブしておき(名前は
GetMails とします)、以下のようなスクリプトで呼びだすわけです。

set jobList to {{"tanaka", "xxx", "g3.tanaka"}, {"motoyuki", "yyy", "g3.tanaka"}, {"test", "test", "shared.tanaka"}}

tell application "GetMails"
  downLoad(jobList)
end tell

骨格だけのスクリプトですが、このようにすることで、複数のアカウントの
メールを連続して落とすことができますよ。

エディ さんからのコメント
( Monday, November 06, 2000 10:13:39 )

田中先生、大変ありがとうございます。上記のスクリプト、うまく動きました。

またまた質問で恐縮なのですが、ダウンロードしたメールの処理を、
"GetMails"を呼び出す側のスクリプト内で行うのは無理でしょうか。
呼び出し側のスクリプト内でダウンロード終了を判断できれば、それが
可能になるのでは、と思うのですが、

田中求之 さんからのコメント
( Monday, November 06, 2000 11:29:19 )

>またまた質問で恐縮なのですが、ダウンロードしたメールの処理を、
>"GetMails"を呼び出す側のスクリプト内で行うのは無理でしょうか。

可能ですよ。スプール(ダウンロードしたメールのファイル)のパスは
User 名から割り出せますので(GetMails と同じフォルダーに User名_spool
という名前のファイルになって保存されています)、これを対象に処理を行
えばよいわけです。

また、呼びだす側で、予めスプールを作る場所を指定する(スプールのパス
を指定する)ようにしておけば、GetMails の場所など気にしなくてよいの
で、処理が楽になりますね。こちらの方のサンプルのスクリプトは、今夜に
でも書き込みます。

エディ さんからのコメント
( Monday, November 06, 2000 13:53:49 )

重ね重ねありがとうございます。

今考えているのは、外部からPOPアクセスを許していない社内のメールを、
外部からコマンドメールを使ってPOPサーバの内容を返送させるシステムです。
セキュリティの点で心配はありますが、予め返送先を限定しておけばいいのでは、
と思っています。

実はmboxer1.0b4の頃、ある程度は作ってあったのですが、mboxerの仕様が
変わってからうまくいかず、ずっと放ってあったのでした。(^^;

田中求之 さんからのコメント
( Monday, November 06, 2000 22:59:59 )

スクリプトを書く前に気がついたのですが、上にかいたスクリプトを実行し
たとき、すべてのダウンロードが終わるまで、呼びだした側のスクリプトは
ずっと実行中のままになっていませんか? もちろん、ダウンロードにあま
りに時間がかかるようだとタイムアウトになってしまうでしょうが(この点
はタイムアウトを伸ばすことで解決できます)。

そうであれば、

tell application "GetMails"
  downLoad(jobList)
end tell

のあとに処理を追加すれば、ダウンロード終了後に処理が行えるはずですが。


なお、mboxer については、今デバッグ中の 1.1 が完了したら、バッチ処理
的な使い方ができるものに仕様を変更することを考えています。つまり、ダ
ウンロードやファイル展開の連続作業を予めまとめて指示がだせる(ようは
イベント・キューを導入するわけなんですけど)ようにすることを考えてま
す。

田中求之 さんからのコメント
( Monday, November 06, 2000 23:01:58 )

>すべてのダウンロードが終わるまで、呼びだした側のスクリプトは
>ずっと実行中のままになっていませんか?

あ、そうはうまくいかないか。

スクリプト作って書きますね。

田中求之 さんからのコメント
( Monday, November 06, 2000 23:17:20 )

色々考えてみたんですが、やはり、ダウンロードのスクリプトの中に処理も埋め込んでおいて
おいたほうが、スマートになりますね。

もし毎回同じ処理を行わせるということでしたら、GetMails のなかにファイル処理も組み込んで
おいたほうがいいでしょう。

また、場合によって処理内容を変えるということでしたら、処理内容を示すものを joblist
と
いっしょに渡して、それに基づいて処理を変えるようにすればよいと思います。

ですので、エディさんが必要な処理の骨格を組み込んだスクリプトを書いたほうが早い
と思いますので、書くことにしました。

で、

>外部からコマンドメールを使ってPOPサーバの内容を返送させるシステムです。

これはメールで返送するということですか?(つまり、メールの転送を行うということ?)

エディ さんからのコメント
( Tuesday, November 07, 2000 09:09:43 )

> これはメールで返送するということですか?(つまり、メールの転送を行うということ?)

そうです。前に試した時は、AutoShareのMail-On-Demand機能を使って返送させていました。
具体的には、対象となるサーバーは固定で(EIMS3.0)、その中の適当なアカウントについて
IDとパスワードをコマンドメールとして送ると、POPサーバの中身がEudora形式に変換されて
送られてくる(メール削除はしない)、という流れになります。
ただし、コマンドメールの送り主(返送先)は予め登録された人に限定しておきます。

今作っているものは、POPサーバの中身のうち、直前に取り寄せたメール以降のメールのみ
取り寄せられるようにしようと思ってやっていましたが、これもなかなか難しいですね。

3年前から時間のある時にアップルスクリプトをいじっていますが、一向に上達しません。(^_^;
ご指導のほど、よろしくお願いします。