13
13

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

オールアバウトAdvent Calendar 2015

Day 19

メール受信をトリガにしてスクリプトを起動させる

Posted at

少し古い技術ですが、前にこんなことしたなと振り返りながら、復習の意味を込めてまとめてみます。
スクリプトは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を追加します。

.forward
"|IFS=' ' && exec /usr/bin/procmail -f- || exit 75 #~/Maildir/"
.procmailrc
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 の内容

受信したメールを受け取り、タイトルやメッセージそれから添付ファイルを解析しています。
※環境によってはそのままでは動きません。
※保存先を環境によって変えて下さい。

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":"てすとだよー"}

まとめ

今回はメールを受信して内容を整形して保存しただけですが、
あるワードを検出すると返信があるとか、そういうことも出来ます。

以上になります!

13
13
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
13

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?