| 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