Class | MemoSend |
In: |
memosend.rb
|
Parent: | Object |
addr_replace_hash | [RW] | |
domain | [R] | |
ext_replace_hash | [RW] | |
from | [RW] | |
gate_user_show | [R] | |
mail_src | [R] | |
memofile | [R] | |
message | [RW] | |
permit_from_group | [RW] | |
replaced_from | [R] | |
smtp_port | [RW] | |
smtp_server | [RW] | |
subject | [RW] | |
toaddr | [R] | |
uid | [R] | |
url | [RW] | |
user_jpname | [RW] | |
user_name | [RW] |
memofile にメモ書きファイルを指定する。 もしもファイルが存在しない場合や読み取れない場合は終了。
# File memosend.rb, line 93 93: def initialize(memofile) 94: @memofile = memofile # メモ書きファイル 95: 96: # memofile に関するエラー処理 97: if !(memofile.instance_of?(String)) then 98: raise ArgumentError, "Error: file is not specified. \n" 99: elsif !(File.exist?(memofile)) then 100: raise ArgumentError, "Error: \"#{memofile}\" is not found. \n" 101: elsif !(File.readable?(memofile)) then 102: raise ArgumentError, "Error: \"#{memofile}\" is not readable. \n" 103: end 104: 105: # 106: # 各種の送信の設定値 107: # 108: @smtp_server = "localhost" # SMTP サーバ 109: @smtp_port = 25 # SMTP ポート 110: @domain = "gfd-dennou.org" # メールの送付元ドメイン 111: @gate_user_show = "/usr/local/bin/gate-user-show" # gate コマンドのパス 112: 113: debug(@smtp_server, @smtp_port, @domain) 114: debug(@gate_user_show) 115: 116: @uid = Process.uid # UID 117: @user_name = username_from_uid(@uid) # ユーザ名 118: @user_jpname = jpname_from_uid(@uid, true) || @user_name 119: # ユーザ(日本語) 120: debug(@uid, @user_name, @user_jpname) 121: 122: @from = @user_name + "@" + @domain # 送信元メールアドレス 123: @replaced_from = @from # 置き換え用 from 124: @toaddr = [@from] # 送信先メールアドレス 125: 126: @addr_replace_hash = Hash.new # アドレス変換エントリ 127: 128: @permit_from_group = false # グループからの投稿許可 129: 130: # 131: # メール本文に関するの設定値 132: # 133: @subject = "[MemoSend] Test Post" # Subject のヘッダ 134: @message = "This is Test mail by memosend.rb" # メッセージ 135: @url = "http://www.gfd-dennou.org/arch/dcmodel/bin" # URL 136: 137: @ext_replace_hash = Hash.new # ファイル名拡張子変換エントリ 138: 139: end
gate_user_show コマンドを入れ替え、user_jpname を再取得する。 command には gate-user-show コマンドのパスを設定する。 プロセスの uid を用いたくない場合には uid に値を設定する。
# File memosend.rb, line 189 189: def gate_user_show_replace(command=nil, uid=nil) 190: return nil unless str_and_notspace?(command) 191: 192: @gate_user_show = command 193: @user_jpname = jpname_from_uid(nil, true) || @user_name 194: return true 195: end
メールを送信する。この際、以下のチェックを行い、適合しない場合 エラーを返して終了する。
# File memosend.rb, line 250 250: def send 251: 252: # 253: # チェック項目 254: # 255: 256: # * user_name や user_jpname が文字である事をチェック 257: if !(str_and_notspace?(@user_name)) then 258: raise ArgumentError, "Error: user_name is invalid. \n" 259: elsif !(str_and_notspace?(@user_jpname)) then 260: raise ArgumentError, "Error: user_jpname is invalid. \n" 261: end 262: 263: # * user_name が group ユーザで無いことをチェック 264: if !@permit_from_group && check_group_user(@uid) then 265: error_msg = "Error: Now your UID is group user.\n" 266: error_msg << " Please exit and retry, \n" 267: error_msg << " or set \"permit_from_group = true\".\n" 268: error_msg << " (In this case, mail is sent to group by default.)\n" 269: raise ArgumentError, error_msg 270: end 271: 272: # * toaddr が空の配列でなく、且つ中に空白ではない文字列があること。 273: if !array_and_notzero?(@toaddr) then 274: raise ArgumentError, "Error : Invalid addresses.\n" 275: end 276: @toaddr.each{|to| 277: if !str_and_notspace?(to) then 278: raise ArgumentError, "Error : Invalid addresses.\n" 279: end 280: } 281: 282: # 283: # アドレスの置換 284: # 285: @replaced_from = addr_replace(@from) 286: debug(@replaced_from) 287: 288: # 289: # メール本文の作成 290: # 291: @mail_src = make_mail_entire 292: 293: Net::SMTP.start( @smtp_server, @smtp_port ) {|smtp| 294: @toaddr.each{|to| 295: debug(@replaced_from, to) 296: smtp.send_mail(@mail_src, @replaced_from, to) 297: } 298: } 299: 300: print "mail send successfull. (from #{@replaced_from})\n" 301: @toaddr.each{|addr| 302: print " to #{addr} \n" 303: } 304: 305: end
ドメインを明示的に指定する。それにより、from も 自動的に設定される。
# File memosend.rb, line 174 174: def set_domain(domain=nil) 175: return nil unless str_and_notspace?(domain) 176: 177: @domain = domain 178: @from = @user_name + "@" + @domain # 送信元メールアドレス 179: 180: return true 181: end
uid を明示的に指定する。それにより、user_name と user_jpname 、 および from が自動的に設定される。無効な UID を指定した場合には エラーを返す。
# File memosend.rb, line 157 157: def set_uid(uid=nil) 158: return nil unless uid 159: 160: @uid = uid 161: @user_name = username_from_uid(@uid) # ユーザ名 162: @user_jpname = jpname_from_uid(@uid, true) || @user_name 163: # ユーザ名 (日本語) 164: @from = @user_name + "@" + @domain # 送信元メールアドレス 165: 166: debug(@uid, @user_name, @user_jpname, @from) 167: return true 168: end
アドレスを追加する。
# File memosend.rb, line 201 201: def to_addr(*addrs) 202: addrs.flatten! # 配列の平滑化 (1次元配列化) 203: addrs.delete_if{|dir| !dir.instance_of?(String)} # 文字列でないものは削除 204: addrs.collect!{|dir| dir = dir.strip} # 前後の空白を除く 205: addrs.uniq! # 重複を無くす 206: 207: @toaddr.push(addrs) 208: 209: @toaddr.flatten! # 配列の平滑化 (1次元配列化) 210: @toaddr.delete_if{|dir| !dir.instance_of?(String)} # 文字列でないものは削除 211: @toaddr.collect!{|dir| dir = dir.strip} # 前後の空白を除く 212: @toaddr.uniq! # 重複を無くす 213: 214: debug(@toaddr) 215: end
今までのアドレスをクリアし、新たにアドレスを設定する。
# File memosend.rb, line 220 220: def to_addr_clear(*addrs) 221: addrs.flatten! # 配列の平滑化 (1次元配列化) 222: addrs.delete_if{|dir| !dir.instance_of?(String)} # 文字列でないものは削除 223: addrs.collect!{|dir| dir = dir.strip} # 前後の空白を除く 224: addrs.uniq! # 重複を無くす 225: 226: if (addrs.size > 0) 227: @toaddr = Array.new 228: @toaddr.push(addrs) 229: 230: @toaddr.flatten! # 配列の平滑化 (1次元配列化) 231: @toaddr.delete_if{|dir| !dir.instance_of?(String)} # 文字列でないものは削除 232: @toaddr.collect!{|dir| dir = dir.strip} # 前後の空白を除く 233: @toaddr.uniq! # 重複を無くす 234: end 235: 236: debug(@toaddr) 237: end
アドレスの変換を行うメソッド。addr に与えられた文字列の内、 "@" よりも前のユーザ名に相当する部分が ハッシュ addr_replace_hash のキーにヒットするものを値に入れ替える。include_domain を true にすると、ドメインまで一致しないと置換されない。
# File memosend.rb, line 427 427: def addr_replace(addr=nil, include_domain=nil) 428: return nil unless str_and_notspace?(addr) 429: debug(addr, include_domain) 430: 431: replaced = addr 432: 433: if !include_domain then 434: check_addr = addr.split(/@/)[0] 435: else 436: check_addr = addr 437: end 438: 439: debug(@addr_replace_hash) 440: @addr_replace_hash.each{|key, value| 441: if /^#{key}@*.*$/ =~ check_addr.chomp.strip then 442: replaced = value 443: else 444: replaced = addr 445: end 446: } 447: 448: debug(replaced) 449: return replaced 450: end
代入された変数が、配列で、且つゼロ配列ではないことを 調べるメソッド
# File memosend.rb, line 479 479: def array_and_notzero?(obj) 480: debug(obj) 481: 482: if obj.instance_of?(Array) && obj.size > 0 then 483: return true 484: else 485: return false 486: end 487: 488: end
引数 uid に対応するユーザ名がグループユーザ (その GID に他のユーザ を含むユーザ) であるかどうかを確かめるメソッド。 uid に nil を入れる場合にはプロセスの UID のユーザを探査する。
グループユーザである場合は true を、そうでない場合は false を返す。
# File memosend.rb, line 314 314: def check_group_user(uid=nil) 315: unless uid 316: current_uid = Process.uid 317: else 318: current_uid = uid 319: end 320: 321: memberlist = Etc.getgrgid(uid).mem 322: 323: if array_and_notzero?(memberlist) then 324: return true 325: else 326: return false 327: end 328: end
mew の形式の Date ヘッダにつける文字を返す
# File memosend.rb, line 396 396: def date_mewform 397: date_mewform = Time.new 398: return date_mewform.strftime("%a, %d %b %Y %H:%M:%S %z (%Z)") 399: end
デバッグ出力用メソッド。組み込み関数 $DEBUG が真の場合 (つまり、 プログラムを $ ruby -d ./xxxxxx.rb として呼び出した場合) に debug メソッドに代入された変数を出力する。
# File memosend.rb, line 146 146: def debug(*args) 147: p [caller.first, *args] if $DEBUG 148: end
拡張子の変換を行うメソッド。filename に与えられた文字列の内、 ハッシュ ext_replace_hash のキーにヒットする拡張子を値のもの に入れ替える。
# File memosend.rb, line 407 407: def ext_replace(filename) 408: return nil unless str_and_notspace?(filename) 409: 410: aftername = filename 411: @ext_replace_hash.each{|key, value| 412: if /^(.*)\.#{key}$/ =~ filename then 413: aftername = $1 + ".#{value}" 414: end 415: } 416: 417: return aftername 418: end
引数 uid に対応するユーザ名 (日本語) を返す。 uid に nil を与えた場合はプロセスの uid に対応するユーザ名 (日本語) を返す。
日本語名は gate-toroku-system <www.ep.sci.hokudai.ac.jp/~gate> によるデータベースから取得するため、このシステムがインストールされて いない場合には nil を返す。
引数 family_name に true を与えた場合、姓のみを返そうと試みる。 データベースの和名が半角空白または全角空白で区切られる場合、 姓のみを返すことが可能である。
# File memosend.rb, line 362 362: def jpname_from_uid(uid=nil, family_name=true) 363: if FileTest.executable?(@gate_user_show) 364: gate_user_database = IO.popen("#{@gate_user_show} #{@user_name}") 365: 366: # 367: # 以下は、完全に gate-toroku-system のデータベース依存である。 368: # 詳しくは <http://www.ep.sci.hokudai.ac.jp/~gate/doc/gate-user-db.htm> 369: # を参照せよ。 370: # 371: while gate_user_data = gate_user_database.gets do 372: gate_user_data.chomp! 373: if /^kname/ =~ gate_user_data 374: jpname_key, jpname_value = gate_user_data.split(/: /, 2) 375: Kconv::toeuc(jpname_value) 376: end 377: # 名字だけ取り出そうと試みる。 378: # (姓名の間に半角空白または全角空白が無い時は無理) 379: if family_name && /(.+)[\s| ]+.+/e =~ jpname_value then 380: jpname = $1 381: else 382: jpname = jpname_value 383: end 384: end 385: else 386: jpname = nil 387: end 388: 389: return jpname 390: end
メールの本文を作成して返す
# File memosend.rb, line 494 494: def make_mail_entire 495: 496: # 複数の to を文字に 497: mail_head_toaddr = "To: " 498: tofirst = true 499: @toaddr.each{|to| 500: mail_head_toaddr << "," unless tofirst 501: mail_head_toaddr << " #{to}" 502: tofirst = false 503: } 504: mail_head_toaddr << "\n" 505: 506: # 507: # ヘッダ作成 508: # 509: mail_head = "" 510: mail_head << "Subject: #{@subject} (#{Date::today})\n" 511: mail_head << "From: #{@replaced_from}\n" 512: mail_head << mail_head_toaddr 513: mail_head << "Date: #{date_mewform}\n" 514: mail_head << "X-Sender: "+ "memosend.rb\n" 515: mail_head << "Content-Type: Text/Plain; charset=iso-2022-jp\n" 516: mail_head << "Content-Transfer-Encoding: 7bit\n" 517: 518: debug(mail_head) 519: 520: # 521: # BODY イントロ 522: # 523: mail_body_intro = "" # ヘッダとの間の空白 (重要) 524: mail_body_intro = "\#{@user_jpname}\244\307\244\271\n\n\#{@message}\n\nURL: \#{@url}/\#{ext_replace(@memofile)}\n\n" 525: 526: # 527: # BODY 全体の作成 528: # 529: mail_body = "" 530: mail_body = open("#{@memofile}"){|io| io.read} 531: 532: mail_entire = mail_head + "\n" + mail_body_intro + "\n" + mail_body 533: 534: return Kconv::tojis(mail_entire) 535: end
代入された変数が、文字列で、且つ空白文字のみではないことを 調べるメソッド。日本語であっても、文字列が入っていれば true を返す。
# File memosend.rb, line 457 457: def str_and_notspace?(obj) 458: debug(obj) 459: 460: if !obj.instance_of?(String) then 461: return false 462: end 463: 464: # 日本語の文字列も対応できるように 465: Kconv::toeuc(obj) 466: 467: if /\w+/e =~ obj.chomp.strip then 468: return true 469: else 470: return false 471: end 472: end
引数 uid に対応するユーザ名 (ログイン名) を返す。 uid に nil を与えた場合はプロセスの uid に対応するユーザ名 (ログイン名) を返す。uid が無効なものである場合、エラーを返す。
# File memosend.rb, line 337 337: def username_from_uid(uid=nil) 338: unless uid 339: pw = Etc.getpwuid(Process.uid) or return nil 340: else 341: pw = Etc.getpwuid(uid) or return nil 342: end 343: 344: user_name = pw.name 345: return user_name 346: end