CentOS7にComposer経由でphp-mime-mail-parserをインストールし pipe処理でphpへ連携する方法

php

業務でメール受信した内容をDBへ取り込むことになったので
骨組みを用意してほしいとの依頼がきたときの作業ログになります。

以前はphpでごりごりヘッダーを解析した記憶がありますが、
今は便利になりました。ありがたくライブラリーを使わせていただくことにしました。

■ まずはComposerの導入
Composerとはプロジェクト単位でパッケージを管理できるパッケージ管理ツールです。

# composer
Do not run Composer as root/super user! See https://getcomposer.org/root for details
   ______
  / ____/___  ____ ___  ____  ____  ________  _____
 / /   / __ \/ __ `__ \/ __ \/ __ \/ ___/ _ \/ ___/
/ /___/ /_/ / / / / / / /_/ / /_/ (__  )  __/ /
\____/\____/_/ /_/ /_/ .___/\____/____/\___/_/
                    /_/
Composer version 1.8.4 2019-02-11 10:52:10

Usage:
  command [options] [arguments]

Options:
  -h, --help                     Display this help message
  -q, --quiet                    Do not output any message
  -V, --version                  Display this application version
      --ansi                     Force ANSI output
      --no-ansi                  Disable ANSI output
  -n, --no-interaction           Do not ask any interactive question
      --profile                  Display timing and memory usage information
      --no-plugins               Whether to disable plugins.
  -d, --working-dir=WORKING-DIR  If specified, use the given directory as working directory.
  -v|vv|vvv, --verbose           Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug

Available commands:
  about                Shows the short information about Composer.
  archive              Creates an archive of this composer package.
  browse               Opens the package's repository URL or homepage in your browser.
  check-platform-reqs  Check that platform requirements are satisfied.
  clear-cache          Clears composer's internal package cache.
  clearcache           Clears composer's internal package cache.
  config               Sets config options.
  create-project       Creates new project from a package into given directory.
  depends              Shows which packages cause the given package to be installed.
  diagnose             Diagnoses the system to identify common errors.
  dump-autoload        Dumps the autoloader.
  dumpautoload         Dumps the autoloader.
  exec                 Executes a vendored binary/script.
  global               Allows running commands in the global composer dir ($COMPOSER_HOME).
  help                 Displays help for a command
  home                 Opens the package's repository URL or homepage in your browser.
  i                    Installs the project dependencies from the composer.lock file if present, or falls back on the composer.json.
  info                 Shows information about packages.
  init                 Creates a basic composer.json file in current directory.
  install              Installs the project dependencies from the composer.lock file if present, or falls back on the composer.json.
  licenses             Shows information about licenses of dependencies.
  list                 Lists commands
  outdated             Shows a list of installed packages that have updates available, including their latest version.
  prohibits            Shows which packages prevent the given package from being installed.
  remove               Removes a package from the require or require-dev.
  require              Adds required packages to your composer.json and installs them.
  run-script           Runs the scripts defined in composer.json.
  search               Searches for packages.
  show                 Shows information about packages.
  status               Shows a list of locally modified packages, for packages installed from source.
  suggests             Shows package suggestions.
  u                    Upgrades your dependencies to the latest version according to composer.json, and updates the composer.lock file.
  update               Upgrades your dependencies to the latest version according to composer.json, and updates the composer.lock file.
  upgrade              Upgrades your dependencies to the latest version according to composer.json, and updates the composer.lock file.
  validate             Validates a composer.json and composer.lock.
  why                  Shows which packages cause the given package to be installed.
  why-not              Shows which packages prevent the given package from being installed.

rootで操作しちゃ駄目だそうです。

■ composerのインストール

# yum install --enablerepo=remi,remi-php73 composer

■ php-mime-mail-parserを探してみる

$ composer search php-mime-mail-parser
php-mime-mail-parser/php-mime-mail-parser A fully tested email parser for PHP 7.1+ (mailparse extension wrapper).
messaged/php-mime-mail-parser Mailparse extension wrapper for PHP 5.3+
exorus/php-mime-mail-parser A fully tested email parser for PHP 7.1+ (mailparse extension wrapper).
benpoulson/php-mime-mail-parser A fully tested email parser for PHP 7.1+ (mailparse extension wrapper).
decodellc/php-mime-mail-parser (FORK) Fully Tested Mailparse Extension Wrapper for PHP 5.4+
wambacom/smtpd Fork thefox/smtpd. SMTP server (library) written in PHP. In this fork we use eXorus/php-mime-mail-parser as mail parser instead of zend::message
mambaru/smtpd Fork thefox/smtpd. SMTP server (library) written in PHP. In this fork we use eXorus/php-mime-mail-parser as mail parser instead of zend::message

上記で、「php-mime-mail-parser/php-mime-mail-parser」を入れてみます。

■ php-mime-mail-parserをインストール

$ composer require php-mime-mail-parser/php-mime-mail-parser

※rootで実行しようとすると、
「Do not run Composer as root/super user! See https://getcomposer.org/root for details」
って警告されます。

$ composer require php-mime-mail-parser/php-mime-mail-parser
Using version ^5.0 for php-mime-mail-parser/php-mime-mail-parser
./composer.json has been created
Loading composer repositories with package information
Updating dependencies (including require-dev)
Your requirements could not be resolved to an installable set of packages.

  Problem 1
    - php-mime-mail-parser/php-mime-mail-parser 5.0.1 requires ext-mailparse * -> the requested PHP extension mailparse is missing from your system.
    - php-mime-mail-parser/php-mime-mail-parser 5.0.0 requires ext-mailparse * -> the requested PHP extension mailparse is missing from your system.
    - Installation request for php-mime-mail-parser/php-mime-mail-parser ^5.0 -> satisfiable by php-mime-mail-parser/php-mime-mail-parser[5.0.0, 5.0.1].

こちら( https://packagist.org/packages/decodellc/php-mime-mail-parser )にrequiresがのってましたね。
・php: ^5.4.0 || ^7.0
・ext-mailparse: *

「PHP extension mailparse is missing」だそうです。
yumで必要なextensionをいれます。

# yum install --enablerepo=remi,remi-php73 php-pecl-mailparse
# ls -l /etc/php.d/40-mailparse.ini                                                                                                                                    
-rw-r--r-- 1 root root 122 Mar 20 19:47 /etc/php.d/40-mailparse.ini

mailparseの設定用ファイルが、/etc/php.dの下に作成されていました。
無事php-pecl-mailparseをインストールできたので、
もう一度composerでphp-mime-mail-parserをインストールします。

$ composer require php-mime-mail-parser/php-mime-mail-parser                                                                                                       
Using version ^5.0 for php-mime-mail-parser/php-mime-mail-parser
./composer.json has been created
Loading composer repositories with package information
Updating dependencies (including require-dev)
Package operations: 1 install, 0 updates, 0 removals
  - Installing php-mime-mail-parser/php-mime-mail-parser (5.0.1): Downloading (100%)         
Writing lock file
Generating autoload files

無事インストールもでき、今入れたパッケージがjsonに書き込まれていました。

$ cat composer.json 
{
    "require": {
        "php-mime-mail-parser/php-mime-mail-parser": "^5.0"
    }
}

phpとapacheを再起動します。

# systemctl restart php-fpm                                                                                                                                            
# systemctl restart httpd

再起動後、iniファイルが反映されているか下記コマンドで確認。
mailparseが出ていればOKです。

# php -i |grep mailparse
/etc/php.d/40-mailparse.ini,
mailparse
mailparse support => enabled
mailparse.def_charset => us-ascii => us-ascii

■ その他

httpd-develパッケージやgcc、gcc-c++パッケージも必要みたいですが、
私の環境には既にインストールされていました。
まだインストールされていない場合は、下記でインストールすればよいかと。

# yum install --enablerepo=remi,remi-php73 httpd-devel gcc gcc-c++ 

■ MTA(Postfix)の設定

外部に対して SMTP と SMTPS のポートを開放したいので、
次のコマンドで開放するサービスを追加し、ファイアウォールの設定をリロードします。

# firewall-cmd --add-service=smtp --zone=public --permanent
success
# firewall-cmd --add-service=smtps --zone=public --permanent
success
# firewall-cmd --reload
success
# firewall-cmd --list-all
public (active)
  target: default
  icmp-block-inversion: no
  interfaces: eth0
  sources: 
  services: dhcpv6-client http https smtp smtps
  ports: xxxx/tcp
  protocols: 
  masquerade: no
  forward-ports: 
  source-ports: 
  icmp-blocks: 
  rich rules:   

これで SMTP と SMTPS のポートが外部に向けて開放されました。


<<全体的な流れ>>

直接コマンドをaliasesに記述することも可能ですが

hoge: hoge, "|/usr/bin/php /path/to/cmd/kick.php"

実行ユーザがnobodyなってしまいメールヘッダに

X-Authentication-Warning: ~

のようなものが付加されてしまいます。

なので、aliasesでincludeを使えるようにし、hogeにメールが来た際に、
/path/to/file に渡し、/path/to/file の所有者としてコマンドを実行させます。
(:コロンを連続してるので注意)

hoge:  :include:/path/to/file

次に/path/to/fileを新規作成してファイルの内容に実際のコマンドを記述します。

"| /usr/bin/php /path/to/cmd/kick.php >> /path/to/cmd/logs/command.log"

(1)まずは、初期の状態ではpostfixはincludeを許可されていないので、

# postconf |grep allow_mail
allow_mail_to_commands = alias, forward
allow_mail_to_files = alias, forward

main.cfに下記を追加して、

allow_mail_to_commands = alias,forward,include
allow_mail_to_files    = alias,forward,include

リロードします。

# systemctl reload postfix
# postconf |grep allow_mail
allow_mail_to_commands = alias,forward,include
allow_mail_to_files = alias, forward,include

(2)includeが有効になったので、下記をaliasesに追加します。

trigger: :include:/path/to/file

(3)aliasesに追記したファイル、/path/to/fileに実際のコマンドを記述します。

|"/usr/bin/php /path/to/cmd/kick.php >> /path/to/cmd/logs/command.log 2>&1"

(4)パーミッション、所有者の確認

# chmod 644 /path/to/file
# chown user.postfix /path/to/file

(5)trigger@~へメール送信し、動作確認

(6)連携用のphpはサンプルを修正し、下記のようにしてます。

<?php
//We need to add the library first !
require_once __DIR__.'/vendor/autoload.php';

$Parser = new PhpMimeMailParser\Parser();

// 下記の1~5のどれかで取り込むことになります。

// 本番
$raw_mail = stream_get_contents(STDIN);
$Parser->setText($raw_mail);

// テキストデータからの動作確認用
//$path = 'path/to/mail.txt';
// Or There are four methods available to indicate which mime mail to parse.
// You only need to use one of the following four:

// 1. Specify a file path to the mime mail.
//$Parser->setPath($path); 

// 2. Specify a php file resource (stream) to the mime mail.
//$Parser->setStream(fopen($path, "r"));

// 3. Specify the raw mime mail text.
//$Parser->setText(file_get_contents($path));

// 4.  Specify a stream to work with mail server
//$Parser->setStream(fopen("php://stdin", "r"));

// We can get all the necessary data
$to = $Parser->getHeader('to');
$from = $Parser->getHeader('from');
$subject = $Parser->getHeader('subject');

$text = $Parser->getMessageBody('text');
$html = $Parser->getMessageBody('html');
$htmlEmbedded = $Parser->getMessageBody('htmlEmbedded'); //HTML Body included data

// and the attachments also
$attach_dir = '/home/_USER_/httpd/sbin/attachments/';
$Parser->saveAttachments($attach_dir);

// loop the attachments
$attachments = $Parser->getAttachments();
if (count($attachments) > 0) {
    foreach ($attachments as $attachment) {
        echo 'Filename : '.$attachment->getFilename().'<br />'; // logo.jpg
        echo 'Filesize : '.filesize($attach_dir.$attachment->getFilename()).'<br />'; // 1000
        echo 'Filetype : '.$attachment->getContentType().'<br />'; // image/jpeg
    }
}

// Write Text
$log = "\n----------------------------------------------------------------\n";
$log.= "From : {$from}\n";
$log.= "To : {$to}\n";
$log.= "Subject : {$subject}\n";
$log.= "Text : {$text}\n";
$log.= "HTML : {$html}\n";
$log.= "Embedded : {$htmlEmbedded}\n";
$fp = fopen('/path/to/cmd/logs/receive.log', 'a');
fwrite($fp, $log);
fclose($fp);
?>

まずは、骨組みだけですが、動作しました。



タイトルとURLをコピーしました