前回、暗号化を行った事によりバックアップの保存の目的はほぼ果たしているのですが、気持ちが悪いので添付ファイルについても考えてみました。
gmail と uuencode をキーワードに Google で検索した所、mutt を使うのが一般的らしい。
↓のように ‘-a’ キーワードで添付するファイルを指定するだけで添付ファイルとして扱ってくれます。
mutt -a name.afz -a mysql_name.afz -s "name backup `date`" to_address
複数の添付ファイルにも対応しているので、この方法で問題ないかとも思ったのですが、1つだけ問題がありました。mutt では Envelope From を引数で変更することが出来ず、muttrc/.muttrc に別途設定する必要があります。
なんかめんどくさそうな感じがしたので、結局は Ruby でフィルタプログラムを書くことにしました。
以下のような物になりました。
#!/usr/bin/env ruby
#
# sendmail.rb</p>
require 'rubygems'
require 'tmail'
require 'net/smtp'
require 'nkf'
require 'etc'
require 'socket'
require 'optparse'
def usage( status, msg = nil )
output = (status == 0 ? $stdout : $stderr)
output.puts msg if msg
output.print(<<EOS)
Usage: cat msg | #{File.basename $0} [-j|--ja] [-s <subject>] [-f <from>] <to>
-s,--subject=sbj subject of the message. (default=(none))
-f,--from=from from address.
-a,--attachment=file attachment
-j,--ja handle japanese message. (default=off)
EOS
exit status
end
def main(args)
subject = nil
from = guess_from_address()
to = []
attachments = []
ja_locale = false
OptionParser.new do |opt|
opt.banner = "Usage: #{$0} [options]"
opt.on('-s', '--subject=subj', 'subject of the message. (default=(none))') do |arg|
subject = arg
end
opt.on('-f', '--from=from', 'from address.') do | arg|
from = arg
end
opt.on('-j', '--ja', 'handle japanese message. (default=off)') do
ja_locale = true
end
opt.on('-a', '--attachment=file', 'attachment') do |arg|
attachments << arg
end
to = opt.parse!(args)
end
usage(1) if to.empty?
setup_mail(from, to, subject, $stdin.read, ja_locale, attachments)
end
def setup_mail( from, to, subject, body, ja_locale, attachments )
mail = TMail::Mail.new
mail.date = Time.now
mail.from = from
mail.to = to
mail.subject = subject if subject
mail.mime_version = '1.0'
# 本文の処理
if attachments.empty?
message = mail
else
message = TMail::Mail.new
message.transfer_encoding = '7bit'
end
if ja_locale
message.body = <span class="caps">NKF.</span>nkf('-j', body)
message.set_content_type 'text', 'plain', 'charset' => 'iso-2022-jp'
else
message.body = body
message.set_content_type 'text', 'plain'
end
# 添付ファイルの処理
unless attachments.empty?
mail.parts.push(message)
attachments.each do |filepath|
body = nil
File.open(filepath) { |f| body = f.read } rescue nil
next if body.nil?
attachment = TMail::Mail.new
filename = File.basename(filepath)
encoded_body = [body].pack('m').chomp.gsub(/.{76}/, "\\1\n")
attachment = TMail::Mail.new
attachment.body = encoded_body
attachment.transfer_encoding = 'base64'
attachment.set_content_type('application', 'octet-stream', 'name' => filename)
attachment.set_content_disposition('attachment',
'filename' => filename)
mail.parts.push(attachment)
end
mail.write_back
end
puts mail.encoded
mail
end
def guess_from_address
user = getlogin()
unless user
$stderr.puts 'cannot get user account; abort.'
exit 1
end
if domain = (Socket.gethostname || <span class="caps">ENV</span>['HOSTNAME'] || <span class="caps">ENV</span>['HOST'])
user + '@' + domain
else
user
end
end
def getlogint
begin
require 'etc'
Etc.getlogin
rescue LoadError
<span class="caps">ENV</span>['LOGNAME'] || <span class="caps">ENV</span>['USER']
end
end
main(ARGV)
TMail のサンプルの sendmail.rb をほぼそのまま使っています。
引数 ’-a’ で添付ファイルを指定出来るように変更しました。(getopts が deprecated になっていたので optparse で書き直しています。)

