前回、暗号化を行った事によりバックアップの保存の目的はほぼ果たしているのですが、気持ちが悪いので添付ファイルについても考えてみました。
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 で書き直しています。)