##################################################
# Spyce mail module
# Copyright (c) 2002 Adrien Plisson.
#
# SPYCE is Copyright (c) 2002 Rimon Barr.
# Refer to spyce.py
##################################################
from spyceModule import spyceModule
import smtplib
import email
import types
import string
import quopri
class mail(spyceModule):
def start(self):
pass
def init(self, *args, **kwargs):
if args != () or kwargs != {}:
self.setServer(*args, **kwargs)
def finish(self, error=None):
pass
def setServer(self, host, port=25, user=None, password=None):
self.host = host
self.port= port
self.user = user
self.password = password
def send(self, from_field, to_field, subject_field, content, cc_field=None, bcc_field=None):
#parse arguments
from_field = _parse_addrs(from_field)
to_field = _parse_addrs(to_field)
if cc_field != None:
cc_field = _parse_addrs(cc_field)
if bcc_field != None:
bcc_field = _parse_addrs(bcc_field)
#compose the mail
msg = _build_main_message(from_field, to_field, subject_field, content, cc_field).as_string()
#build the sender and recipients lists
sender = from_field[0]
if cc_field == None:
recipients = to_field
else:
recipients = to_field + cc_field
sender= _unparse_addr(sender)
for i in range(len(recipients)):
recipients[i] = _unparse_addr(recipients[i])
#establish the connection
con = smtplib.SMTP(self.host, self.port)
if self.user != None and self.password != None:
con.login(self.user, self.password)
#send the mail first to the recipients in the to and cc fields
con.sendmail(sender, recipients, msg)
#then we send it for each recipient in the bcc field
if bcc_field != None:
for recipient in bcc_field:
con.sendmail(sender, recipient, msg)
#close the connection
con.quit()
def _parse_addrs(addrs):
if type(addrs) == types.ListType:
return map(_parse_addr, addrs)
else:
return [_parse_addr(addrs)]
def _parse_addr(addr):
if type(addr) in types.StringTypes:
return email.Utils.parseaddr(addr)
elif type(addr) == types.TupleType:
return addr
def _unparse_addrs(addrs):
return string.join(map(_unparse_addr, addrs), ', ')
def _unparse_addr(addr):
return email.Utils.dump_address_pair(addr)
def _build_main_message(from_field, to_field, subject_field, content, cc_field=None):
msg = email.Message.Message()
msg['From'] = _unparse_addrs(from_field)
msg['To'] = _unparse_addrs(to_field)
if cc_field != None:
msg['Cc'] = _unparse_addrs(cc_field)
msg['Subject'] = _encode_field(subject_field)
msg['MIME-Version'] = '1.0'
#if content is a dictionnary (with content, type, encoding and disposition)
if type(content) == types.DictType:
msg['Content-Type'] = content['type']
#if we have subparts
if type(content['content']) == types.ListType:
for submsg in content['content']:
msg.attach(_build_message(submsg))
#if we don't have any subpart
else:
#if the content is a string
if type(content['content']) in types.StringTypes:
msg.attach(content['content'])
#or if it's an open file
else:
msg.attach(content['content'].read())
#if we have an encoding, then we encode
if content.has_key('encoding'):
msg = _encode_message(msg, content['encoding'])
#we allow to specify some additional fields
if content.has_key('additional_fields'):
for field in content['additional_fields']:
msg[field] = content['additional_fields'][field]
#if the content is a list then we have subparts
elif type(content) == types.ListType:
msg['Content-Type'] = 'multipart/mixed'
for submsg in content:
msg.attach(_build_message(submsg))
#if content is a string, then we dump it as is
elif type(content) in types.StringTypes:
msg.attach(content)
#in other cases, we consider it's an open file
else:
msg.attach(content.read())
return msg
def _build_message(content):
msg = email.Message.Message()
#if content is a dictionnary (with content, type, encoding and disposition)
if type(content) == types.DictType:
msg['Content-Type'] = content['type']
#if we have subparts
if type(content['content']) == types.ListType:
for submsg in content['content']:
msg.attach(_build_message(submsg))
#if we don't have any subpart
else:
#if the content is a string
if type(content['content']) in types.StringTypes:
msg.attach(content['content'])
#or if it's an open file
else:
msg.attach(content['content'].read())
#if we have an encoding, then we encode
if content.has_key('encoding'):
msg = _encode_message(msg, content['encoding'])
#we allow to specify some additional fields
if content.has_key('additional_fields'):
for field in content['additional_fields']:
msg[field] = content['additional_fields'][field]
#if the content is a list then we have subparts
elif type(content) == types.ListType:
msg['Content-Type'] = 'multipart/mixed'
for submsg in content:
msg.attach(_build_message(submsg))
#if content is a string, then we dump it as is
elif type(content) in types.StringTypes:
msg.attach(content)
#in other cases, we consider it's an open file
else:
msg.attach(content.read())
return msg
def _encode_field(field):
if quopri.encodestring(field) == field:
return field
else:
return email.Utils.encode(field)
def _encode_message(msg, encoding):
if encoding == 'quoted-printable':
email.Encoders.encode_quopri(msg)
elif encoding == 'base64':
email.Encoders.encode_base64(msg)
elif encoding == '7bit' or encoding == '8bit':
email.Encoders.encode_7or8bit(msg)
return msg
|