qmailでメールを携帯に転送して、メール通知に使っておられる方は結構多いんじゃないでしょうか。
ただ、大きなファイルが添付されていると、エラーメールが送信元に戻ってしまいます。
つまり、クライアントが大きなファイルを添付してきた場合、エラーメールがクライアントに戻ってしまうことになります。
やっぱりそれだとマズイです。添付ファイルが勝手に他者に転送されている訳ですからね。
それで、転送する際に添付ファイルを落としてから、転送したほうが無難です。
転送するためのスクリプトをPHPで作ってやることにしました。
インストールされているパッケージは以下の通り。
php php-cli php-common php-gd php-intl php-mbstring php-pear php-pear-Mail-Mime php-pear-Mail-mimeDecode php-process php-xml
php-cli、php-mbstring、php-pear、php-pear-Mail-Mime、php-pear-Mail-mimeDecode
以上が必要パッケージですが、依存性でその他もインストールされるはずです。
PHPは最低でも以下のような設定が必要です。
[Date] date.timezone = Asia/Tokyo [mbstring] mbstring.language = Japanese mbstring.internal_encoding = UTF-8 mbstring.http_input = pass mbstring.http_output = pass mbstring.encoding_translation = Off mbstring.detect_order = auto mbstring.substitute_character = none mbstring.func_overload = 0 mbstring.strict_detection = Off |
vpopmailの実行ファイルがあるところにスクリプトを置きます。
#!/usr/bin/php <?php /** * あらかじめ添付ファイルを叩き落として、メッセージだけを転送するスクリプト * * @author Digital Acorn * @created 2015-06-15 */ mb_internal_encoding( 'UTF-8' ); $res = fopen ( 'php://stdin' , 'r' ); if (! $res ) { exit (0); } $output = '' ; $boundary = '' ; $attached_deleted = false; // ヘッダー部分でboundaryを探す while ( $line = fgets ( $res )) { // content-type句を得る。もしcontent-typeが無いような失礼なメールの場合、 // 全てがoutputに回るはず。そしてboundaryがないので、全部出力される。 if (preg_match( '/content-type:\s+multipart\/[a-z]+;/i' , $line )) { // mixedでない場合は全て出力 if (!preg_match( '/multipart\/mixed/i' , $line )) { $output .= $line ; while ( $line = fgets ( $res )) echo $output .= $line ; break ; } else { if (!preg_match( '/boundary=/i' , $line )) { $line .= fgets ( $res ); } $boundary = array (); if (!preg_match( '/boundary="*([^"\s]+)"*$/i' , $line , $boundary )) { exit (0); } else { $boundary = $boundary [1]; } $output .= $line ; break ; } } $output .= $line ; } if (! empty ( $boundary )) { // 最初のboundaryまで送る while ( $line = fgets ( $res )) { // boundaryを発見 if ( strpos ( $line , $boundary )!==false) { break ; } $output .= $line ; } while (true) { $saved = array ( $line ); $attached = false; while ( $line = fgets ( $res )) { // boundaryが登場するまで回す if ( strpos ( $line , $boundary )!==false) { break ; } // content-type句が出てきた if (preg_match( '/^content-type/i' , $line )) { if (preg_match( '/text\/plain|text\/html|multipart\/alternative/i' , $line )) { // テキストメッセージ $attached = false; } else { // 添付ファイル $attached = true; $attached_deleted = true; } } if (! $attached ) { // テキストメッセージなら保存 $saved [] = $line ; } } if (! $attached ) { // テキストメッセージなら出力する foreach ( $saved as $value ) { $output .= $value ; } } // 終端のboundaryなら最後まで出力して終了 if ( strpos ( $line , $boundary . "--" )!==false) { $output .= $line ; while ( $line = fgets ( $res )) $output .= $line ; break ; } // もし最後のboundaryが無いような尻切れのメール場合、出力を終了する。 if ( $line ===false) break ; } } require_once ( '/usr/share/pear/Mail/mimeDecode.php' ); // qmailが環境変数に値をセットしてくる // .qmailのあるディレクトリにenv.phpを置いて、そこに転送先を書いてある。 // $mail = "test@example.jp" みたいに。 // 現在のディレクトリ $dir = getenv ( 'PWD' ); $mail = '' ; @ include ( $dir . '/env.php' ); if ( empty ( $mail )) { exit (0); } // 転送前の送り主 $sender = getenv ( 'SENDER' ); // メールを受け取ったドメイン名(バーチャルドメインかも) $host = getenv ( 'HOST' ); // デコード $params [ 'include_bodies' ] = true; $params [ 'decode_bodies' ] = true; $params [ 'decode_headers' ] = true; $decoder = new Mail_mimeDecode( $output ); $structure = $decoder ->decode( $params ); $from = mb_convert_encoding( $structure ->headers[ 'from' ], 'UTF-8' , 'auto' ); $subject = mb_convert_encoding( $structure ->headers[ 'subject' ], 'UTF-8' , 'auto' ); $date = $structure ->headers[ 'date' ]; // スパム判定なら転送しない if (preg_match( '/^\s*\[SPAM\]/' , $subject )) { exit ; } // ボディが奥の方にある場合があるので、ストラクチャを下がっていく // この方法でいいのか、疑問。text部分が必ず最初に来るのか? if (!( $body = @ $structure ->body)) { if (!( $body = @ $structure ->parts[0]->body)) { if (!( $body = @ $structure ->parts[0]->parts[0]->body)) { $body = 'HTMLだけのメールです' ; } } } $body = mb_convert_encoding( $body , 'UTF-8' , 'auto' ); $new_body = <<<END_OF_BODY { $host }メールサーバーです。 サーバーに到着したメールを転送します。 このメールに直接返信しないでください。 END_OF_BODY; $new_body .= ( $attached_deleted )? "※ 添付ファイルが削除されました。\n" : "" ; $new_body .= <<<END_OF_BODY ----- Original Message ----- From: $from Date : $date Subject: $subject $body END_OF_BODY; $header = 'From: <postmaster@' . $host . ">" ; mb_send_mail( $mail , "Fw: " . $subject , $new_body , $header ); exit (0); |
オーナーを変更し、実行権限を付けます。
chown vpopmail.vchkpw /home/vpopmain/bin/mailTransfer chmod 711 /home/vpopmain/bin/mailTransfer
各ユーザーの環境設定ファイルを作ります。
下記例だと、example.jpドメインのfooさんの環境設定です。
<?php $mail = 'example@docomo.ne.jp' ; |
その後、.qmailを編集します。
|spamc |mailTransfer |spamc |tomaildir ./Maildir |
こうしておくと、spamassassinの結果で転送をコントロールできます。
スパムだった場合は、転送されずメールボックスには、件名に [SPAM] という接頭子が付いたメールが入ります。
(下の記事の、おまけ部分をインストールしてあることが前提です)
qmail(with smtp auth) + vpopmail + ezmlm-idx + dovecot + qmailadminなサーバ構築
以上です。