From: Mark Huang Date: Tue, 16 Jan 2007 17:02:52 +0000 (+0000) Subject: - just call sendmail instead of using smtplib. sendmail is required for X-Git-Tag: pycurl-7_13_1~105 X-Git-Url: http://git.onelab.eu/?a=commitdiff_plain;h=7a0cd1f35e73c08da9d10f90fe37fa3d6b56964a;p=plcapi.git - just call sendmail instead of using smtplib. sendmail is required for MyPLC anyway, and gets us queueing for free. --- diff --git a/PLC/sendmail.py b/PLC/sendmail.py index 408f2cb..aa7c8eb 100644 --- a/PLC/sendmail.py +++ b/PLC/sendmail.py @@ -1,144 +1,67 @@ -import smtplib -import string +import os import sys -import time +from types import StringTypes +from subprocess import Popen, PIPE +from PLC.Debug import log from PLC.Faults import * -""" -used to send out emails - sets up the headers correctly -""" -class sendmail: - - def __init__(self, config): - - self.MAIL_ENABLED = config.PLC_MAIL_ENABLED - - self.SMTP_SERVER= 'localhost' - - self.X_MAILER= 'PlanetLab API Mailer' - - - """ - open up a connect to our mail server, and send out a message. - - the email addresses are not verified before sending out the message. - - to_addr_list, cc_addr_list, and from_addr should be a dictionary, with the keys - being the email address and the value being the plain text name of - the recipient. only the first key from from_addr will be used, so it should - contain only one address. - - subject is not checked for multiple lines - ensure it is only one. - """ - def mail( self, to_addr_list, cc_addr_list, from_addr, subject, content ): - - if self.MAIL_ENABLED == 0: - return 1 - - server= smtplib.SMTP(self.SMTP_SERVER) - - str_date= time.strftime("%a, %d %b %Y %H:%M:%S +0000", time.gmtime()) - - str_from_addr= self.create_recipient_list(from_addr,1) - str_to_addr= self.create_recipient_list(to_addr_list) - - full_message = "" - full_message += "Content-type: text/plain; charset=iso-8859-1\r\n" - full_message += "Date: %s\r\n" % str_date - full_message += "MIME-Version: 1.0\r\n" - - full_message += "To: %s\r\n" % str_to_addr - full_message += "From: %s\r\n" % str_from_addr - - if cc_addr_list is not None and len(cc_addr_list) > 0: - str_cc_addr= self.create_recipient_list(cc_addr_list) - full_message += "Cc: %s\r\n" % str_cc_addr - - full_message += "Subject: %s\r\n" % subject - full_message += "Reply-To: %s\r\n" % str_from_addr - full_message += "X-Mailer: %s\r\n\r\n" % self.X_MAILER - full_message += content - - try: - # get just a list of to recipients (needed for envelope). this - # needs to include all reciepients, including Cc - local_to_list= to_addr_list.copy() - - if cc_addr_list is not None: - local_to_list.update( cc_addr_list ) - - all_to_addr_list= self.create_recipient_list(local_to_list, - return_string=0) - - # send out the mail! - rc= server.sendmail(str_from_addr, all_to_addr_list, full_message ) - - return 1 - - except smtplib.SMTPRecipientsRefused, err: - sys.stderr.write( "SMTPRecipientsRefused: %s" % repr(err) ) - return 0 - - except smtplib.SMTPHeloError: - sys.stderr.write( "SMTPHeloError: %s" % repr(err) ) - return 0 - - except smtplib.SMTPSenderRefused: - sys.stderr.write( "SMTPSenderRefused: %s" % repr(err) ) - return 0 - - except smtplib.SMTPDataError: - sys.stderr.write( "SMTPDataError: %s" % repr(err) ) - return 0 - - - - - +def sendmail(api, To, Subject, Body, From = None, Cc = "", Bcc = "", DSN = "never"): """ - accepts a list of email recipient as a dictionary in the same format - as the mail function, and returns it in a format suitable for use in - an email message. for example: - - if limit is specified, only limit number of entries from - addr_list is used. which one is used is not defined, so it is really only - useful to make sure that the result has a single entry (for from lines) - - for return_string= 1: - input: {'user@domain.com': 'A User','test@planet-lab.org': 'PL User'} - ouput: 'A User , PL User ' - otherwise: - input: {'user@domain.com': 'A User','test@planet-lab.org': 'PL User'} - ouput: ['A User ', 'PL User '] - + Uses sendmail (must be installed and running locally) to send a + message to the specified recipients. If the API is running under + mod_python, the apache user must be listed in e.g., + /etc/mail/trusted-users. + + If dsn is not 'never' (e.g., 'failure', 'delay', or 'success'), + then the current support address (PLC_MAIL_SUPPORT_ADDRESS) will + receive any delivery status notification messages. """ - def create_recipient_list( self, addr_list, return_string= 1, limit= None ): - if not isinstance(addr_list,dict): - raise PLCAPIError, \ - "Internal error, call to create_recipient_list " \ - "with non-dict addr_list (%s)." % str(addr_list) - - if limit == None: - limit= len(addr_list.keys()) - if limit <= 0: - return '' + # Fix up defaults + if From is None: + From = "%s Support <%s>" % \ + (api.config.PLC_NAME, api.config.PLC_MAIL_SUPPORT_ADDRESS) - recipients= [] - total= 0 - - for email in addr_list.keys(): - recipients = recipients + ['%s <%s>' % (addr_list[email],email)] - total= total+1 - if total == limit: - break + header = {'From': From, + 'version': sys.version.split(" ")[0], + 'Subject': Subject} - if return_string == 1: - return string.join( recipients, ", " ) + # Accept either a string or a list of strings for each of To, Cc, and Bcc + for line in 'To', 'Cc', 'Bcc': + addresses = locals()[line] + if isinstance(addresses, StringTypes): + header[line] = addresses else: - return recipients - - - - + header[line] = ", ".join(addresses) + + if not api.config.PLC_MAIL_ENABLED: + print >> log, "From: %(From)s, To: %(To)s, Subject: %(Subject)s" % header + return + + p = Popen(["sendmail", "-N", DSN, "-t", "-f" + api.config.PLC_MAIL_SUPPORT_ADDRESS], + stdin = PIPE, stdout = PIPE, stderr = PIPE) + + # Write headers + p.stdin.write(""" +Content-type: text/plain +From: %(From)s +Reply-To: %(From)s +To: %(To)s +Cc: %(Cc)s +Bcc: %(Bcc)s +X-Mailer: Python/%(version)s +Subject: %(Subject)s + +""".lstrip() % header) + + # Write body + p.stdin.write(Body) + + p.stdin.close() + err = p.stderr.read() + rc = p.wait() + + # Done + if rc != 0: + raise PLCAPIError, err