携帯サイトで画像投稿に ランダム文字列@domain.com みたいなアドレスをユーザーに発行して、そこに添付メールを送信してもらい、PHPで受け取ってパースしたかった。

PHPとsendmailで任意のメールアドレスに来たメールを処理する方法

こちらのブログで紹介されている通りなんだけど、/etc/mail/sendmail.cfを修正してもエラーになる。
表記が難解過ぎて自分で調べる気にもならない・・・。
ふとコメントを見ると「virtusertable」で設定するのが今風らしい。 で調べて半日以上ウダウダ格闘した結果。

/etc/aliases に追記

hoge: "| cake shell_name function -app /cake_path/app"

hoge に実体(linuxユーザー)はない。

php, cake, cake.phpはsendmailが呼べるように/etc/smrsh/にシンボリックリンクを貼っておく。

$ln -s /usr/bin/php php
$ln -s /cake_path/cake/console/cake cake
$ln -s /cake_path/cake/console/cake.php cake.php

ハッシュリスト再構築

newaliases

/etc/mail/virtusertable

@mail.hoge.com hoge

mail.hoge.comに来たメールは全てaliasesのhogeに投げるという設定。
本当は @hoge.com に全て飛ばしたかったのだが、ユーザーの有無に関わらず全て転送されてしまうため、サブドメインを用意した。
他に方法はあるんだろうか。

再構築。

/usr/sbin/makemap hash /etc/mail/virtusertable.db > /etc/mail/virtusertable

そんでもって更にサブドメインにしてしまったのでlocal-host-namesを修正。

/etc/mail/local-host-names

mail.hoge.com

たぶんsendmailの再起動、stop → startが必要。

ここからやっと本題?のCakePHPでの処理。
メールのパースにはPEARのMail_mimeDecodeを利用する。

/cake_path/vendors/pear_init.php

ini_set('include_path', ini_get('include_path') . PATH_SEPARATOR . dirname(__FILE__));

PEAR環境は整っているものとする。

Mail_Mime
/cake_path/vendors/Mail/mime.php
Mail_mimeDecode
/cake_path/vendors/Mail/mimeDecode.php
Mail_mimePart
/cake_path/vendors/Mail/mimePart.php

をダウンロード、設置。

/cake_path/app/vendors/shells/mailer.php とか

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
App::import('Vendor', array('pear_init'));
App::import('Vendor', 'Mail_mimeDecode', array('file' => 'Mail/mimeDecode.php'));
App::import('Component', 'Email');
 
class MailerShell extends Shell {
	function startup(){
	$this->Controller =& new Controller();
	$this->Email =& new EmailComponent(null);
	$this->Email->initialize($this->controller);
}
 
function receive() {
	// 標準出力から読み取り
	$stdin = $this->Dispatch->stdin;
	while(!feof($stdin)) {
		$email .= fgets($stdin, 4096);
	}
 
	$decoder = new Mail_mimeDecode($email);
	$params['include_bodies'] = true; //ボディを解析する
	$params['decode_bodies'] = true; //ボディをコード変換する
	$params['decode_headers'] = true; //ヘッダをコード変換する
	$structure = $decoder->decode($params);
 
	// たとえばtoをパース
	preg_match("/([a-zA-Z0-9"._-]+@[a-zA-Z0-9._-]+.+[a-zA-Z0-9]+)/"
	, $structure->headers['to']
	, $mailto);
 
	// 以後適当な処理
 
	// たとえば宛先不明なら
	$this->_user_unknown($mailto[0], $email);
}
 
function _user_unknown($to, $body) {
	$this->Email->smtpOptions = array(
		'port'=>'25',
		'timeout'=>'30',
		'host' => 'localhost',
	);
	$this->Email->delivery = 'smtp';
 
	$this->Email->from = "Mail Delivery Subsystem <mailer-daemon@mail.hoge.com>";
	$this->Email->to = "<".$to.">";
	$this->Email->subject = "Delivery Status Notification (Failure)";
	$this->Email->sendAs = "text";
	$this->Email->template = "annon_user";
 
	$this->Email->send($body);
}

toからDBに紐づいたユーザーを判別して云々とか。
設定したドメイン宛のメールが全てここに来ることになるので、User unknownとかも自分で送信しないといけないっぽい。

後は$structureに全部デコード状態で入っているので$this->log()とかして中身を見れば後はわかるかと。
文字列はエンコードタイプを見て、必要に応じて変換(mb_convert_encoding)する必要あり。
添付のバイナリデータはそのままファイルに出力すればOKだった。

www1.hoge.com
www2.hoge.com

でセッションを共有したい場合、PHPならsession.cookie_domainを設定すればOKと判明、もちろん同一サーバでないとダメだけど。
#セッションをDBで共有すれば、別サーバでもOKかも

session.cookie_domain “.hoge.com”

をどっかで設定して、試しに$_SESSIONに書きこんで、他のサブドメから参照。
上手くいったのでCakePHPのAuthコンポーネントでテスト。

するとログイン後、他のサブドメから参照すると、ログインしたドメイン側からセッション情報が消えるという謎展開。

CakePHPのAuthコンポーネントでログインセッション切れが発生する件

事情は若干違うんだけど。

リクエストの間にユーザエージェントが変更されていないかを CakePHP のセッションが確認しなくなります。

config/core.php
Session.checkAgent false

で解決。

プログラミング時に最適なフォント「Inconsolata」

長時間眺めるのだから見易い方が良いに決まってる。

ターミナルなどで使える等幅フォントのメイリオ MeiryoKe + MeiryoKe_Console を使ってみる
メイリオ(9)――メイリオ 6.02, Meiryo UI

今はWindows7のEclipse環境がメインになっているため、等幅メイリオを使用中。

Page 12 of 12« First...« Previous89101112