メール一括送信スクリプトの覚え書き
さくらインターネットのSMTPサーバーからメールを一括送信するためのスクリプト。「ruby 1.9.2p136 (2010-12-25) [i386-mingw32]」でのみ動作を確認済み。M17N絡みの不具合を避けるためにforce_encodingしていたりするので,あんまり参考にすべきコードではないかも……
#!/usr/local/bin/ruby # -*- coding: utf-8 -*- require 'kconv' require 'net/smtp' require 'time' require 'cgi' require 'csv' ################################################## ## 送信設定 ################################################## MAIL_FROM = "hoge@fuga.jp" SMTP_HOST = "fuga.sakura.ne.jp" SMTP_ACCOUNT = "hoge@fuga.sakura.ne.jp" SMTP_PASSWORD = "your_password" MAIL_FIELD = "mail" SUBJECT = "subject" BODY = Proc.new {|hash| <<END_OF_MESSAGE #{hash['name']}様 ここに本文を書く #{hash['field_name']} こうやってパラメータを展開できる -- なんちゃら END_OF_MESSAGE } ################################################## ## ここから先は変更不要 ################################################## class Mail attr_accessor :to, :from, :subject, :body def encoded # 参考: http://code.nanigac.com/source/view/108 packed = [@subject.tojis].pack('m').gsub("\n", '').gsub("\r", '') encoded_subject = "=?ISO-2022-JP?B?" + packed + "?=" header = <<END_OF_HEADER To: #{@to} From: #{@from} Mime-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Type: Text/Plain; charset=iso-2022-jp Subject: #{encoded_subject} Date: #{Time.now.rfc2822} END_OF_HEADER # 参考: http://d.hatena.ne.jp/takehikom/20091122/1258835349 (header + "\n" + @body).tojis.force_encoding("US-ASCII") end end class SendMail attr_accessor :host, :account, :password def send(mail) smtp = Net::SMTP.new(@host, 587) smtp.start('localhost.localdomain', @account, @password, :login) {|smtp| smtp.sendmail(mail.encoded, mail.from, mail.to) } end end class CSVMailer def initialize @sender = SendMail.new @sender.host = SMTP_HOST @sender.account = SMTP_ACCOUNT @sender.password = SMTP_PASSWORD @mail_from = MAIL_FROM @mail_field = MAIL_FIELD @database = [] end def load(filename) count_row = 0 headers = [] CSV.parse(File.read(filename, :mode => 'r')) do |row| count_col = 0 hash = Hash.new row.each {|elem| if count_row == 0 then headers << elem else hash[ headers[count_col] ] = elem end count_col += 1 } if count_row != 0 then @database << hash end count_row += 1 end end def sendmail(subject, &block) @database.each {|hash| puts("sending: #{hash[@mail_field]}") mail = Mail.new mail.subject = subject mail.from = @mail_from mail.to = hash[@mail_field] mail.body = block.call(hash) @sender.send(mail) } end end instance = CSVMailer.new instance.load(ARGV.shift) instance.sendmail(SUBJECT, &BODY)
読み込ませるCSVとしては次のようなものを用意する。
name,mail,field_name おなまえ,foo@bar.jp,パラメータ おなまえ,foo@baz.jp,パラメータ