[Tutor] pdf file as attachment
Harm Kirchhoff
harm.kirchhoff at web.de
Wed Aug 25 10:57:24 CEST 2004
I have recently experimented with excel files as attachments.
I think the code should work for pdf files, too.
I attach some sample code. This sample mails all files in the direcotry
defined as path. Be careful to thest this on .pdf files, because you can
see that I used in-memory storage by constructing my own buffer.
Don't do this for larger files. The below is experimental code which I
used to understand the concept.
Further down I attach the code that I am actually using to get my work done.
I hope this helps.
#############################################################################3
#!/usr/bin/env/ python
"""
This example was tested and worked just fine.
"""
import base64, quopri
import mimetypes, email.Generator, email.Message
import cStringIO, os
toAddr =
"harm_kirchhoff at mail.digital.co.jp,hk at pop.ms,harm.kirchhoff at r8.dion.ne.jp"
fromAddr = "harm_kirchhoff at mail.digital.co.jp"
outputFile = 'mailmessage.tmp'
def main():
print 'start main'
mainMsg = email.Message.Message()
mainMsg["To"] = toAddr
mainMsg["From"] = fromAddr
mainMsg["Subject"] = "files"
mainMsg["Mime-version"] = "1.0"
mainMsg["Content-type"] = "Multipart/mixed"
mainMsg.preamble = "Mime message\m"
mainMsg.epilogue = ""
path = "C:/Program Files/Zope262/Extensions/cost_mailer/templates"
fileNames = [f for f in os.listdir(path)] # if os.path.isfile(f) ]
print 'List of files:',fileNames
for fileName in fileNames:
fileName = path + '/' + fileName
contentType,ignored = mimetypes.guess_type(fileName)
if contentType == None: # If no guess, use generic opaque text
contentType = "application/octet-stream"
contentsEncoded = cStringIO.StringIO()
f = open(fileName,"rb")
mainType = contentType[:contentType.find("/")]
if mainType == "text":
cte = "quoted-printable"
quopri.encode(f, contentsEncoded, 1) # 1 to encode tabs
else:
cte = "base64"
base64.encode(f, contentsEncoded)
f.close()
subMsg = email.Message.Message()
subMsg.add_header( "Content-type", contentType, name=fileName)
subMsg.add_header( "Content-transfer-encoding", cte)
subMsg.add_payload(contentsEncoded.getvalue() )
contentsEncoded.close()
mainMsg.add_payload(subMsg)
subMsg = email.Message.Message()
subMsg.add_header( "Content-type", "text")
subMsg.add_header( "Content-transfer-encoding", "quoted-printable")
subMsg.add_payload('This is a plain us-ascii message string' )
contentsEncoded.close()
mainMsg.add_payload(subMsg)
#f = open(outputFile, "wb")
f = temp_buffer()
g = email.Generator.Generator(f)
g(mainMsg)
f.close()
print "done, now sending"
import smtplib
#f = open(outputFile, "rb")
s = f.read()
server = smtplib.SMTP('smtp.server.com',0) # server and port
server.sendmail(fromAddr,toAddr,s)
return True
class temp_buffer:
"""
email.Generator.Generator() requires an output file as argument,
or another storage object that supports write methods.
Writing to files is adequate for larger messages, but keeping the
process in the buffer is better when the messages are to be sent
immediately and now large memmory is consumed.
"""
def __init__(self):
self.contents = ""
def write(self,var):
self.contents = self.contents + var
def read(self):
return self.contents
def close(self):
"Just to be compliant with files"
return True
if __name__ == '__main__':
# If run as stand alone ...
main()
###########################################################################
"""
Here you see the loop that I use in my actual program to compile and
send the emails. This is only an exerpt
"""
for toAddr in self.init.recipients[report]:
# email header
mainMsg = email.Message.Message()
mainMsg["To"] = toAddr
mainMsg["From"] = self.init.notify
mainMsg["Subject"] = self.init.header+report
mainMsg["Mime-version"] = "1.0"
mainMsg["Content-type"] = "Multipart/mixed"
mainMsg.preamble = "Mime message\m"
mainMsg.epilogue = ""
# First lines of message
try:
header.write('Report for Cost Center: '+report +
', '+Date+'\n\n')
header.write('All amounts in JPY.\n\n')
subMsg = email.Message.Message()
subMsg.add_header( "Content-type", "text")
subMsg.add_header( "Content-transfer-encoding",
"quoted-printable")
contentsEncoded = cStringIO.StringIO()
quopri.encode(header, contentsEncoded, 1) # 1 to
encode tabs
subMsg.add_payload( contentsEncoded.getvalue() )
contentsEncoded.close()
header.close()
mainMsg.add_payload(subMsg)
except:
self.init.gui.write('Failed to include header
into email.')
# report.csv file part of the message
subMsg = email.Message.Message()
subMsg.add_header( "Content-type",
"application/octet-stream", name='report.csv')
subMsg.add_header( "Content-transfer-encoding",
"base64")
contentsEncoded = cStringIO.StringIO()
buff = file( repFile, 'rb')
base64.encode(buff, contentsEncoded)
buff.close()
subMsg.add_payload( contentsEncoded.getvalue() )
contentsEncoded.close()
mainMsg.add_payload(subMsg)
# ledger.csv file part of the message
subMsg = email.Message.Message()
subMsg.add_header( "Content-type",
"application/octet-stream", name='ledger.csv')
subMsg.add_header( "Content-transfer-encoding",
"base64")
contentsEncoded = cStringIO.StringIO()
buff = file( csvFile, 'rb')
base64.encode(buff, contentsEncoded)
buff.close()
subMsg.add_payload( contentsEncoded.getvalue() )
contentsEncoded.close()
mainMsg.add_payload(subMsg)
# last lines of message
try:
subMsg = email.Message.Message()
subMsg.add_header( "Content-type", "text")
subMsg.add_header( "Content-transfer-encoding",
"quoted-printable")
contentsEncoded = cStringIO.StringIO()
header.write( '\n\n'+self.init.footer)
quopri.encode(header, contentsEncoded, 1) # 1 to
encode tabs
subMsg.add_payload( contentsEncoded.getvalue() )
contentsEncoded.close()
header.close()
mainMsg.add_payload(subMsg)
except:
self.init.gui.write('Failed to include footer
into email.')
# and send it:
f = open(emlFile, "wb")
g = email.Generator.Generator(f)
g(mainMsg)
f.close()
f = open(emlFile, "rb")
s = f.read()
f.close()
error =
mail_man(self.init.notify,toAddr,s,self.init.SMTPserver,0)
del s,f
if error <> True:
if error == -1:
self.init.gui.write('Report_Mailer failed to
initialize SMTP server. Settings wrong ?')
self.init.gui.write('
Server:'+self.init.SMTPserver )
self.init.gui.write(' Port
:'+str(self.init.port) )
return False
else:
self.init.gui.write('Failed to send mails
to:'+self.init.notify)
self.init.gui.write('A possible reason may
be that you use Japanese characters.')
for index in error:
self.init.gui.write( mail_list[index][1] )
return False
##########################################################
"""
And here is the routine that actually sends the email.
"""
def mail_man(fromAddr, toAddr, Message, Server, Port):
"""Sends mails from a list.
Message : A mail message (correctly encoded)
Server : A string with the server address
Port : An integer with the port number
Returns:
True If all mails sent
-1 If Server could not be initialized
0 ... A list of numbers x that correspond to the elements in
Mails[x],
describing the message that could not be sent.
"""
# Open the server
import smtplib
error = True
try:
server = smtplib.SMTP(Server, Port)
except:
return -1
# send message
try:
server.sendmail( fromAddr, toAddr , Message )
except:
error = False
# close server
if error == True:
server.quit()
return True
else:
return -2
More information about the Tutor
mailing list