PHP でメールするときの注意等

– 過去に書いたドキュメントを整理するため、整形してコピペ。内容は多分 2004-06 くらいのもの。
– mail関数と、そのラッパーであるmb_send_mail関数があるが、後者はオプションのヘッダ指定に無関係に、自動的に

MIME-Version: 1.0
Content-Type: text/plain; charset=ISO-2022-JP
Content-Transfer-Encoding: 7bit

という3つのヘッダを挿入する(Content-Typeを明示的に指定していてもなお)。
– mail関数のデフォルトのヘッダーは
mail(‘foo@yyy.zz’,’title’,’message’);
として送信した場合、

Return-Path: <anonymous@local.host>
Delivered-To: foo@yyy.zz
Received: (qmail xxxxx invoked from network); 2 Apr 2004 15:13:40 +0900
Received: from unknown (HELO local.host) (xxx.xxx.xxx.xxx)
  by pcxxx.xxx.xxx.xxx.in-addr.foo with SMTP; 2 Apr 2004 15:13:40 +0900
Received: (qmail xxxxx invoked by uid 80); 2 Apr 2004 15:13:40 +0900
Date: 2 Apr 2004 15:13:40 +0900
Message-ID: <20040402061340.11671.qmail@local.host>
From: anonymous@local.host
To: foo@yyy.zz
Subject: title
 
message
 

のようになる。(Received:はもちろんmail関数がつけたものではない)
– MIME-Versionフィールドを指定する場合、第四引数でヘッダ指定する場合に改行は\r\nや直接の改行(SJISの場合CRLFになる)ではなく\nでなければならない。(MIME-Version:1.0を宣言した行以降は\rも\nも1つの行として認識されるため。
– PHPでHTMLメールを送るごく簡単な例)

sAddHeader = “MIME-Version: 1.0\n”
.”Content-Type: multipart/alternative;\n”
.”boundary=\”—-=_NextPart_000_0024_01C418A2.AA46C5F0\”\n”;
$sMessage = “This is a multi-part message in MIME format.”
.”\n\n——=_NextPart_000_0024_01C418A2.AA46C5F0\n”
.”Content-Type: text/plain; charset=ISO-2022-JP\n”
.”Content-Transfer-Encoding: 7bit\n\n”
.”プレーンテキストメールです\n”
.”\n\n——=_NextPart_000_0024_01C418A2.AA46C5F0\n”
.”Content-Type: text/html; charset=ISO-2022-JP\n”
.”Content-Transfer-Encoding: 7bit\n\n”
.”<font color=’red’>HTMLメールです。あ</font>いう<b>えお</b>\n”
.”\n\n——=_NextPart_000_0024_01C418A2.AA46C5F0–\n”;
//送信先メールアドレス等。
$sMailAddress = ‘foo@xxx.zz’;
$sTitle = ‘タイトル’;
if(mail($sMailAddress,$sTitle,$sMessage,$sAddHeader))
echo “sent successfully!\n”;
else
echo “sent failure”;

プラグインや国際化で動作がおかしいときに状態をクリーンにする

eclipse.exe -clean

みたく -clean オプションを付けて Eclipse IDE を起動すると、クリーンアップされて状態が直ったりする。何かあったときに一度だけやればいい。
3.0.x の日本語化周りで、一部しか日本語化されなかった場合などに有効。

Java Applet で JavaScript コードを実行する

import java.applet.Applet;
import netscape.javascript.JSObject;
 
public class jstest extends Applet{
public void start(){
JSObject js = JSObject.getWindow(this);
js.eval(“alert(‘Hello, world!!’)”);
}
}

JavaScript を Java Applet にしてサイズ圧縮をうたい文句にしているソフトより。これなら JavaScript 上で Zip 圧縮/解凍して eval したほうがいい(jar って zip だし、肝心の JavaScript は Java コードのリテラルなので *.class に生で書かれているし)。

ブラウザの JavaScript バージョンチェック

<http://members.at.infoseek.co.jp/sig1/jscript/js-vercheck.html>
– JavaScript バージョンチェック

<SCRIPT LANGUAGE=”JavaScript1.0″><!–
j=”1.0″;
–></SCRIPT>
 .. snip ..
