#  PMail - GNOME/GTK/Python email client
#  Copyright (C) 2000 Scott Bender <sbender@harmony-ds.com>

#  This file is part of PMail.

#  PMail is free software; you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation; either version 2, or (at your option)
#  any later version.

#  PMail is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.

#  You should have received a copy of the GNU General Public License
#  along with GNU Emacs; see the file COPYING.  If not, write to
#  the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
#  Boston, MA 02111-1307, USA.  

from smtplib import *
from StringIO import StringIO
from MimeWriter import MimeWriter
import mimetypes
import mimetools
import mimify
import time
import os

import Base
import config
import util
import pmailmimify
import Plugin
from Message import Message

class NewMessage(Message):
  def __init__(self, to, cc=None, bcc=None, subject=None):
    Base.PMailObject.__init__(self, debug=100)
    Message.__init__(self)
    #self._debug = 190

    self._from = util.get_config('email_address')
    self._to = to
    self._cc = cc and cc or []
    self._bcc = bcc and bcc or []
    self._subject = subject
    self._multipart = 0
    
    self._mime_io = StringIO()
    self._writer = MimeWriter(self._mime_io)

    sio = StringIO()

    def addheader(header, val, s=sio):
      s.write('%s: %s\n' % (header, mimify.mime_encode_header(val)))

    addheader('To', string.join(to, ','))
    addheader('From', '%s <%s>' %  (util.get_config('users_name'),self._from))
    if cc and len(cc):
      addheader('CC', string.join(cc, ','))
    if subject and len(subject):
      addheader('Subject', subject)

    rt = util.get_config('reply_to')
    if len(rt):
      addheader('Reply-To', rt)

    addheader('MIME-Version', '1.0')
    addheader('X-Mailer', '%s %s' % (config.app_name, config.version))
    #addheader('X-Mailer', 'ScottBender Python Mailer %s' % config.version)    
    addheader('Date', self.rfc822_date())

    sio.seek(0)
    self._headers = rfc822.Message(sio)

    self._write_mime_headers()

  def _write_mime_headers(self):
    for hdr in self._headers.dict.items():
      key, val = hdr
      self._writer.addheader(key, val)

  def rfc822_date(self):
    return time.strftime('%a, %d %b %Y %H:%M:%S %Z',
                         time.localtime(time.time()))

  def _wrap_line(self, column, line, new_lines):
    if len(line) > column:
      cutoff = string.rfind(line[:column+1], ' ')
      if cutoff == -1: cutoff = column
      new_lines.append(line[:cutoff])
      if cutoff < len(line):
        self._wrap_line(column, line[cutoff+1:], new_lines)
    else:
      new_lines.append(line)

  def _wrap_text(self, text):
    column = util.get_config('wrap_column')
    if column:
      lines = string.split(text, '\n')
      new_lines = []
      for line in lines:
        self._wrap_line(column, line, new_lines)
      return string.join(new_lines, '\n')
    else:
      return text
                       
  def set_body(self, body):
    if not self._multipart:
      w = self._writer
    else:
      w = self._writer.nextpart()

    body = self._wrap_text(body)
    io = StringIO(body)
    oio = StringIO()
    charset, encoding = pmailmimify.mimify_part(io, oio, 0)

    if not charset:
      charset = 'us-ascii'
    if not encoding:
      extra = {}
    else:
      extra = { 'Content-Transfer-Encoding': encoding}

    s = w.startbody('text/plain', [('charset',charset)], 0,  extra)

    s.write(oio.getvalue())

  def full_body(self):
    return self.msg()

  def start_message(self, is_multipart=0):
    self._multipart = is_multipart
    self.debug('start_message, multipart: %d"' % is_multipart)
    if is_multipart:
      self._writer.startmultipartbody('mixed', None, [], 0)

  def add_attachment(self, filename):
    assert self._multipart
    self.debug('add_attachment "%s"' % filename)
    w = self._writer.nextpart()
    type = mimetypes.guess_type(filename)
    sname = os.path.split(filename)[1]
    #FIXME: should be smarter about encoding??
    encoding = 'base64'

    if not type[0]:
      type = ('text/plain',None)
    
    s =  w.startbody(type[0], [('name', sname)], 0,
                     { 'Content-Transfer-Encoding': encoding,
                       'Content-Disposition': 'attachment' })
    f = open(filename, 'r')
    mimetools.encode(f, s, encoding)
    f.close()

  def add_messsage_attachment(self, message):
    assert self._multipart
    self.debug('add_messsage_attachment "%s"' % message)
    w = self._writer.nextpart()
    s =  w.startbody('message/rfc822', [], 0,
                     { 'Content-Transfer-Encoding': '7bit',
                       'Content-Disposition': 'inline' })
    s.write(message.full_body())
 

  def msg(self):
    return self._mime_io.getvalue()

  def send(self):
    if self._multipart:
      self._writer.lastpart()
      
    self.debug('Connecting to SMTP server: %s' %
               util.get_config('smtp_server'))
    self.debug(self.msg())

    doit = 1
    if doit:
      smtp = SMTP()
      smtp.set_debuglevel(self._debug)
      smtp.connect(util.get_config('smtp_server'))
      addrs = self._to + self._cc + self._bcc
      errs = smtp.sendmail(self._from, addrs, self.msg())
      if errs:
        self.log_error('Could not send mail: %s' % errs)
      else:
        Plugin.call_plugins('new_mail_sent', (self,))
      return errs
    return []
