[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
(DTPtechNote:1133) [ruby] fwd_important-mail.rb(簡易メール転送クライアント)
京ぽん(京セラAH-K3001V)が音声・Mailともに定額になりました。
特定の相手からのメールを24時間いつでもキャッチしたいと思って、
earth.rb 3.6.1(http://www.fjts.org/~m/Soft/Ruby/earth.rb/)
を導入してみましたが、ウチのプロバイダ(ASAHIネット)はちゃんと未読管理とかしてくれない。
サーバー上で動作する、わたしの希望に添うようなメールクライアントも探してみましたが、どれもいまひとつ。
んで、rubyで書いちゃいました。
アイデアをいただいたり、部分的にコードを書いていただいたりしたaiboさんに感謝します。
#!/usr/bin/ruby
=begin
fwd_important-mail.rb 0.1
簡易メール転送クライアント
環境;
ruby 1.8.2が動くこと。
使い方;
メールサーバーの設定を変数に入れてください
実行ユーザーのオーナーで、パーミッションを700にセットしてください
適宜サーバー上のcrontabで定期的に実行してください。
histry;
2005.05.17 ver.0.1
=end
#らいぶらりー
require "socket"
require 'net/pop'
require "net/smtp" # SMTPライブラリの読込
require "kconv" # kconvライブラリの読込
##======================================================変数と設定
popserver = '【ここにPOPサーバー名をいれる(例:pop.asahi-net.or.jp)】'##POPサーバー名(受信)
smtpserver = '【ここにSMTPサーバー名をいれる(例:mail.asahi-net.or.jp)】'##SMTPサーバー名(送信)
accunt = '【ここにアカウント名を入れる(例:ym3s-ickw)】'#アカウント
passwd = '【ここにパスワードを入れる(例:openthesesami)】'#パスワード
#from行にこれらのアドレスが含まれていれば、転送処理対象とする
targetaddress = '【ここに処理対象のメールアドレスを入れる。複数のアドレスは「|」で区切ること。正規表現つかえます。こんな感じ。(例;hoghoge@mac.com|ym3s-ickw@asahi-net.or.jp|@thinks-net.co.jp)】'
fromaddress = '【ここに転送元アドレスを入れる(例:ym3s-ickw@asahi-net.or.jp)】'#転送元アドレス
toaddress = '【ここに転送先アドレスを入れる(例;hogehoge@dk.pdx.ne.jp)】'#転送先アドレス
nobody = false#メール着信のおしらせだけならtrue。メッセージも転送するならfalse
attachments = false#添付ファイルを転送するかどうか? 転送するtrue, 転送しないfalse
#必要なファイル このプログラムと同じ階層に下記のファイルができます。
mypwd = Dir.pwd
mail_idlog = mypwd + "/mail_idcheck.txt"
##======================================================メソッド
#-------------------------------------------------------def error message
def my_error(errMess)
puts "Error!\n" + errMess
exit#プログラム終了
end
#-------------------------------------------------------def my_exist
#########ファイル読み書き用メソッド
#ファイルの存在確認
def my_exist(filepath)
unless FileTest.exist?(filepath) then#もしなかったら
system("touch " + filepath)#ファイル作るだす
end
if !(FileTest.readable_real?(filepath)) then#読み込み不可なら
my_error("Don't Read This File.")
elsif !(FileTest.writable_real?(filepath)) then#書き込み不可なら
my_error("Don't Write This File.")
end
end
#-------------------------------------------------------def fileread
#ファイル(filepath)を読み込んで、ハッシュを返す。値の初期値はfalse
def fileread(filepath)
myhash = Hash.new
File.open(filepath, 'r') { |io|
while line = io.gets
line.chomp!#改行を削除して
myhash[line] = false#初期値はfalse
end
}
return myhash
end
#-------------------------------------------------------def
#filepathにstrを新規書き込み
def filewrite(filepath, str)
File.open(filepath, 'w') { |file|
file.puts str
}
end
#-------------------------------------------------------def
#フラグの立っているキーを文字列化
#ハッシュ(myhash)を渡されたら、tureの値を持つキーだけを集めて(falseを値にもつキーを削除して)、改行でひとかたまりの文字列にする
def hash2str(myhash)
myhash.delete_if {|key, value| value == false}
str = myhash.keys.join("\n")
return str
end
#########ここからメール送信用メソッド
#-------------------------------------------------------メールテキスト作成メソッド
def make_mail_text(subject, from, to, multipart_header, body)
# メールのテキストの作成
mail_text = <<-EndOfMail
Subject: Fwd:#{subject}
To: #{to}
From: #{from}
Content-Type: text/plain; charset='iso-2022-jp'
Content-Transfer-Encoding: 7bit
MIME-Version: 1.0
#{multipart_header}
#{Kconv::tojis(body)}
EndOfMail
return(mail_text)
end
#-------------------------------------------------------メールの送信
def send_mail(smtpserver, src, from, to)
timeout(20) do
Net::SMTP.start( smtpserver, 25 ) do |session|
session.send_mail( src, from, to )
end
end
end
#-------------------------------------------------------メールの全体からボディだけを返す
#実はここは使っていない^^参考程度に
def my_body(str)
startpoint = str.index( "\r\n\r\n" ) + 4
return str[ startpoint, str.size - startpoint ].to_s
end
#こっちでやってます
module Net
class POPMail
def body
self.all[self.header.size .. -1]
end
end
end
##======================================================メイン
my_exist(mail_idlog)
myhash = fileread(mail_idlog)
begin
Net::APOP.start(popserver, 110, accunt, passwd) {|pop|
if pop.mails.empty? then#もしメールボックスが空だったら
puts "No Mail"
else
mail_count=pop.mails.size #メール総数
puts "Receved Mail +#{mail_count}\n"
pop.each { |mmail| ##1通1通のメールの処理
mail_id=mmail.unique_id #ユニークidのゲット
if myhash.key?(mail_id) then#既読メールであった
myhash[mail_id] = true#値をセット
else #myhashにふくまれていなければ
mail_header=mmail.header#ヘッダをget
address_re = Regexp.new("From: (.*" + targetaddress + "[^\n]*)")#正規表現の生成
if mail_header =~ address_re#targetaddressに含まれていれば
mailfrom = $1
puts mailfrom#だれからのメールかをコンソールに出力
mail_header =~ /Subject: ([^\n]*)/
mailsubject = $1#Subjectの取得
#メール着信のみのお知らせか、メッセージも転送するか
if nobody then#お知らせだけなら
mail_body = "You got a Mail!\nFrom: " + mailfrom + "\nSubject: " + mailsubject
else#以下ボディ処理
mail_body = mmail.body#ボディ全体の取得
#添付ファイルの処理(大きなデータである可能性もあるので、メソッドにしない)
#ヘッダ中にmultipartがあれば取得しておく
if (mail_header =~ /^(Content-Type: multipart.+boundary=\"([^\"]+)\")/) then
multipart_header = $1 + "\n"#Content-Typeヘッダの取得
boundary = '--' + $2#区切り文字の取得
end
if !(attachments) then#添付ファイルを転送しない設定なら
multipart_header = "\n"#Content-Typeヘッダをなしに
startpoint = mail_body.index("\r\n\r\n") + 4#最初の空行までのバイト数
endpoint = mail_body.index(boundary, startpoint) -1#空行から区切り文字までのバイト数
mail_body = mail_body[startpoint .. endpoint].to_s
end
end#if nobody
# smtpでメールの送信と例外処理
begin
mail_src = make_mail_text(mailsubject, fromaddress, toaddress, multipart_header, mail_body) # メールソースの作成
send_mail(smtpserver, mail_src, fromaddress, toaddress)
rescue
my_error("send_mail\n$!")
end
myhash[mail_id] = true#キーと値をセットして既読とする
end
end #if myhash.key?(mail_id)
} #end pop.each
#既読状態のものを書き込み
str = hash2str(myhash)
filewrite(mail_idlog, str)
end # pop.mails.empty?
} #end Net::APOP
rescue
my_error($!)
end
puts "It succeeded."