Rubyでマルチスレッドを使い、メール送信できるクライアントを作成する。
【条件】
・送信元アドレスは1つ
・受信アドレスは複数
※この受信アドレス宛に一斉にメールを送りたいわけである。
下記がコードである。
短いので説明するより見てもらえば分かるだろう。
クラス名として使っているAmailのAはAsynchronous(非同期)の頭文字である。
#!/usr/bin/ruby require "net/smtp" require 'time' require 'timeout' require 'thread' Thread.abort_on_exception = true $from = 'fromアドレス' class Amail def initialize(mta) @mta = mta @rcpts = Array.new @rcpts.push('rcpt_user1@example.com') @rcpts.push('rcpt_user2@example.com') @rcpts.push('rcpt_user3@example.com') @rcpts.push('rcpt_user4@example.com') @rcpts.push('rcpt_user5@example.com') @max_threads = 10 @num_thread = 0 @mutex = Mutex.new @cond = ConditionVariable.new @threads = Array.new end def get() while @rcpts.length != 0 do multi() end for i in 1..@threads.length @threads[i-1].join end end def multi() @threads << Thread.new(@rcpts.shift) do |rcpt| sendmail = Sendmail.new(rcpt, @mta) @mutex.synchronize do while @num_thread == @max_threads @cond.wait(@mutex) end @num_thread += 1 end begin sendmail.run() ensure @mutex.synchronize do @num_thread -= 1 @cond.signal end end end end end class Sendmail def initialize(rcpt, mta) @rcpt = rcpt @mta = mta @timeout = 10 content() end def content() @content = <<EOF From: #{$from} To: #{@rcpt} Subject: TEST FULLMESH Date: #{Time.now.rfc2822} #{$from} #{@rcpt} test fullmesh EOF end def run() begin @t0 = Time.now timeout(@timeout) do Net::SMTP.start(@mta, 25) do | smtp | smtp.send_mail @content, $from, @rcpt end end @t1 = Time.new printf("OK time:%f " ,@t1-@t0) print("mta:#{@mta} from:#{$from} to:#{@rcpt}\n") rescue StandardError, Timeout::Error => ex print("NG: mta:#{@mta} from:#{$from} to:#{@rcpt} #{ex}\n") exit 2 end end end amail = Amail.new('example.comのMX') amail.get()
スレッドパターン以前の並行処理プログラミングの基礎はここを参考してほしい。