アプリ版:「スタンプのみでお礼する」機能のリリースについて

※一部、ドメイン名が隠れてなかったので再度投稿しました。


【環境】
os: freebsd 8.4
php: 5.4.13
postfix:2.9.5
メールの送受信はエラーなくできています。


【やりたいこと】
メール受信時にPHPスクリプトを実行したい!(メールでブログ上げたい!!!!)


【困っていること】
メールログみると、PHPが実行されずに”転送”しようとしている。

<maillog>
Jan 22 23:42:31 postfix/qmgr[36840]: from=<送信元>, size=38495, nrcpt=1 (queue active)

Jan 22 23:42:31 postfix/virtual[36877]: to=<|php /usr/home/ユーザー名/htdocs/実行したい.php@ドメイン>, orig_to=<送信先>, relay=virtual, delay=0.32, delays=0.31/0/0/0, dsn=5.1.1, status=bounced (unknown user: "|php /usr/home/ユーザー名/htdocs/実行したい.php@ドメイン")


※なぜか PHP 実行したいのに、PHPのパスのあとに@ドメインが!
このアドレスはあるわけないので送信元にエラーメールが戻ってきたのでした。

<エラーメール>
Undelivered Mail Returned to Sender

中略

<"|php /usr/home/ユーザー名/htdocs/実行したい.php"@ドメイン>
(expanded from <送信先>): unknown user: "|php
/usr/home/ユーザー名/htdocs/実行したい.php@ドメイン"


【試したこと】
バーチャルメールボックスなので
virtual_alias_maps(ファイル名:/usr/local/etc/postfix/virtual_alias) に 下記を記述しました。

blog@ドメイン  | "/usr/local/bin/php /usr/home/ユーザー名/htdocs/実行したい.php"

そして、

postmap /usr/local/etc/postfix/virtual_alias

として、postfix stop → postfix start してメールを送信すると、上記エラーに…。


※blog@ドメイン までをバーチャルなユーザー名にしています。
(バーチャルドメインで現在2ドメイン運用しています。今回の「blog@ドメイン」というのはサーバのユーザーにはいなくてvirtual_mailbox_mapsに登録しているバーチャルなユーザーです。)

バーチャルなユーザーは ユーザーID:グループID を 5000:5000 としています。

実行したい.php は 持ち主 5000:5000 で、 パーミッション 744 です。
また、このPHPはファイルの書き込みをします。
書きこみ対象のフォルダのパーミッションは777にしてあります。
(持ち主はwww:www になっています)


あとで調べてみたらmain.cf の default_privs という項目が気になったので
サーバーのユーザーを指定してPHPもそのユーザーのものにしましたが
結果、なんらかわらなかったので元に戻しました…。

A 回答 (7件)

> 「#!/usr/local/bin/php」


> これはどういう意味なのでしょうか。

プログラムを実行するインタプリタを指定しています。
通常PHPのプログラムをコマンドラインで実行するとき
/usr/local/bin/php プログラム.php
といった感じで、phpという実行ファイルに対して引数としてプログラムファイルのパスを渡しますが、先のパイプでメールを転送するような方法の場合
| "/usr/local/bin/php プログラム.php"
と書くことになり、この場合 /usr/local/bin/php に対してメール本文が渡されてしまい動作しない可能性が考えられたので、プログラムの中に実行に用いるインタプリタを指定する書き方にすると変わるかなと思いました。

この回答への補足

この度は、丁寧に教えてくださってありがとうございます。
無事解決しましたので、報告とともにベストアンサーを決定し、閉めさせていただきます。

【標準入力が読めなかった件】
if (!STDIN) exit("ERROR");
$mail = "";
while(!feof(STDIN)) {
  $mail .= fgets(STDIN);
}
STDINでファイルポインタをとることで解決しました。


$fp = fopen("php://stdin"); をやめました。
ファイルポインタとれてましたが、EOFが検出できなくて
while(!feof($fp)){ ... }
ここで無限ループへ突入したんだと思います。
で、なぜか処理は強制終了されたのか、
maillog に deliverd to command: というログを出しました。


あとハマったのは
date_default_timezone_set('Asia/Tokyo'); くらいでしょうか。
サーバ内で実行させてたときは問題ありませんでしたが、
postfixから起動させたら date() 関数がうまく機能せず、
上記のタイムゾーンの設定で無事動作しました。


