Class MemoSend
In: memosend.rb
Parent: Object

Methods

Attributes

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] 

Public Class methods

memofile にメモ書きファイルを指定する。 もしもファイルが存在しない場合や読み取れない場合は終了。

[Source]

     # 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

Public Instance methods

gate_user_show コマンドを入れ替え、user_jpname を再取得する。 command には gate-user-show コマンドのパスを設定する。 プロセスの uid を用いたくない場合には uid に値を設定する。

[Source]

     # 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

メールを送信する。この際、以下のチェックを行い、適合しない場合 エラーを返して終了する。

  • user_name や user_jpname が文字である。
  • user_name が group ユーザで無い場合。
    • ただし、permit_from_group を true にしている場合は例外。
  • toaddr が空の配列でなく、且つ中に空白ではない文字列があること。

[Source]

     # 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 も 自動的に設定される。

[Source]

     # 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 を指定した場合には エラーを返す。

[Source]

     # 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

アドレスを追加する。

[Source]

     # 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

今までのアドレスをクリアし、新たにアドレスを設定する。

[Source]

     # 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

Private Instance methods

アドレスの変換を行うメソッド。addr に与えられた文字列の内、 "@" よりも前のユーザ名に相当する部分が ハッシュ addr_replace_hash のキーにヒットするものを値に入れ替える。include_domain を true にすると、ドメインまで一致しないと置換されない。

[Source]

     # 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

代入された変数が、配列で、且つゼロ配列ではないことを 調べるメソッド

[Source]

     # 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 を返す。

[Source]

     # 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 ヘッダにつける文字を返す

[Source]

     # 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 メソッドに代入された変数を出力する。

[Source]

     # File memosend.rb, line 146
146:   def debug(*args)
147:     p [caller.first, *args] if $DEBUG
148:   end

拡張子の変換を行うメソッド。filename に与えられた文字列の内、 ハッシュ ext_replace_hash のキーにヒットする拡張子を値のもの に入れ替える。

[Source]

     # 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 を与えた場合、姓のみを返そうと試みる。 データベースの和名が半角空白または全角空白で区切られる場合、 姓のみを返すことが可能である。

[Source]

     # 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

メールの本文を作成して返す

[Source]

     # 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 を返す。

[Source]

     # 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 が無効なものである場合、エラーを返す。

[Source]

     # 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

[Validate]