ftpdパッケージ

 ftpdパッケージはその名の通り、 他のコンピュータからのFTP接続を待ち受けるサーバープロセスの機能を提供します。 スクリプト言語でFTPのサーバーを立てて何の役にたつのかは若干謎ですが、 後述の通り、OS標準のパスワード認証システムを使わないので、 LDAPで認証するFTPサーバー(-_-;)など、 どうしてもOSの認証を必要としないFTPをやりたい場合に便利です。
(-_-) 。o ○ (ほんとかなあ)

package require ftpd

proc authIP ip {
  puts "接続要求が発生しました:IPアドレス=$ip"; return 1
}
proc authUser {account password} {
  puts "アカウント=$account"
  if {"$account" == "urano" && "$password" == "hirake!"} {
    return 1
  } else {
    return 0
  }
}

::ftpd::config -authIpCmd authIP -authUsrCmd authUser
# set ::ftpd::port 8021
::ftpd::server

message .msg -text "現在FTPサーバーが動いています。"
button .b -text "終了" -command { exit }
pack .msg .b -side top
# end.

 まず、::ftpd::configコマンドで、 クライアントから接続されたときのコールバックスクリプトを定義します。 -authIpCmdはクライアントのIPアドレスを、 -authUsrCmdはクライアントから渡されてきたユーザ名 (アカウント)とパスワードを引数にとります。 これらのスクリプトは、「認証」を行う必要があります。 つまり、渡されたIPアドレスやアカウント名やパスワードを使って、 FTP接続を許可するなら1を、そうでなければ0を返すように書きます。 ここが面白いところで、UNIX環境の場合も、FTPユーザのパスワードは、 OSのpasswdコマンドで定義するパスワードと異なっていても構いません。 ftpdパッケージの世界では、ログイン認証はftpd自身がやり、 OSのパスワードは全く使いません。

 なおサーバのポートを標準の21以外に変えたい場合には、 変数::ftpd::portにそのポート番号をセットしてから ::ftpd::serverを実行すればOKです。

 接続後の機能ですが、 「HELP」コマンドでサーバ側で用意しているコマンドの一覧を見ることができます。 「mput」などいくつかのコマンドがサポートされていませんが、 一通りFTPサーバとしては動作します。 ただし、「CD」コマンドはなくて、「CWD」コマンドです。 これははまりやすいので注意してくださいね。

 で、最初の話に戻って、何の役に立つのかですけど、 深く考え始めると夜も眠れなくなりそうなので簡単に… UNIX上では使う必要はないでしょう(きっぱり) おいおいおい…でもWindowsでは、ファイル共有ができなかったり、 (ウィルスが怖いので)したくなかったりした場合には、 簡単に、かつ一時的にファイルの送受信を行うのに使えると思います。


smtpdパッケージ

 あわわ、そしてやってまいりました。tcllib 1.2からは、 smtpdなるパッケージが追加されました。 これも名前の通り、SMTP(Simple Mail Transfer Protocol) に則り電子メールの送受信をするサーバーアプリケーション、これすなわち、 一般にMTA(Mail Transfer Agent)と呼ばれるアプリケーションをエミュレートするものです。 ただし、sendmailやqmailのようなMTAの代わりに動作するというものではありません。 smtpdが行うのは、

  1. SMTPポート(一般に25番)で接続を待ち受ける。
  2. メールが送られてきたら、MIMEヘッダを解析し、 From: To:などのヘッダの妥当性によりメールを受託/拒絶する機能を提供する。
  3. 送られてきたメールに対して、何かの処理をする機能を提供する。
あらら?「何かの処理をする機能を提供するとはどういうことかしら? 簡単に言うと、 例えばイントラの内部からこのサーバに対して送られてきたメールに対し、
  • サーバのスプールに保管する。
  • 宛先(To:)を見て、そのドメインを管理するMTAにメールを転送する(リレー)。
というような機能は、自分で書く必要があります。 それはたいへんやろう、というわけで、 マニュアルにも書かれているのですが、このパッケージの主な使い道は、
  • メール送信クライアントアプリケーションを開発したときの、テスト用
だそうです。なるほど、なるほど。

package require smtpd

proc validateHostProc host {
    puts "サーバー機:$host"
}

proc validateSenderProc sender {
    puts "送信者:$sender"
    if {! [regexp {@nsnhnkmmkk\.co\.jp$} $sender]} {
        error "送信者エラー!!"
    }
}

proc validateRecipientProc recipient {
    puts "宛先:$recipient"
}

proc deliveredProc {sender recipients data} {
    if {[catch {eval array set saddr [mime::parseaddress $sender]}]} {
        error "invalid sender address \"$sender\""
    }
    set mail "From $saddr(address) [clock format [clock seconds]]"
    append mail "\n" [join $data "\n"]

    foreach rcpt $recipients {
        if {! [catch {eval array set addr [mime::parseaddress $rcpt]}]} {
            puts $mail
        }
    }
}

::smtpd::configure -validate_host validateHostProc \
  -validate_sender validateSenderProc \
  -validate_recipient validateRecipientProc \
  -deliver deliveredProc
#::smtpd::start
::smtpd::start 0.0.0.0 8025

message .msg -text "現在メールサーバーが動いています。"
button .b -text "終了" -command {::smtpd::stop; exit}
pack .msg .b -side top
# end.

 smtpdの使い方もftpdとよく似ていて、まずconfigureコマンドで、 メールが自分のもとにやってきた場合の、

  • 送信元ホストのIPアドレスの妥当性をチェックする処理 (-validate_host)
  • 送信者(From:)の妥当性をチェックする処理 (-validate_sender)
  • 宛先(To:)の妥当性をチェックする処理 (-validate_recipient)
  • 送信OKの場合にメールに対して行う処理 (-deliver)
を指定します。妥当性チェックの処理で、「そのメールはあかんす」 となった場合には、処理内でerrorコマンドを使ってエラーを発生させればOKです。

 それぞれの処理に渡される引数は上の例の通りで、 -validate_hostには送信元のIPアドレスが、 -validate_senderにはFrom:のメールアドレスが、 -validate_recipientにはTo:のメールアドレスが、 -deliverにはTo:のメールアドレス(複数いる場合にはそれらのリスト) とメールの内容が渡されます。

 実際にサービスを開始するにはstartコマンドを使います。 引数は対象のネットワークインターフェースとポート番号です。 引数を省略すると、全てのネットワークインターフェース(0.0.0.0) に対して、ポート25番で待ち受ける格好になります。

拡張レビュー分室 top
(first uploaded 2002/02/02 last updated 2002/11/15, MISUMI URANO)