한메일 다운로드 스크립트(루비 Ver.)
글쓴이: 158cm / 작성시간: 일, 2005/06/05 - 1:42오후
주석도 없고, 형편없는 코드지만..
이 프로그램은 한메일 계정에서 메일을 받아서 내용을 UTF8으로
변경하고 저장하는.. 루비로 작성된 스크립트입니다.
** Mailbox 형식의 메일함을 사용합니다.
필요한 모듈은 tmail(http://www.loveruby.net/ja/prog/tmail.html)입니다.
행복하세요~~. 이상.
#!/usr/bin/env ruby $KCODE = 'U' require 'net/https' Net::HTTP.version_1_2 require 'tmail/mail' require 'iconv' class HTTPConnection def initialize @header = {} @cookie = {} end def update_header @header['Cookie'] = '' @cookie.each { |k, v| @header['Cookie'] << "#{k}=#{v}; " } end def update_cookie(set_cookie) set_cookie.split('; ').each { |str| if str =~ %r{^.*, [^=]+=} then str.gsub!(%r{^.*, }, '') end e = str.split('=') @cookie.update({ e[0] => e[1] }) } self.update_header() end def get(url) uri = URI::parse(url.strip) uri.path = '/' if uri.path.empty? uri.path << "?#{uri.query}" if uri.query conn = Net::HTTP.new(uri.host, uri.port) conn.use_ssl = uri.scheme == "https" ? true : false response = conn.get2(uri.path, @header) update_cookie(response['set-cookie']) if response.key?('set-cookie') self.get($1) if response.body =~ %r{<META http-equiv="refresh" content="\d; ?url=([^"]+)">}i case response when Net::HTTPOK return response.body when Net::HTTPFound self.get("#{response['location']}") end end end class String def to_utf8(from) begin retval = Iconv.open('UTF-8', from.to_s.upcase) { |obj| obj.iconv(self) } rescue Iconv::IllegalSequence => err return nil end retval end end class Filter def initialize(regexp, header, action, priority=1) @regexp = Regexp.new(regexp) @header = header @act = action @priority = priority end attr_reader :act, :priority def compare(letter) true if @regexp.match(letter[@header].to_s) letter.parts { |part| true if @regexp.match(part[@header].to_s) } if letter.multipart? false end class << Filter def execution(act, letter) letter.send :"#{act}" end end end class Letter def initialize(reference) @baseurl = reference.base_url @identity = reference.cur_letter @inbox = reference.cur_inbox @remove = reference.remove @letter = TMail::Mail.parse(reference.fetch.call(@identity, @inbox)) self.to_utf8 if $utf8 end attr_reader :letter def remove @remove.call(@identity, @inbox) end def to_utf8_header(letter) letter.each_header { |hdr, val| if val.to_s =~ %r{=\?([\w_-]+)\?(\w)\?(.*)\?=} charset = $1; encoded = $2; str = $3 next if charset =~ %r{utf-8}i decoded = case encoded when /B/i str.unpack('m') when /Q/i str.unpack('M') end utf8_str = decoded.to_s.to_utf8(charset).strip next if utf8_str.nil? letter[hdr] = "=?UTF-8?B?#{utf8_str.to_a.pack('m').delete("\n")}?=" else utf8_str = letter[hdr].to_s.to_utf8(letter.type_param('charset', 'EUCKR')) next if utf8_str.nil? letter[hdr] = "#{utf8_str.strip}" end } end def to_utf8_body(letter) return if not letter.main_type =~ %r{text}i utf8_str = letter.body_port.ropen.read_all.to_utf8(letter.type_param('charset', 'EUCKR')) utf8_str.gsub!(%r{^(.*)<!--.*}im, '\1') if letter.sub_type =~ %r{html}i and @letter['X-Mailer'].to_s =~ %r{Daum Web Mailer}i utf8_str.gsub!(%r{(?<=<META)(.*charset=)[A-Z0-9\-_]+}im, '\1utf-8') if letter.sub_type =~ %r{html}i letter.body_port.wopen { |f| f.write(utf8_str) } letter.set_content_type(letter.main_type, letter.sub_type, {'charset'=>'utf-8'}) end def to_utf8 self.to_utf8_header(@letter) if @letter.multipart? letters = @letter.parts letters.each { |l| self.to_utf8_header(l) self.to_utf8_body(l) } else self.to_utf8_body(@letter) end end def to_disk begin fname = "#{$maildir}/new/#{Time.now.to_i}.M#{Time.now.usec}.#{`hostname`}".chomp f = File.new(fname, File::CREAT|File::TRUNC|File::RDWR, 0600) f.write(@letter.to_s) rescue File.delete(fname) ensure f.close if f self.remove end end end class DAUM def initialize(connection, uid, pwd) @conn = connection @letters = [] configure = Struct.new("CONFIGURE", :base_url, :cur_letter, :cur_inbox, :inboxs, :fetch, :remove) #base_url = 자신의 계정이 있는 호스트의 이름.. -_-; @reference = configure.new('http://wwl536.daum.net/Mail-bin/', '', '', { 'INBOX' => '%B9%DE%C0%BA%C6%ED%C1%F6%BA%B8%B0%FC%C7%D4', 'TRASH' => '%C8%DE%C1%F6%C5%EB' }, self.fetch_letter, self.remove_letter) self.login(uid, pwd) end attr_reader :reference, :letters def login(uid, pwd) @conn.get("https://logins.daum.net/Mail-bin/login.cgi?id=#{uid}&pw=#{pwd}&checkip=") @conn.get("#{@reference.base_url}mail_left.cgi") end def fetch_list @letters.clear unless @letters.empty? @reference.cur_inbox = @reference.inboxs['INBOX'] pnum = 1 end_of_page = true loop { end_of_page = true @conn.get("#{@reference.base_url}mail_list?FOLDER=#{@reference.cur_inbox}&mpage=#{pnum}").to_s.scan(/(?<=CHECKID" value=")[\w\d]+/) { |identity| end_of_page = false @reference.cur_letter = identity @letters << Letter.new(@reference) } break if end_of_page pnum += 1 } @reference.cur_letter = '' @reference.cur_inbox = '' end def fetch_letter Proc.new { |letter, inbox| str = @conn.get("#{@reference.base_url}view_mail?MSGID=#{letter}&FOLDER=#{inbox}") str =~ %r{href="([^\"]+download)}m @conn.get($1).each_line { |l| str << l.delete("\r") } } end def remove_letter Proc.new { |letter, inbox| @conn.get("#{@reference.base_url}mail_manage?ORGFOLDER=#{inbox}&FOLDER=#{inbox}&CHECKID=#{letter}&HOWTO=delete") } end def empty_trash @conn.get("#{@reference.base_url}mail_manage?HOWTO=empty&ORGFOLDER=#{@reference.inboxs['TRASH']}") end end Process.daemon #아이디 uid = '' #비밀번호 pwd = '' $utf8 = true $maildir = ENV['MAIL'] $filters = [] daum = DAUM.new(HTTPConnection.new, uid, pwd) loop { count = 0 daum.fetch_list daum.letters.each { |l| count += 1 act = 'to_disk' unless $filters.empty? f = $filters.select { |f| f.compare(l.letter) } if f.length == 1 act = f[0].act elsif f.length > 1 t = f.max { |n, m| n.priority <=> m.priority } act = t.act end end Filter.execution(act, l) } daum.empty_trash if count sleep(1200) }
Forums:
댓글 달기