少し古い技術ですが、前にこんなことしたなと振り返りながら、復習の意味を込めてまとめてみます。
スクリプトはperlです。
やりたいこと
- メールを受信したタイミングで内容を解析してjson形式で保存する
-
procmail
を使います
準備
環境
#cat /etc/redhat-release
CentOS release 6.5 (Final)
※postfixはすでに入っているので割愛
# which postfix
/usr/sbin/postfix
procmailをインストール
yum -y install procmail
postfixの設定にprocmailを使うことを伝える
main.cf
ファイルに下記の内容を追加します。
#mailbox_command = /some/where/procmail
#mailbox_command = /some/where/procmail -a "$EXTENSION"
# 以下を追加
mailbox_command = /usr/bin/procmail
.forward
、.procmailrc
の設定
今回はユーザごとに設定することにしました
ユーザのホームディレクトリに、.forward
と.procmailrc
を追加します。
"|IFS=' ' && exec /usr/bin/procmail -f- || exit 75 #~/Maildir/"
MAILDIR=$HOME/Maildir/
DEFAULT=$MAILDIR
LOGFILE=$MAILDIR/procmail.log
:0
* ^To: .*trigger
| /home/user/script/receive_mail.pl
今回は trigger@example.com にメールを送った時に処理をする記述です。
.procmailrc
の記述は下記に詳しく記述があります。
http://www.jaist.ac.jp/~fjt/procmail.html
receive_mail.pl の内容
受信したメールを受け取り、タイトルやメッセージそれから添付ファイルを解析しています。
※環境によってはそのままでは動きません。
※保存先を環境によって変えて下さい。
#!/usr/bin/perl
use strict;
use Email::MIME;
use Email::MIME::XPath;
use Email::MIME::ContentType;
use JSON::XS;
use Time::Piece;
use Encode;
use Image::Magick;
=memo
"(time)_$$/body" preserves it here.
Some images are preserved by "(time)_$$/file_1,file_2,...".
Please change $DIR to a suitable directory.
=cut
my $MAIL = join '', <STDIN>;
my $DIR = '/home/user/received_data';
my $time = time();
my $mail = Email::MIME->new($MAIL) or die "error - $!";
# MessageID
my $id = $mail->header('Message-Id');
# Subject
my $subject = $mail->header('Subject');
# image rotate check.
my $image_rotate;
if( $subject =~ m/\{imagerotate\}/ ) {
$image_rotate = 1;
$subject =~ s/\{imagerotate\}//;
}
# From
my $from = do {
$mail->header('From') =~ /([^<]+\@(?:[-a-z0-9]+\.)*[a-z]+)/;
$1
};
# Body
my ($body_data) = $mail->xpath_findnodes('//*[@content_type=~"^text"][1]');
if( ! $body_data ) {
($body_data) = $mail->xpath_findnode('//*[@content_type=~"^html"][1]');
}
my $body = '';
if( $body_data ) {
$body = Encode::decode(
parse_content_type($body_data->content_type)->{attributes}->{charset},
$body_data->body,
);
}
# Make dir
my $local_time_piece = localtime();
my $target_dir = $DIR. '/' .$local_time_piece->date;
if( not -d $target_dir ) {
umask(0);
mkdir( $target_dir, 0777 ) or die $!;
}
my $image_parts = [];
@$image_parts = $mail->xpath_findnodes('//*[@content_type=~"^image/"]');
my $file_array = [];
for( my $i = 0; $i < scalar @$image_parts; $i++ ) {
my $image_data = $image_parts->[$i];
my $filename = int(rand(1000)). $image_data->filename;
my $image_dir = "$target_dir\/". $time;
if( not -d $image_dir ) {
umask(0);
mkdir( $image_dir, 0777 ) or die $!;
}
my $save_file = "$image_dir\/$filename";
open( FH, ">$save_file" );
print FH $image_data->body;
close FH;
# create thumb.
my $image = Image::Magick->new();
$image->Read( $save_file );
# image rotate.
if( $image_rotate ) {
$image->Rotate(degrees=>-90,crop=>1);
}
# size check.
if( $image->Get('width') lt $image->Get('height') ) {
$image->Scale(geometry=>350);
} else {
$image->Scale(geometry=>425);
}
# out put
$image->Write( $image_dir. '/thumb_'. $filename );
# create thumb for mobile.
my $mobile_image = Image::Magick->new();
$mobile_image->Read( $save_file );
# image rotate.
if( $image_rotate ) {
$mobile_image->Rotate(degrees=>-90,crop=>1);
}
# size check.
if( $mobile_image->Get('width') lt $mobile_image->Get('height') ) {
$mobile_image->Scale(geometry=>180);
} else {
$mobile_image->Scale(geometry=>240);
}
# out put
$mobile_image->Write( $image_dir. '/mobile_thumb_'. $filename );
push( @$file_array, $filename );
}
# create json
my $json_hash = {};
$json_hash->{'message_id'} = $id;
$json_hash->{'subject'} = $subject;
$json_hash->{'from'} = $from;
$json_hash->{'body'} = $body;
if( scalar @$file_array ) {
$json_hash->{'file_array'} = $file_array;
}
# data dump
my $out_file_name = "$target_dir\/". $time. '.json';
open( my $FH, ">$out_file_name" ) or die "file open error - $!";
print $FH JSON::XS->new->utf8->encode ($json_hash);
close $FH;
chmod (0666 , $out_file_name);
1;
権限を変更しておきます。
chmod 755 receive_mail.pl
完了したら、いよいよメールを受信してみます。
メールを受信してみる
メールを実際に受信してみます。
デコメ形式やHTMLメール形式でも対応しています。
受信がうまくいくと、下記のような感じで保存されます。
$ tree
.
`-- 2015-11-09
|-- 1447039295
| |-- 166__.JPG
| |-- mobile_thumb_166__.JPG
| `-- thumb_166__.JPG
`-- 1447039295.son
こんな感じでデータを取得できました。
jsonの中身はこんな感じになっています。
{"file_array":["166__.JPG"],"body":"こんにちはー\r\n\r\n\r\n","message_id":"<AAAAAAAAA-BBBBB-CCCCC-DDDDD-EEEEEEEEE@example.com>","from":"xxxx@example.com","subject":"てすとだよー"}
まとめ
今回はメールを受信して内容を整形して保存しただけですが、
あるワードを検出すると返信があるとか、そういうことも出来ます。
以上になります!