<SCRIPT LANGUAGE=”JavaScript2.0″><!–
j=”2.0″;
//–></SCRIPT>
.. snip ..
<SCRIPT LANGUAGE=”JavaScript1.0″><!–
document.write(“Javascript “+j+” に対応しています。”);
//–></SCRIPT>

というように, <script> の language 属性を使って判別してる。このサイトでは LiveScript, VBScript もチェック対象としているが、VBScript のチェックを JavaScript の文で行おうとしてエラーになっている。IE6 は JavaScript 1.3, Firefox1.0(Gecko/20050318) は JavaScript 1.5 までに対応していた。

[JavaScript][ActionScript] ブロック({ … }) ではスコープの限定ができない

一時変数のスコープを絞るのに { … } をよく使うが、ECMAScript (ActionScript/JavaScript 共通) だと物理的には意味をなさなくなる。例えば、次の文はエラーにはならない:

{var t=”NG”;} alert(t);

ブロックがスコープを持つなら、t は alert() を呼ぶ時点では存在しないためエラーになるべきだが、実際は NG と表示されてしまう。(Firefox 1.0, IE6, Flash MX 2004 で確認)
 
これは制御構文でも同じで、例えば、

for(var i; i < 10; i++){ var n = i; }

は、for 文の終了後に

i = 10; n = 9;

が入ったままになる。スコープを切りたい場合は、その部分だけ関数を使う等するしかなさそう。個人的に、リファクタリングの準備のために頻繁にスコープを切るのでこれは不便だなぁ..
ECMAScript では関数スコープであることを宣言するときのみ var 宣言は意味を成しているよう。
 

簡易タイマー

例えば 1 分後にアラートを鳴らすには次のようにすればよい。
– Windows なら sleep というコマンドを使えるようにしてコマンドプロンプトで

sleep 60 && echo <Ctrl-G>

  • UNIX 系(bash, sh)なら

sleep 60 && printf “\a”

 
追記:
(2006-05-10) sleep が Windows 標準で存在しないことに気づき訂正.

static ファクトリメソッドの落とし穴

Effective Java より、static ファクトリメソッドで Foo.getInstance() みたくするのがいい、とあったが、何も考えずやってると継承周りで混乱を招く。

class Parent {
public static Parent getInstance(){ return new Parent(); }
}
class Child extends Parent {}

このとき、Child.getInstance(); は Child インスタンスではなく(スーパークラスで定義されている getInstance() を使うため) Parent インスタンスを生成してしまう。
 
Effective Java の例にきっちり書かれているとおり、

class Parent {
private Parent(){ }
public static Parent getInstance(){ return new Parent(); }
}

とか class final Parent とかして継承を禁止するのが妥当な解決方法(拡張にはコンポジションを使う)。
それが嫌なら static ファクトリメソッドの公開をやめて普通にコンストラクタを公開する。
 
あるいは、継承を行うクライアントが、確実に public static Child getInstance() を定義してくれることを信じるか。

DAO パターン

Core J2EE Patterns – Data Access Object
データソースや製品依存の処理を隠蔽して、例えばテーブル単位でアクセス用の API を作り、insert, delete, find, update など必要な処理はインターフェイスにして、それを実装する。複数の形式に対応するにはこの DAO インターフェイスを実装すればいいだけなのがメリット。
 
DAO だけでなく、シリアル化可能な値オブジェクトの、 Transfer Object も用意しておけば、DAO とクライアントの通信では Transfer Object がレコードの代用になるため抽象度が増す。
 
説明では、複数のソースと複数のテーブルが存在するため、利便性のために Abstract Factory Method Pattern でソースタイプ毎に階層を作り、メソッドでテーブルを作れるようにしている。
 
難点は、簡易的な実装だと条件をしぼりきれずオーバーヘッドがかかりそうなことや、どうしても JDBC とかを直接さわるより開発コストがかかること。単純な実装では select で全てとって Collection にしてしまえば楽だけど、たとえば数万行のテーブルが毎回格納されるとなると大変。単純な実装とは別にシステム特化のメソッドを実装すればいいかも。

リモートから任意のコマンドを実行する

$ ssh user@host command…
– CUI でどうやるんだっけなと思って ssh(1) を見たらそのままでした。コマンドは引数をとれるが、interactive な挙動も可能。って shell の代用で動かすのだからできて当然か。公開鍵認証とかでパスワードレスにすると遠隔バッチ処理に便利。