この度は本当にありがとうございました。 ^^@

補足日時:2014/01/24 22:26
    • good
    • 0
この回答へのお礼

わかりやすいご回答ありがとうございます!!


昨日の件ですが、実行したい.php は実行されていました。
(ログを出すパスが誤っておりましたすみません…)

実はまだ苦戦しております。
どういうことで悩んでいるかと言うと

syslog(LOG_INFO, "STDIN fopen");

$fp = fopen('php://stdin', 'r');

if (!$fp) syslog(LOG_INFO, "Fail fopen");

syslog(LOG_INFO, "Done fopen");


ログはfopenするまえのものしか出力されていません。
標準入力を取得するところで止まってしまうようです。


頂いたご回答にもありました 「/usr/local/bin/php に対してメール本文が渡されてしまい動作しない可能性」 もあるかと思い、 エイリアスに phpのパスを記す方法と、書かずに実行したい.phpファイルの先頭に、phpのパスを書いてみたりしましたが、fopenで止まっています。
「入力がないと入力を待つ」というのをどこかで見たので、
メールデータが標準入力で取得できる状態じゃないのかな、と思い…
グーグル先生等に聞きまわっていますが、いまだ解決に至っておりません。

また、標準入力を取得するにあたって「file_get_contents("php://stdin");」も試しましたが、
この関数で止まってしまい次に処理が行っていません。

aliases の書き方も

blog_tanomu: | "php /usr/home/(略)/実行したい.php"
→ (Command died with status 127: "php /usr/home/(略)/実行したい.php". Command output: php: not found )

blog_tanomu: > "/(略)/php -f /usr/home/(略)/実行したい.php"
→ cannot append message to file /usr/home/(略)/実行したい.php: file is executable)

blog_tanomu: | "/(略)/php -f /usr/home/(略)/実行したい.php"
blog_tanomu: "| /(略)/php -f /usr/home/(略)/実行したい.php"
→ 標準入力取得で沈黙

blog_tanomu: | "/usr/home/(略)/実行したい.php"
blog_tanomu: "| /usr/home/(略)/実行したい.php"
→ 標準入力取得で沈黙


またもや詰まってしまいました。
検索しても「こうしたらメールを標準入力でとれます」みたいな事例しかなくて
悩んだ、詰まった、解決した!っていうのがなかなかなくて大変困っております。。。

もしよろしければもうちょっとだけ
お付き合い願えないでしょうか。宜しくお願いします!

お礼日時:2014/01/24 16:53

blog_tanomu: | "/usr/local/bin/php /usr/home/ユーザー名/htdocs/実行したい.php"


ではなく
blog_tanomu: | "/usr/home/ユーザー名/htdocs/実行したい.php"
として、実行したい.phpのプログラムの先頭を
#!/usr/local/bin/php
<?php
・・・・・
と書き換え、パーミッションを 777 にしてみたら動作は変わりませんか。
    • good
    • 0
この回答へのお礼

ご回答ありがとうございます泣
嬉しいです本当にありがとうございます。
しかし状況変わらず、エラーログも出ませんでした…。

<maillog>
Jan 23 19:44:43 postfix/local[50306]: to=<blog_tanomu@FQDN>, orig_to=<blog@ドメイン>, relay=local, delay=0.34, delays=0.31/0/0/0.03, dsn=2.0.0, status=sent (delivered to command: /usr/home/ユーザー名/htdocs/実行したい.php)

chown 5000:5000 /usr/home/ユーザー名/htdocs/実行したい.php
chmod 777 /usr/home/ユーザー名/htdocs/実行したい.php


ひとつお聞きしたいのですが
「#!/usr/local/bin/php」
これはどういう意味なのでしょうか。

宜しくお願い致します。

お礼日時:2014/01/23 19:51

最初に書いた通り、virtual_alias_maps にパイプでプログラムへ渡す設定は書けませんので mydestination で指定したドメインのアドレスへ転送したうえで aliases でプログラムへ渡す必要があります。



また、postfix がバーチャルドメインとして想定しているのは、mydestination に登録されていないドメイン名ですので、リアルとバーチャルは分けて考えなければいけません。

通常FQDNが@の右側に書かれたメールアドレスのメールはシステム等で使用するものだったりするのでバーチャルに登録せず、リアルなドメインとして処理するのは望ましいと思います。

