#!/usr/bin/python

# Copyright 2011 Google Inc. All Rights Reserved.

from email import Encoders
from email.MIMEBase import MIMEBase
from email.MIMEMultipart import MIMEMultipart
from email.MIMEText import MIMEText
import getpass
import os
import smtplib
import sys
import tempfile

from utils import command_executer

class EmailSender(object):
  class Attachment(object):
    def __init__(self, name, content):
      self.name = name
      self.content = content

  def SendEmail(self,
                email_to,
                subject,
                text_to_send,
                email_cc=None,
                email_bcc=None,
                email_from=None,
                msg_type="plain",
                attachments=None):
    """Choose appropriate email method and call it."""
    if os.path.exists("/usr/bin/sendgmr"):
        self.SendGMREmail(email_to, subject, text_to_send, email_cc, email_bcc,
                          email_from, msg_type, attachments)
    else:
        self.SendSMTPEmail(email_to, subject, text_to_send, email_cc, email_bcc,
                           email_from, msg_type, attachments)

  def SendSMTPEmail(self,
                    email_to,
                    subject,
                    text_to_send,
                    email_cc,
                    email_bcc,
                    email_from,
                    msg_type,
                    attachments):
    """Send email via standard smtp mail."""
    # Email summary to the current user.
    msg = MIMEMultipart()

    if not email_from:
      email_from = os.path.basename(__file__)

    msg["To"] = ",".join(email_to)
    msg["Subject"] = subject

    if email_from:
      msg["From"] = email_from
    if email_cc:
      msg["CC"] = ",".join(email_cc)
      email_to += email_cc
    if email_bcc:
      msg["BCC"] = ",".join(email_bcc)
      email_to += email_bcc

    msg.attach(MIMEText(text_to_send, msg_type))
    if attachments:
      for attachment in attachments:
        part = MIMEBase("application", "octet-stream")
        part.set_payload(attachment.content)
        Encoders.encode_base64(part)
        part.add_header("Content-Disposition", "attachment; filename=\"%s\"" %
                        attachment.name)
        msg.attach(part)

    # Send the message via our own SMTP server, but don't include the
    # envelope header.
    s = smtplib.SMTP("localhost")
    s.sendmail(email_from, email_to, msg.as_string())
    s.quit()

  def SendGMREmail(self,
                   email_to,
                   subject,
                   text_to_send,
                   email_cc,
                   email_bcc,
                   email_from,
                   msg_type,
                   attachments):
    """Send email via sendgmr program."""
    ce = command_executer.GetCommandExecuter(log_level="none")

    if not email_from:
      email_from = os.path.basename(__file__)

    to_list = ",".join(email_to)

    if not text_to_send:
        text_to_send = "Empty message body."
    body_fd, body_filename = tempfile.mkstemp()

    try:
      os.write(body_fd, text_to_send)
      os.close(body_fd)
      to_be_deleted = [body_filename]

      # Fix single-quotes inside the subject. In bash, to escape a single quote
      # (e.g 'don't') you need to replace it with '\'' (e.g. 'don'\''t'). To
      # make Python read the backslash as a backslash rather than an escape
      # character, you need to double it. So...
      subject = subject.replace("'", "'\\''")

      if msg_type == "html":
        command = ("sendgmr --to='%s' --subject='%s' --html_file='%s' "
                   "--body_file=/dev/null" %
                   (to_list, subject, body_filename))
      else:
        command = ("sendgmr --to='%s' --subject='%s' --body_file='%s'" %
                   (to_list, subject, body_filename))
      if email_from:
        command += " --from=%s" % email_from
      if email_cc:
        cc_list = ",".join(email_cc)
        command += " --cc='%s'" % cc_list
      if email_bcc:
        bcc_list = ",".join(email_bcc)
        command += " --bcc='%s'" % bcc_list

      if attachments:
        attachment_files = []
        for attachment in attachments:
          if "<html>" in attachment.content:
            report_suffix = "_report.html"
          else:
            report_suffix = "_report.txt"
          fd, fname = tempfile.mkstemp(suffix=report_suffix)
          os.write (fd, attachment.content)
          os.close (fd)
          attachment_files.append(fname)
        files = ",".join(attachment_files)
        command += " --attachment_files='%s'" % files
        to_be_deleted += attachment_files

      # Send the message via our own GMR server.
      status = ce.RunCommand(command)
      return status

    finally:
      for f in to_be_deleted:
        os.remove(f)
