한메일 다운로드 스크립트(루비 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:


댓글 달기