> mydestination に localhost とだけ書いて、
> virtual_mailbox_domains に FQDN、ドメイン と書いてもだめでした。
これだとFQDNはバーチャルなのでFQDN宛に来たメールは virtual_alias_maps に書かれた条件に沿って配信されますし、バーチャルなのでパイプでプログラムに渡せません。

【virtual_mailbox_domains】
othermail.ドメイン,ドメイン

【main.cf】
myhostname = FQDN
mydomain = ドメイン
mydestination = $myhostname, localhost.$mydomain, localhost

といった設定が理想だと思います。
    • good
    • 0
この回答へのお礼

大変わかりやすい説明ありがとうございます。
しっかり自分のメモに記しました!
ありがとうございます^^



さて、PHPの件ですが、こちらもお付き合い願えないでしょうか><

root# php /usr/home/ユーザー名/htdocs/実行したい.php < /var/spool/mail/(略)/適当なメール

としたところ、期待した動作(メールの内容をデータベースに登録する)をしました。
しかし、メール受信 で パイプで渡してるはずですが、受信したメールでは動作してないようです。
ログも履いてませんでした…。ということは、動いてないということですね。

maillog にはエラーのようなものはなかったです。
実行したい.php もエラーをだしていません。

実行する権限がなかったりするとなにかエラーとか出したりしないものでしょうか…。

うーん…。
今夜もがんばります…


ありがとうございます!

お礼日時:2014/01/23 19:06

エラーメッセージに書かれている通り、mydestination と virtual_mailbox_domains に同じホスト名(ドメイン名)を書いてはいけません。


virtual_mailbox_domains には mydestination に書かれていない名前をセットしましょう。
    • good
    • 0
この回答へのお礼

ご回答ありがとうございます。
ちょうど、質問3のお礼の補足を送信したところで、ご回答をいただきました。
仰る通り、名前が被っていたからでしたが、

mydestination に localhost とだけ書いて、
virtual_mailbox_domains に FQDN、ドメイン と書いてもだめでした。


mydestination に FQDN を書いて、
virtual_mailbox_domains から FQDN の記述を消したらワーニングは消えました。

えっと・・・よくわかんないのですが、
なぜなんでしょう…?

お付き合いくださいましてありがとうございます。
宜しくお願い致します。

お礼日時:2014/01/23 17:38

> (どこのエラーログ見たら書いてあるんでしょうか)


PHPの設定でどこにログを書き出す設定になっているか次第です。
syslogに書き出すか、ご自身でファイルを指定して判りやすい所にログが出るよう設定した方がいいと思います。

この回答への補足

回答2のお礼の補足についてその後調べたところ
FQDNが、mydestination と、 virtual_mailbox_domains の両方にあるからだめなのかなと思って

【main.cf】
mydestination = localhost

【virtual_mailbox_domains】
FQDN,ドメイン

と、したところ

postfix/virtual[48597]: to=<blog_tanomu@FQDN>, orig_to=<blog@ドメイン>, relay=virtual, delay=0.32, delays=0.31/0/0/0, dsn=5.1.1, status=bounced (unknown user: "blog_tanomu@FQDN")

となってリターンメールが戻ってきました。


そこで

【main.cf】
mydestination = $myhostname, localhost.$mydomain, localhost

【virtual_mailbox_domains】
ドメイン

としたところ、ワーニングが消えました。

/etc/aliases
に記載していた「blog_tanomu」で受信するメールの@以降は
main.cf の mydestination に書いてないとだめなのかなー…と思ったのでした。

↑この解釈で合ってますでしょうか?


お忙しいところ、何度もご回答いただきありがとうございます。
このままもう少し見守っていてくださると非常に助かります。
(まだPHPが動いてないです…)

補足日時:2014/01/23 17:28
    • good
    • 0
この回答へのお礼

ありがとうございます。
先ほど回答2のお礼の補足 に、見落としていたログを記載しましたので、
ぜひ、見ていただきたいと思います。宜しくお願い致します。

PHPのログに関しては、
単体テストではサーバ上で
php /usr/home/ユーザー名/htdocs/実行したい.php
としてvar_dump や echo を使っていましたが、
syslog を活用してみたいと思います。ありがとうございます。

お礼日時:2014/01/23 16:43

