email_sender.py revision ed69676d435b7b6983271ed8fab200627a0b966e
1#!/usr/bin/env python2
2
3# Copyright 2011 Google Inc. All Rights Reserved.
4"""Utilities to send email either through SMTP or SendGMR."""
5
6from __future__ import print_function
7
8from email import encoders as Encoders
9from email.mime.base import MIMEBase
10from email.mime.multipart import MIMEMultipart
11from email.mime.text import MIMEText
12import os
13import smtplib
14import tempfile
15
16from cros_utils import command_executer
17
18
19class EmailSender(object):
20  """Utility class to send email through SMTP or SendGMR."""
21
22  class Attachment(object):
23    """Small class to keep track of attachment info."""
24
25    def __init__(self, name, content):
26      self.name = name
27      self.content = content
28
29  def SendEmail(self,
30                email_to,
31                subject,
32                text_to_send,
33                email_cc=None,
34                email_bcc=None,
35                email_from=None,
36                msg_type='plain',
37                attachments=None):
38    """Choose appropriate email method and call it."""
39    if os.path.exists('/usr/bin/sendgmr'):
40      self.SendGMREmail(email_to, subject, text_to_send, email_cc, email_bcc,
41                        email_from, msg_type, attachments)
42    else:
43      self.SendSMTPEmail(email_to, subject, text_to_send, email_cc, email_bcc,
44                         email_from, msg_type, attachments)
45
46  def SendSMTPEmail(self, email_to, subject, text_to_send, email_cc, email_bcc,
47                    email_from, msg_type, attachments):
48    """Send email via standard smtp mail."""
49    # Email summary to the current user.
50    msg = MIMEMultipart()
51
52    if not email_from:
53      email_from = os.path.basename(__file__)
54
55    msg['To'] = ','.join(email_to)
56    msg['Subject'] = subject
57
58    if email_from:
59      msg['From'] = email_from
60    if email_cc:
61      msg['CC'] = ','.join(email_cc)
62      email_to += email_cc
63    if email_bcc:
64      msg['BCC'] = ','.join(email_bcc)
65      email_to += email_bcc
66
67    msg.attach(MIMEText(text_to_send, msg_type))
68    if attachments:
69      for attachment in attachments:
70        part = MIMEBase('application', 'octet-stream')
71        part.set_payload(attachment.content)
72        Encoders.encode_base64(part)
73        part.add_header('Content-Disposition',
74                        "attachment; filename=\"%s\"" % attachment.name)
75        msg.attach(part)
76
77    # Send the message via our own SMTP server, but don't include the
78    # envelope header.
79    s = smtplib.SMTP('localhost')
80    s.sendmail(email_from, email_to, msg.as_string())
81    s.quit()
82
83  def SendGMREmail(self, email_to, subject, text_to_send, email_cc, email_bcc,
84                   email_from, msg_type, attachments):
85    """Send email via sendgmr program."""
86    ce = command_executer.GetCommandExecuter(log_level='none')
87
88    if not email_from:
89      email_from = os.path.basename(__file__)
90
91    to_list = ','.join(email_to)
92
93    if not text_to_send:
94      text_to_send = 'Empty message body.'
95    body_fd, body_filename = tempfile.mkstemp()
96    to_be_deleted = [body_filename]
97
98    try:
99      os.write(body_fd, text_to_send)
100      os.close(body_fd)
101
102      # Fix single-quotes inside the subject. In bash, to escape a single quote
103      # (e.g 'don't') you need to replace it with '\'' (e.g. 'don'\''t'). To
104      # make Python read the backslash as a backslash rather than an escape
105      # character, you need to double it. So...
106      subject = subject.replace("'", "'\\''")
107
108      if msg_type == 'html':
109        command = ("sendgmr --to='%s' --subject='%s' --html_file='%s' "
110                   '--body_file=/dev/null' % (to_list, subject, body_filename))
111      else:
112        command = ("sendgmr --to='%s' --subject='%s' --body_file='%s'" %
113                   (to_list, subject, body_filename))
114      if email_from:
115        command += ' --from=%s' % email_from
116      if email_cc:
117        cc_list = ','.join(email_cc)
118        command += " --cc='%s'" % cc_list
119      if email_bcc:
120        bcc_list = ','.join(email_bcc)
121        command += " --bcc='%s'" % bcc_list
122
123      if attachments:
124        attachment_files = []
125        for attachment in attachments:
126          if '<html>' in attachment.content:
127            report_suffix = '_report.html'
128          else:
129            report_suffix = '_report.txt'
130          fd, fname = tempfile.mkstemp(suffix=report_suffix)
131          os.write(fd, attachment.content)
132          os.close(fd)
133          attachment_files.append(fname)
134        files = ','.join(attachment_files)
135        command += " --attachment_files='%s'" % files
136        to_be_deleted += attachment_files
137
138      # Send the message via our own GMR server.
139      status = ce.RunCommand(command)
140      return status
141
142    finally:
143      for f in to_be_deleted:
144        os.remove(f)
145