Message.py
上传用户:gyjinxi
上传日期:2007-01-04
资源大小:159k
文件大小:5k
源码类别:

WEB邮件程序

开发平台:

Python

  1. try: import locale; locale.setlocale(locale.LC_ALL,"")
  2. except: pass
  3. import mimetools, mimify, re, multifile, base64, string, time
  4. try: from cStringIO import StringIO
  5. except: from StringIO import StringIO
  6. mime_head_quopri = re.compile('=\?iso-8859-[12]\?q\?([^? tn]+)\?=', re.I)
  7. mime_head_base64 = re.compile('=\?iso-8859-[12]\?b\?([^? tn]+)\?=', re.I)
  8. def mime_decode(line, isBase64=0):
  9.         if isBase64: return base64.decodestring(line)
  10.         else: return mimify.mime_decode(line)
  11. # mimify.mime_decode_header only decodes quoted printable
  12. # this one also handles base64 encoded headers
  13. def mime_decode_header(line):
  14.         '''Decode a header line to 8bit.'''
  15.         newline = ''
  16.         pos = 0
  17.         while 1:
  18.                 res = mime_head_quopri.search(line, pos)
  19.                 if res is None:
  20.                         res = mime_head_base64.search(line, pos)
  21.                         if res is None: break
  22.                         else: isBase64 = 1
  23.                 else: isBase64 = 0
  24.                 match = res.group(1)
  25.                 # convert underscores to spaces (before =XX conversion!)
  26.                 match = string.join(string.split(match, '_'), ' ')
  27.                 newline = newline + line[pos:res.start(0)] + mime_decode(match, isBase64)
  28.                 pos = res.end(0)
  29. return newline + line[pos:]
  30. class Message(mimetools.Message):
  31.     """A real MIME-message class :-)
  32.     Handles multipart messages and 
  33.     helps decoding parts as well as headers.
  34.     Disadvantage: slow on long mails :-(
  35.     """
  36.     
  37.     def __init__(self, fp, preview=0):
  38.             mimetools.Message.__init__(self, fp)
  39.             self.body = ""
  40.             self.parts = []
  41.             self.encoding = self.getencoding()
  42.             self.boundary = self.getparam("boundary")
  43.             disp = self.getheader("content-disposition") or ""
  44.             f = string.find(disp, 'filename="')
  45.             if f <> -1: #XXX VERY BAD HACK!!!
  46.                     self.filename = disp[f+10:string.find(disp, '"', f+10)]
  47.             else:
  48.                     self.filename = None
  49.             self.parsed = 0
  50.             self.processHeaders()
  51.             if not preview: self.parse()
  52.     
  53.     def processHeaders(self):
  54.             self.Lines = self["Lines"]
  55.             if self.Lines: self.Lines = int(self.Lines)
  56.             self.Subject = self["Subject"]
  57.             self.FromName, self.FromAddr = self.getaddr("From")
  58.             self.Sender = "%s <%s>" % (self.FromName, self.FromAddr)
  59.             self.ReplyToName, self.ReplyToAddr = self.getaddr("Reply-To")
  60.             self.ToName, self.ToAddr = self.getaddr("To")
  61.             self.CcName, self.CcAddr = self.getaddr("Cc")
  62.             self.BccName, self.BccAddr = self.getaddr("Bcc")
  63.             self.UserAgent = self["X-Mailer"] or self["User-Agent"]
  64.             self.Date = self.getdate("Date")
  65.             if self.Date:
  66.                     self.DateStr = time.strftime(
  67.                             "%a, %d. %b %Yn %H:%M", self.Date)
  68.                     self.DateShortStr = time.strftime("%D %T", self.Date)
  69.             else:
  70.                     self.DateStr = self.DateShortStr = "(no date)"
  71.     def parse(self):
  72.         if self.parsed: return
  73.         self.rewindbody()
  74.         if self.boundary:
  75.                 mf = multifile.MultiFile(self.fp)
  76.                 mf.push(self.boundary)
  77.                 while mf.next():
  78.                         self.parts.append(Message(mf))
  79.                 mf.pop()
  80.         else:
  81.                 self.body = self.fp.read()
  82.                 self.parsed = 1
  83.     def decode(self):
  84.             if self.encoding in ['7bit', '8bit']:
  85.                     return self.body
  86.             try:
  87.                     self.rewindbody()
  88.                     out = StringIO()
  89.                     mimetools.decode(StringIO(self.body), out, self.encoding)
  90.                     return out.getvalue()
  91.             except:
  92.                     raise ValueError, "MIME part decoding failed"
  93.             
  94.     def getheader(self, name, default=None):
  95.             header = mimetools.Message.getheader(self, name, default)
  96.             if header:
  97.                     return mime_decode_header(header)
  98.     def getaddr(self, name):
  99.             name, addr = mimetools.Message.getaddr(self, name)
  100.             if name: return mime_decode_header(name), addr
  101.             else: return name, addr
  102.             
  103.     def getdate(self, name):
  104.             try: return mimetools.Message.getdate(self, name)
  105.             except: pass
  106.     
  107.     def __getitem__(self, name):
  108.         return self.getheader(name)
  109.     
  110.     def __str__(self):
  111. # rebuild the message
  112.         f = StringIO()
  113.         f.write('%sn' % string.join(
  114.             map(mimify.mime_encode_header, self.headers), ''))
  115.         if self.parts: # multipart message
  116.             for p in self.parts:
  117.                 f.write('n--%sn' % self.boundary)
  118.                 f.write(str(p))
  119.             f.write('n--%s--n' % self.boundary)
  120.         else:
  121.             f.write(self.body or "")
  122.         return f.getvalue()