blog@ドメイン  blog_tanomu



blog@ドメイン  blog_tanomu@FQDN
にしたらどうなりますか。
ドメイン名を指定しないので、デフォルトのドメイン名で補完しようとしているのではないでしょうか。

この回答への補足

うー、ログを見落としてました…

Jan 23 16:20:49 postfix/trivial-rewrite[47416]: warning: do not list domain FQDN in BOTH mydestination and virtual_mailbox_domains

このあとに、先ほどの

postfix/local[46764]: to=<blog_tanomu@FQDN>, orig_to=<blog@ドメイン>, relay=local, delay=0.36, delays=0.31/0.03/0/0.03, dsn=2.0.0, status=sent (delivered to command: /usr/local/bin/php /usr/home/ユーザー名/htdocs/実行したい.php)

のようなログがでておりました。

【virtual_mailbox_domains】
dmail.ドメイン,ドメイン

【main.cf】
myhostname = dmail.ドメイン
mydomain = ドメイン
mydestination = $myhostname, localhost.$mydomain, localhost

となっております。
もう少しお付き合いくださるととっても嬉しいです。
宜しくお願い致します。

補足日時:2014/01/23 16:36
    • good
    • 0
この回答へのお礼

ご回答ありがとうございます。

>ドメイン名を指定しないので、デフォルトのドメイン名で補完しようとしているのではないでしょうか。

その通りで、@FQDN を追加したらリターンメールが届きませんでした。

<そのときのmaillog>
Jan 23 15:32:37 postfix/local[46764]: to=<blog_tanomu@FQDN>, orig_to=<blog@ドメイン>, relay=local, delay=0.36, delays=0.31/0.03/0/0.03, dsn=2.0.0, status=sent (delivered to command: /usr/local/bin/php /usr/home/ユーザー名/htdocs/実行したい.php)

このログを見ると、 実行したいPHP へコマンドを届けました みたいなこと書いてあると思うんです!
やったー!

@ドメイン ではだめでしたが、 @FQDN でいけました!


肝心の出力がまったくなかったので、うまく実行できなかったということですね。
PHPファイル自体は単体でテスト済なので、あとは パーミッション関係でしょうか。
(どこのエラーログ見たら書いてあるんでしょうか)


前に進めました!ありがとうございます!!!

お礼日時:2014/01/23 15:55

だいぶ前にやった事なのでうろ覚えですが、virtual_alias_mapsではパイプを使ってプログラムへメールを渡せなかったはずで、ローカルドメイン宛にvirtual_alias_mapsで転送してからaliasでプログラムへ渡すといけるはずです。


私が管理しているメールサーバはそういう設定をしてありました。

この回答への補足

もしかして blog_tanomu はただ記述するだけじゃなくて、サーバーのユーザーじゃないとイケないとかありますか?!

試してみます…orz

補足日時:2014/01/23 12:21
    • good
    • 0
この回答へのお礼

ご回答ありがとうございます。

さっそく、
virtual_alias_mapsの中身を

blog@ドメイン  blog_tanomu

postmap virtual_alias_map をして、


/etc/aliases を開いて最後の行に

blog_tanomu: | "/usr/local/bin/php /usr/home/ユーザー名/htdocs/実行したい.php"

として、postalias /etc/aliases をして、postfix と dovcotの再起動してメールを送ってみました。

しかし…

戻ってきたメールは同じで

<戻ってきたメール>
Undelivered Mail Returned to Sender

中略

<blog_tanomu@ドメイン> (expanded from
<blog@ドメイン>): unknown user:
"blog_tanomu@ドメイン"

なぜか、 「blog_tanomu のあとに@ドメイン」に送ろうとしたけど
そんなひといませんでしたみたいになっています。
そんな人はいないんですけど、パイプで渡してるPHPを実行してほしいです泣

ちなみにそのときの maillog です↓

Jan 23 12:04:25 postfix/virtual[44443]: to=<blog_tanomu@ドメイン>, orig_to=<blog@ドメイン>, relay=virtual, delay=0.32, delays=0.31/0/0/0, dsn=5.1.1, status=bounced (unknown user: "blog_tanomu@ドメイン")


もうしばらくお付き合いいただければ嬉しいです。
宜しくお願い致します。

お礼日時:2014/01/23 12:16

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!