# gypsyutils.py
import os, sys, cgi, traceback, string
from time import strftime, gmtime, time, localtime, asctime
import rfc822
from cStringIO import StringIO
GypsyMailHomePage = "http://www.thinkspot.net/sheila/computers/software/gypsymail.html"
versionNumber = "0.7.1 beta"
# to turn on debug logging, set debug = 1
# to turn off debug logging, set debug = 0
debug = 0
def Debug(string):
if debug:
f=open('./gypsydebug.txt', 'a')
timestamp = asctime(localtime(time()))
f.write('**** %s ****' % timestamp)
f.write('\n')
f.write(string)
f.write('\n\n')
f.close()
def PrintHTTPHeader(Title):
print "Content-type: text/html\n"
print "\n
\n", Title, "\n\n"
def PrintURLLink(URLstring):
print '',URLstring,''
def PrintClosingHTMLTags(dict, Error=1):
# There are three possible levels of Error.
# For no error, Error == 0, so use SuccessReturnURL
# For a mild error, Error == 1, use ErrorReturnURL
# For a serious error, where it is not possible or not
# practical to give a return URL, Error == 2, and do not
# attempt to print any return URL.
if Error != 2:
print "Return to the website: "
if Error==1:
PrintURLLink(dict["ErrorReturnURL"])
else:
PrintURLLink(dict["SuccessReturnURL"])
try:
if dict["webmasterEmail"]:
print "
To contact the webmaster, send e-mail to: "
print '',dict["webmasterEmail"],''
except:
pass
print "
"
print "Gypsy Mail version ", versionNumber, "
"
print "\n"
def PrintErrorToLogFile(exc, val, tb, dict, ErrMessage = None):
''' log errors to file
requires a call in the calling routine of
exc, val, tb = sys.exc_info()
and then after PrintErrorToLogFile finishes, the
calling routine should execute this statment:
del tb '''
errortime = str(asctime(localtime(time())))
logfile = open(dict["logfilename"], 'a')
logfile.write('\n*** '+errortime+' ***\n')
if exc and val and tb:
traceback.print_exception(exc, val, tb, file = logfile)
if ErrMessage:
logfile.write(ErrMessage)
logfile.write('*************************\n\n')
logfile.close()
def PrintMissingFieldError(field):
print "Error: Required Field not Completed
"
print "Please use the back button on your browser and complete "
print "the required information.
"
print "The following required field was not completed: "
print ""
print field, "
"
dict ={}
PrintClosingHTMLTags(dict, Error =2)
def composeMessage(text, dict):
message = StringIO(text)
headers = rfc822.Message(message)
body = message.read()
TempToList = headers.getaddrlist("To") +\
headers.getaddrlist("Cc") +\
headers.getaddrlist("Bcc")
ToList = []
for addrTuple in TempToList:
name, addr = addrTuple
ToList = ToList + [addr]
if not dict["SMTPEnvelopeFrom"]:
FromField = headers.getaddr("From")[1]
else:
FromField = dict["SMTPEnvelopeFrom"]
while (1):
BccList = headers.getfirstmatchingheader('Bcc')
if BccList:
for line in BccList:
headers.headers.remove(line)
else:
break
date = strftime("%a, %d %b %Y %H:%M:%S", gmtime(time()))
RcvdLine = "Received: from "+ os.environ["REMOTE_ADDR"] +\
" by "+ os.environ["SERVER_NAME"] + " with HTTP;\n\t"+date+" -0000\n"
headers.headers.insert(0, RcvdLine)
if not headers.getrawheader("Date"):
DateField = "Date: " + date + " -0000\n"
headers.headers.append(DateField)
if not dict["MssgIDdomain"]:
if dict["SMTPhost"] == 'localhost':
import socket
hostname = socket.gethostname()
else:
hostname = dict["SMTPhost"]
else:
hostname = dict["MssgIDdomain"]
MessageID = "<"+str(abs(os.getpid()))+'.' + str(time())+".gypsymail@"+hostname+">"
IDField = "Message-ID: " + MessageID + '\n'
headers.headers.append(IDField)
if not os.environ.has_key("PATH_INFO"):
os.environ["PATH_INFO"] = ""
MailerField = "X-Mailer: GypsyMail "+versionNumber +\
"\n\t(Server_Name = " + os.environ["SERVER_NAME"]+")"+\
"\n\t(Script_URL = " + os.environ["SCRIPT_NAME"] + \
os.environ["PATH_INFO"] + "\n"
headers.headers.append(MailerField)
headerstring = string.join(headers.headers, '')
return FromField, ToList, string.replace(headerstring, '\r\n', '\n'), string.replace(body, '\r\n', '\n')
def sendMessage(text, dict):
From, To, headerstring, body = composeMessage(text, dict)
Message = "%s\n%s" % (headerstring, body)
import smtplib
try:
server = smtplib.SMTP(dict["SMTPhost"])
result = server.sendmail(From, To, Message)
server.quit()
Debug('SMTP result = %s' % str(result))
return headerstring, body
except smtplib.SMTPException, errmssg:
exc, val, tb = sys.exc_info()
PrintErrorToLogFile(exc, val, tb, dict = dict)
del tb
PrintHTTPHeader(dict["ErrorPageTitle"])
print "Error sending mail via SMTP server
"
print "", errmssg, "
"
print " result = %s
" % result
PrintClosingHTMLTags(dict)
raise
def FatalErrorPage(message = "A fatal error occured. The script cannot proceed."):
PrintHTTPHeader("GypsyMail - Fatal Error")
print "Fatal Error
"
print message
dict = {}
PrintClosingHTMLTags(dict, Error = 2)
def returnConfigFileContents(filepath):
try:
f = open(filepath, 'r')
except IOError, OSError:
FatalErrorPage("returnConfigFileContents in gypsyutils could not open the Config file.
"+\
"GypsyMail cannot continue without the Config File")
raise
filecontents = f.readlines()
f.close()
dict = {}
valuedict = {}
for line in filecontents:
if line[0] != '#' and string.find(line, '=') > 0 :
pair = string.split(line, '=')
key = string.strip(pair[0])
value = string.strip(pair[1])
if string.find(key, "values-") > -1:
key = string.replace(key, "values-", "")
valuedict[key]=value
else:
dict[key]=value
return dict, valuedict
def PrintNonMatchingFieldError(basefieldname):
print "Error: non-matching fields
"
print "Please use the <BACK> Button on your browser
"
print "and correct the data that you input in the fields for the
"
print "", basefieldname,"
"
print "so that the values match.
"
def printDefaultSuccess(dict, messageText):
try:
PrintHTTPHeader(dict["SuccessPageTitle"])
print "Success!
"
print "The following message was sent:
"
print ""
print cgi.escape(messageText, quote = 1)
print "
"
except:
PrintHTTPHeader(dict["ErrorPageTitle"])
exc, val, tb = sys.exc_info()
PrintErrorToLogFile(exc, val, tb, dict = dict)
del tb
print "Error: Script did not complete properly.
"
PrintClosingHTMLTags(dict=dict)
raise
def printTemplateSuccess(templatetext, sentMessage, headerstring, body, successDict, successoption):
formattedMessage = cgi.escape(sentMessage, quote=1)
headerstring = cgi.escape(headerstring, quote=1)
body = cgi.escape(body, quote=1)
if successoption == "3":
formattedMessage = string.replace(formattedMessage, '\n', '
')
formattedMessage = string.replace(formattedMessage, '\t', ' ')
headerstring = string.replace(headerstring, '\n', '
')
headerstring = string.replace(headerstring, '\t', ' ')
body = string.replace(body, '\n', '
')
body = string.replace(body, '\t', ' ')
templatetext = string.replace(templatetext, '[email_complete]', formattedMessage)
templatetext = string.replace(templatetext, '[email_headers]', headerstring)
templatetext = string.replace(templatetext, '[email_body]', body)
templist = [sentMessage, headerstring, body]
for field in templist:
Debug("field at %d = %s" % (templist.index(field), field))
headeroccurences = string.count(templatetext, '[headerfield-')
Debug("headeroccurences = %d" % headeroccurences)
loopcount = 1
if headeroccurences:
sentheaders = rfc822.Message(StringIO(sentMessage))
Debug("headers = %s" % str(sentheaders))
while headeroccurences:
Debug("occurence # %d" % loopcount)
startindex = string.find(templatetext, '[headerfield-')
endindex = string.find(templatetext, ']', startindex)
tag = templatetext[startindex:endindex+1]
Debug("tag = %s" % tag)
hyphenloc = string.find(tag, '-')
fieldname = tag[hyphenloc + 1 :-1]
formattedheader = "%s: %s" % (fieldname, sentheaders.getheader(fieldname, ''))
Debug("fieldcontents = %s" % formattedheader)
if successoption == "3":
formattedheader = string.replace(formattedheader, '\n', '
')
formattedheader = string.replace(formattedheader, '\t', ' ')
escaped_header = cgi.escape(formattedheader, quote=1)
templatetext = string.replace(templatetext, tag, escaped_header)
headeroccurences = headeroccurences - 1
loopcount = loopcount + 1
for key in successDict.keys():
keyvalue = successDict[key]
keyvalue = cgi.escape(keyvalue, quote=1)
if successoption == "3":
keyvalue = string.replace(keyvalue, '\n', '
')
templatetext = string.replace(templatetext, key, keyvalue)
print "Content-type: text/html\n"
print templatetext