2011年8月14日日曜日

Sending Emails from CSV/TSV Formatted Data through Gmail SMTP by Ruby

A Japanese version of this document is in TechRacho. I want to send e-mails to my students from my Excel-formatted list. I don't have any SMTP servers so that I use Gmail SMTP. The advantage of this program is:
  • Email from your tabular data (Excel, CSV, TSV, etc.)
  • Using Gmail SMTP (you don't worry whether your server is in spam blacklists)
  • Customizable mail template, no Ads
This program is verified on Ruby 1.8.7 + ActionMailer 3.0.3 + fastercsv 1.5.4 + tlsmail 0.0.1.

Install Required Gems

First of all, install gems.
$ gem install rails
$ gem install fastercsv
$ gem install tlsmail

Convert List of Data

Then, you have to convert your tabular data to TSV(because CSV might cause some troubles in parsing especially multibyte data). If you use Japanese (or other multibyte encoded language), convert it to UTF-8. For example, Excel's default output encoding in Japanese is MS932(Shift-JIS), We use NKF(Nihongo Kanji Filter) to convert it.
$ brew install nkf
$ nkf -w data.tsv > data-utf8.tsv

Program and Setup

Save below source code as send_email.rb:
# encoding: UTF-8
require 'rubygems'
require 'action_mailer'
require 'fastercsv'

# for Gmail SMTP
require 'tlsmail'
if ARGV.count != 2
  puts "usage: ruby send_email.rb [Gmail Account] [Gmail Password] < TSV"
  exit -1
end

Net::SMTP.enable_tls(OpenSSL::SSL::VERIFY_NONE)
ActionMailer::Base.delivery_method = :smtp
ActionMailer::Base.perform_deliveries = true
ActionMailer::Base.raise_delivery_errors = true
ActionMailer::Base.smtp_settings = {
   :enable_starttls_auto => true,
   :address        => 'smtp.gmail.com',
   :port           => 587,
   :domain         => 'gmail.com',
   :authentication => :plain,
   :user_name      => ARGV[0],
   :password       => ARGV[1]
}

class CustomMailer < ActionMailer::Base
    def createMessage(toAddress, mySubject, myBody)
        from 'your_email_address@your_domain.com'
        recipients toAddress
        subject mySubject
        body myBody
    end
end

FasterCSV.parse(
  STDIN.read(100000000).to_s,
  :col_sep => "\t",
  :headers => %w(email name a b c d e f g your file format here)
) do |h|
  to = h['email']
  body =<<EOS
Dear #{h['name']},

Some message.

If you want to insert TSV parameter, write #{h['header_name']}.

-- 
Signatures

EOS
  puts to
  puts body
  CustomMailer.createMessage([to, "your_email_address@your_domain.com"], "Subject  for #{h['name']}", body).deliver
end
Please replace highlighted lines. Line 29: The email address in the from header. If you don't want to use your gmail address, you must setup to enable the address before (Details here). Line 39: ":headers" is key strings for your tabular data. For example, the data is formatted by [email, name] like below:
hoge@example.com Hoge
huga@example.com Huga
foo@example.com  Foo
Then you can refer them by h['email'] or h['name'] below:
  :headers => %w(email name)
Line 43-51: Mail body Line 55: If he first argument is array, you can use multiple TO addresses. The second argument is a subject.

Sending Email

If you are ready, execute below command in your terminal.
$ ruby send_email.rb 'GMAIL_ACCOUNT@gmail.com' 'PASSWORD' < data-utf8.tsv
The Gmail SMTP is not so fast SMTP, the sending rate is about 10 mails/a minute.

0 件のコメント:

コメントを投稿