携帯サイトで画像投稿に ランダム文字列@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

で解決。

WordPressにXMLRPCで投稿する

この辺を参考に。

[WordPress] XML-RPC を使用する方法
WordPressでXML-RPCを使った投稿
[WordPress] XML-RPCを駆使してブログの記事を投稿してみる

この辺を見ながら。

XML-RPC wp
Movable Type で使える XML-RPC API

タグやカテゴリ、カスタムフィールドの追加なんかもできる。
ファイルはアップロードはできるが、一覧や削除はできない模様。

カスタムフィールドでハマった点は、更新時にIDが必要になる事。削除時(フィールドを空にしたい時)にはvalueを空にするのではなく、keyメンバ自体を入れないようにすること。

当初wp.*しか使えないのだと思っていたら互換性と利便性を保つために数種類のメジャーブログシステムのAPIが使える事が判明。
以下mt.supportedMethodsをWordPress3に投げて返ってきた結果。

wp.getUsersBlogs
wp.getPage
wp.getPages
wp.newPage
wp.deletePage
wp.editPage
wp.getPageList
wp.getAuthors
wp.getCategories
wp.getTags
wp.newCategory
wp.deleteCategory
wp.suggestCategories
wp.uploadFile
wp.getCommentCount
wp.getPostStatusList
wp.getPageStatusList
wp.getPageTemplates
wp.getOptions
wp.setOptions
wp.getComment
wp.getComments
wp.deleteComment
wp.editComment
wp.newComment
wp.getCommentStatusList
blogger.getUsersBlogs
blogger.getUserInfo
blogger.getPost
blogger.getRecentPosts
blogger.getTemplate
blogger.setTemplate
blogger.newPost
blogger.editPost
blogger.deletePost
metaWeblog.newPost
metaWeblog.editPost
metaWeblog.getPost
metaWeblog.getRecentPosts
metaWeblog.getCategories
metaWeblog.newMediaObject
metaWeblog.deletePost
metaWeblog.getTemplate
metaWeblog.setTemplate
metaWeblog.getUsersBlogs
mt.getCategoryList
mt.getRecentPostTitles
mt.getPostCategories
mt.setPostCategories
mt.supportedMethods
mt.supportedTextFilters
mt.getTrackbackPings
mt.publishPost
pingback.ping
pingback.extensions.getPingbacks
demo.sayHello
demo.addTwoNumbers

なんてやっていたら。

WordPress XML-RPC API用クライアントライブラリ

もうある罠。

Page 6 of 6« First...« Previous23456