空メールでユーザ登録

無料ケータイサイト等では空メールを送信することで利用登録するシステムがありますが、簡単に実装するとしたらこんな例があります。

1.空メールを送信。

2.メールサーバのalias若しくはforwardでスクリプトに転送。

3.スクリプトはメールのヘッダを解析し、登録完了メール返信及びDB登録を行う。

4.登録完了メールのURLからアクセスすると送られたIDの認証を行い案内する。

と、こんな感じです。

メールサーバをqmail、スクリプトをPHPとしてこんなサンプルを作ってみました。

1と4は同じPHPページml.phpを使用し、IDがない場合は空メール送信の案内。IDで認証できた場合はコンテンツを表示。
3は登録用スクリプトとしてmlreg.phpを使用。メールサーバからのみ起動される。

ml mlreg

mlreg.phpのサンプル中にあるFrom抽出は完全ではありませんが、メールの規格は実質無法地帯な状態できりがないのである程度対応できるレベルに留めておきます。

そしてqmailのaliasを使う場合
# cat /var/qmail/alias/.qmail-regist
| /usr/local/apache/htdocs/mlreg.php

このように転送先にスクリプトを設定します。
別に登録用PHPはウェブからアクセスする必要がないのでこの場所は不適切ですが…。

【2007/08/27 19:40追記】
上記プログラムはあくまで動作確認用でセキュリティに関しては一切考慮に入れておりません。
まさかそのまま使う人はいないだろうと思っているので注意事項も書かず放置しておりましたが、はてなブックマークからリンクされているのに気づき自分の愚かさと恥ずかしさで申し訳ない気持ちでいっぱいです。今後もセキュリティに関するサンプル以外はセキュリティ対策コードを含めることは少ないと思いますが、必ずどこが危険かは併記したいとおもいます。

因みに上記のプログラム内では、
ml.txt 6行目:
直接MySQLにGET引数を渡している事、これはセミコロンを挟んで閲覧者が任意のSQL文を実行できます(SQLインジェクション)。外部から取り込むパラメータには必ず内容のチェックを入れます。
ml.txt 9行目:
逆にDBから取り出したデータをそのまま表示するのも推奨できません。出力する書式に合わせて内容のチェックを行います。
ml.txt 12行目:
exsample・・・orz typoです。しかも実在するドメインですね。exsampleの方申し訳ありません。
ml.txt 16行目以降:
とりあえず表示されれば良いレベルで書いているので実際はちゃんとしたHTML書くなりしてください。
mlreg.txt 12~14行目:
ここはあまり参考にならないと思います。ヘッダー内にFromが2箇所あったりしても最初のFromを拾いますし、この部分については他所で良いライブラリが公開されています。
mlreg.txt 16~17行目:
コピペかすです… このコードはメールアラートに使っているものの流用です。その上変数名の変換忘れ
orz
mlreg.txt 22行目:
ここも$toまで用意して何故か$from[0]にしている…。どっちもどっちですが。
mlreg.txt 23~30行目:
これはauto_incrementで得たidをそのままアカウントに使用することに問題があります。つまり他の数字を使ってアクセスしたら他人の情報が表示されるという罠です。ここは連続性のないユニークIDを作成して発行するなりの工夫が必要です。(セッションハイジャックというのも厚かましいセキュリティホール)
mlreg.txt 35行目:
これも$titleではなく$subjectです。また元の文字コードを考慮していないので文字の組み合わせが悪いと誤認識するかも。実際にローカルで動作確認した時は日本語すら使ってなかったのでこのコードは跡付けです。
mlreg.txt 40行目:
ここもtypoです。

この度は大変お騒がせしました。直ぐに無意味なコードとtypoを修正したサンプルをアップします

【2007/09/23 02:20追記】
うわぁ…修正ファイルのアップを忘れてました…。一ヶ月近く経ってる。
とりあえず上記のとおりtypoと無意味なコードを省いたもので更新しています。セキュリティはまったく考慮していないので、使用するときは変数無害化とアクセス制限を追加してください。

メールサーバ上でのメール受信をトリガーとしてメールの内容を処理に使用するデータとして取り出すまでがエントリーの趣旨だったのでそれ以降の処理は端折っています。

Core吐かせてみよう

今日はトンデモな実験。というかここ数年Core吐かせてないのでデバッグ用にわざと吐かせてみた。

#include
int main(){
int i=0;int j=1;int k=0;
printf(“i=%d,j=%dn”,i,j);
k=j/i;
printf(“k=%dn”,k);
return 0;
}

コンパイル
> gcc -o fault fault.c

実行
> ./fault
i=0,j=1
Floating exception (core dumped)

まぁ酷いプログラムです。
実行すればたちまち0除算が原因でcoreを吐きます。
今までWindowsも含めてコアダンプを利用した解析なぞやったこと無かったので、バイナリエディタで開く…。全く読めない。そこで調べていたらgdbコマンドを使えば直ぐにわかるという。これがあれば解析のためにガリガリファイルにログを書き出さなくていいかもです。

まずは試しに実行。(実行ファイル名はfaultでコアダンプはfault.coreです)

> gdb fault fault.core
#0 0x0804854e in main ()

main関数でダウンしたことがわかります。

今度はデバッグモードでコンパイル(特に再実行してコアを更新する必要はなさそうです)
> gcc -g -o fault fault.c
> gdb fault fault.core
#0 0x0804854e in main () at fault.c:8
8 k=j/i;

なるほど、fault.cの8行目で停止したことがわかります。

PHP+GDで画像の透過

昨日のようにぬりつぶしだと、指定座標の色が透過用ではなかったり、また他の透過させたい背景のところまで色が連続していなかったりするとまるで使えません。そこで今度は正確なカラーインデックスを取得して割り当てれば大丈夫なのでは?ということで透過処理を下記のコードにいれかえます。

$white = imagecolorexact($backimg, 255, 0, 255);
imagecolortransparent($backimg, $white);

これなら行けるかと思えば前回の強制処理とは違うので画像も選ぶ必要があります。
透過書き出しとしっても種類がありFireworksの場合ではgif/pngともに8bit色インデックス透明カラー(255,0,255)を指定します。

早速やってみたところ、元画像gifの場合は成功しましたがpngで失敗。
ちょっとトレースしてみたら、imagecolorexactでgifの場合必ず-1が返ってきていてimagecolortransparentが役に立ってない。pngでは正の整数が返っているようだが…。

と言うことで上記の透過処理そのものを外すとgif/png共に成功… orz…
全然意味ないどころか障害になってた。

前に同じように透過処理をしないまま合成したときはマットカラー?と思われる色が塗りつぶされていたりしたので全く信頼できない不安定状態です。(多分元画像側でしっかりフォーマットを統一させれば大丈夫と思うが最近のデザイナーはフォーマット知識無いから大変)

PHPとGDのどっちがバグってるのか検討も付かないなー。
今のところ元画像をgifにして書き出しをpng/gifで使い分けるほうが安全かもしれないです。

20060714-1gd_marge