[Commits] (bkirsch) Updated smtp logic expanded message code and
made changes to support new additions to mail content model
commits at osafoundation.org
commits at osafoundation.org
Thu Aug 19 16:59:57 PDT 2004
Commit by: bkirsch
Modified files:
chandler/parcels/osaf/mail/MailTasks.py 1.4 1.5
chandler/parcels/osaf/mail/imap.py 1.11 1.12
chandler/parcels/osaf/mail/message.py 1.12 1.13
chandler/parcels/osaf/mail/parcel.xml 1.16 1.17
chandler/parcels/osaf/mail/smtp.py 1.2 1.3
Log message:
Updated smtp logic expanded message code and made changes to support new additions to mail content model
ViewCVS links:
http://cvs.osafoundation.org/index.cgi/chandler/parcels/osaf/mail/MailTasks.py.diff?r1=text&tr1=1.4&r2=text&tr2=1.5
http://cvs.osafoundation.org/index.cgi/chandler/parcels/osaf/mail/imap.py.diff?r1=text&tr1=1.11&r2=text&tr2=1.12
http://cvs.osafoundation.org/index.cgi/chandler/parcels/osaf/mail/message.py.diff?r1=text&tr1=1.12&r2=text&tr2=1.13
http://cvs.osafoundation.org/index.cgi/chandler/parcels/osaf/mail/parcel.xml.diff?r1=text&tr1=1.16&r2=text&tr2=1.17
http://cvs.osafoundation.org/index.cgi/chandler/parcels/osaf/mail/smtp.py.diff?r1=text&tr1=1.2&r2=text&tr2=1.3
Index: chandler/parcels/osaf/mail/imap.py
diff -u chandler/parcels/osaf/mail/imap.py:1.11 chandler/parcels/osaf/mail/imap.py:1.12
--- chandler/parcels/osaf/mail/imap.py:1.11 Tue Aug 17 18:33:21 2004
+++ chandler/parcels/osaf/mail/imap.py Thu Aug 19 16:59:55 2004
@@ -1,5 +1,5 @@
-__revision__ = "$Revision: 1.11 $"
-__date__ = "$Date: 2004/08/18 01:33:21 $"
+__revision__ = "$Revision: 1.12 $"
+__date__ = "$Date: 2004/08/19 23:59:55 $"
__copyright__ = "Copyright (c) 2004 Open Source Applications Foundation"
__license__ = "http://osafoundation.org/Chandler_0.1_license_terms.htm"
@@ -24,7 +24,7 @@
class ChandlerIMAP4Client(imap4.IMAP4Client):
- def __init__(self, contextFactory, useSSL):
+ def __init__(self, contextFactory=None, useSSL=False):
imap4.IMAP4Client.__init__(self, contextFactory)
self.useSSL = useSSL
@@ -40,7 +40,7 @@
@return C{None}
"""
- if self.useSSL == 'NoSSL':
+ if not self.useSSL:
self.serverCapabilities = self.__disableTLS(caps)
d = defer.Deferred()
@@ -68,7 +68,7 @@
class ChandlerIMAP4Factory(protocol.ClientFactory):
protocol = ChandlerIMAP4Client
- def __init__(self, callback, errback, useSSL):
+ def __init__(self, callback, errback, useSSL=False):
"""
A C{protocol.ClientFactory} that creates C{ChandlerIMAP4Client} instances
and stores the callback and errback to be used by the C{ChandlerIMAP4Client} instances
@@ -87,10 +87,11 @@
self.useSSL = useSSL
def buildProtocol(self, addr):
- if self.useSSL == 'NoSSL':
- p = self.protocol(contextFactory=None, useSSL=self.useSSL)
+ if not self.useSSL:
+ p = self.protocol()
else:
- p = self.protocol(ssl.ClientContextFactory(useM2=1), self.useSSL)
+ p = self.protocol(ssl.ClientContextFactory(useM2=1), True)
+
p.factory = self
return p
@@ -98,7 +99,7 @@
logging.error("Unable to connect to server; reason: '%s'", reason)
-class IMAPMailException(common.MailException):
+class IMAPException(common.MailException):
pass
class IMAPDownloader(RepositoryView.AbstractRepositoryViewManager):
@@ -156,20 +157,15 @@
host = self.account.host
port = self.account.port
- portSSL = self.account.portSSL
useSSL = self.account.useSSL
- if __debug__:
- self.printAccount()
-
finally:
self.restorePreviousView()
- factory = ChandlerIMAP4Factory(self.loginClient, self.catchErrors,
- useSSL)
- if useSSL == 'SSL':
- reactor.connectSSL(host, portSSL, factory,
- ssl.ClientContextFactory(useM2=1))
+ factory = ChandlerIMAP4Factory(self.loginClient, self.catchErrors, useSSL)
+
+ if useSSL:
+ reactor.connectSSL(host, port, factory, ssl.ClientContextFactory(useM2=1))
else:
reactor.connectTCP(host, port, factory)
@@ -187,7 +183,6 @@
str = "\nHost: %s\n" % self.account.host
str += "Port: %d\n" % self.account.port
- str += "PortSSL: %d\n" % self.account.portSSL
str += "SSL: %s\n" % self.account.useSSL
str += "Username: %s\n" % self.account.username
str += "Password: %s\n" % self.account.password
@@ -331,7 +326,7 @@
repMessage.deliveryExtension.folder = "INBOX"
repMessage.deliveryExtension.uid = uid
- self.account.downloadedMail.append(repMessage)
+ #self.account.downloadedMail.append(repMessage)
if uid > self.__getLastUID():
self.__setLastUID(uid)
Index: chandler/parcels/osaf/mail/message.py
diff -u chandler/parcels/osaf/mail/message.py:1.12 chandler/parcels/osaf/mail/message.py:1.13
--- chandler/parcels/osaf/mail/message.py:1.12 Tue Aug 17 18:33:21 2004
+++ chandler/parcels/osaf/mail/message.py Thu Aug 19 16:59:55 2004
@@ -1,5 +1,5 @@
-__revision__ = "$Revision: 1.12 $"
-__date__ = "$Date: 2004/08/18 01:33:21 $"
+__revision__ = "$Revision: 1.13 $"
+__date__ = "$Date: 2004/08/19 23:59:55 $"
__copyright__ = "Copyright (c) 2004 Open Source Applications Foundation"
__license__ = "http://osafoundation.org/Chandler_0.1_license_terms.htm"
@@ -11,6 +11,7 @@
import email.Utils as Utils
import re as re
import common as common
+import logging as logging
__exp = re.compile("\w+((-\w+)|(\.\w+)|(\_\w+))*\@[A-Za-z2-9]+((\.|-)[A-Za-z0-9]+)*\.[A-Za-z]{2,5}")
@@ -27,7 +28,7 @@
@type addr: C{String}
@return: C{Boolean}
"""
- if not isinstance(emailAddress, str):
+ if not __isString(emailAddress):
return False
emailAddress = emailAddress.strip()
@@ -58,7 +59,7 @@
"""
#XXX: There are bugs here because of the weakness of the parseaddr API
- if not isinstance(emailAddressOne, str) or not isinstance(emailAddressTwo, str):
+ if not __isString(emailAddressOne) or not __isString(emailAddressTwo):
return False
emailAddressOne = Utils.parseaddr(emailAddressOne)[1]
@@ -91,7 +92,7 @@
@type value: C{String}
@return: C{Boolean}
"""
- if isinstance(value, str):
+ if __isString(value):
test = value.strip()
if len(test) > 0:
return True
@@ -99,7 +100,7 @@
return False
def isPlainTextContentType(contentType):
- if isinstance(contentType, str):
+ if __isString(contentType):
contentType = contentType.lower().strip()
if contentType == common.MIME_TEXT_PLAIN:
@@ -207,7 +208,7 @@
del messageObject[key]
except KeyError:
- print "KEY ERROR Here"
+ logging.error("in osaf.mail.message.messageObjectToKind: KEY ERROR")
if messageObject.is_multipart():
mimeParts = messageObject.get_payload()
@@ -276,33 +277,35 @@
if mailMessage.body is not None:
messageObject.set_payload(textToStr(mailMessage.body))
-
- if mailMessage.fromAddress is not None:
- messageObject['From'] = format_addr(mailMessage.fromAddress)
-
- if mailMessage.replyToAddress is not None:
- messageObject["Reply-To"] = format_addr(mailMessage.replyToAddress)
+ __populateParam(messageObject, 'From', mailMessage.fromAddress, 'EmailAddress')
+ __populateParam(messageObject, 'Reply-To', mailMessage.replyToAddress, 'EmailAddress')
to = []
for address in mailMessage.toAddress:
- to.append(format_addr(address))
+ if hasValue(address.emailAddress):
+ to.append(format_addr(address))
- messageObject['To'] = ", ".join(to)
+ if len(to) > 0:
+ messageObject['To'] = ", ".join(to)
cc = []
for address in mailMessage.ccAddress:
- cc.append(format_addr(address))
+ if hasValue(address.emailAddress):
+ cc.append(format_addr(address))
- messageObject['Cc'] = ", ".join(cc)
+ if len(cc) > 0:
+ messageObject['Cc'] = ", ".join(cc)
bcc = []
for address in mailMessage.bccAddress:
- bcc.append(format_addr(address))
+ if hasValue(address.emailAddress):
+ bcc.append(format_addr(address))
- messageObject['Bcc'] = ", ".join(bcc)
+ if len(bcc) > 0:
+ messageObject['Bcc'] = ", ".join(bcc)
return messageObject
@@ -326,7 +329,7 @@
def strToText(contentItem, attribute, string):
- if not isinstance(string, str):
+ if not __isString(string):
return None
return contentItem.getAttributeAspect(attribute, 'type').makeValue(string, indexed=False)
@@ -344,9 +347,16 @@
return string
-def __populateParam(messageObject, param, var):
- if hasValue(var):
- messageObject[param] = var
+def __populateParam(messageObject, param, var, type='String'):
+
+ if type == 'String':
+ if hasValue(var):
+ messageObject[param] = var
+
+ elif(type == 'EmailAddress'):
+ if var is not None and hasValue(var.emailAddress):
+ messageObject[param] = format_addr(var)
+
def __assignToKind(kindVar, messageObject, key, type, attr = None):
@@ -383,10 +393,16 @@
kindVar.append(ea)
else:
- print "Header slipped through"
+ logging.error("in osaf.mail.message.__assignToKind: HEADER SLIPPED THROUGH")
try:
del messageObject[key]
except KeyError:
- print "Key Error Thrown"
+ logging.error("in osaf.mail.message.__assignToKind: KEY ERROR")
+
+def __isString(var):
+ if isinstance(var, str) or isinstance(var, unicode):
+ return True
+
+ return False
Index: chandler/parcels/osaf/mail/parcel.xml
diff -u chandler/parcels/osaf/mail/parcel.xml:1.16 chandler/parcels/osaf/mail/parcel.xml:1.17
--- chandler/parcels/osaf/mail/parcel.xml:1.16 Tue Aug 17 18:33:21 2004
+++ chandler/parcels/osaf/mail/parcel.xml Thu Aug 19 16:59:55 2004
@@ -11,7 +11,7 @@
<host>code-bear.com</host>
<username>osafuser</username>
<password>chandler</password>
- <useSSL>NoSSL</useSSL>
+ <useSSL>False</useSSL>
<!-- This points replyToAddress to the email address item below-->
<replyToAddress ref="mail:ReplyAddress" />
<!-- This points to the SMTPAccount item below -->
@@ -29,7 +29,7 @@
<host>code-bear.com</host>
<username>osafuser</username>
<password>chandler</password>
- <useSSL>NoSSL</useSSL>
+ <useSSL>False</useSSL>
<useAuth>False</useAuth>
</content:SMTPAccount>
@@ -46,15 +46,14 @@
</task:Task>
- <task:Task itsName="SMTPClient">
+ <task:Task itsName="SMTPMailClient">
<task:Schedule itsName="MailSchedule">
<task:startTime>2003-11-11 11:11:11+0800</task:startTime>
- <task:repeatFlag>False</task:repeatFlag>
- <task:repeatDelay>00:00:00:30</task:repeatDelay>
+ <task:repeatFlag>True</task:repeatFlag>
+ <task:repeatDelay>00:00:01:00</task:repeatDelay>
</task:Schedule>
- <!--task:Action itsName="sendmail" itemClass="osaf.mail.MailTasks.SMTPSendAction"/>
- <task:schedule itemref="mail:SMTPClient/MailSchedule"/>
- <task:actions itemref="mail:SMTPClient/sendMail"/-->
+ <!--task:Action itsName="sendMail" itemClass="osaf.mail.MailTasks.SMTPSendAction"/>
+ <task:schedule itemref="mail:SMTPMailClient/MailSchedule"/>
+ <task:actions itemref="mail:SMTPMailClient/sendMail"/-->
</task:Task>
-
</Parcel>
Index: chandler/parcels/osaf/mail/MailTasks.py
diff -u chandler/parcels/osaf/mail/MailTasks.py:1.4 chandler/parcels/osaf/mail/MailTasks.py:1.5
--- chandler/parcels/osaf/mail/MailTasks.py:1.4 Tue Aug 17 18:33:21 2004
+++ chandler/parcels/osaf/mail/MailTasks.py Thu Aug 19 16:59:55 2004
@@ -1,13 +1,16 @@
-__revision__ = "$Revision: 1.4 $"
-__date__ = "$Date: 2004/08/18 01:33:21 $"
+__revision__ = "$Revision: 1.5 $"
+__date__ = "$Date: 2004/08/19 23:59:55 $"
__copyright__ = "Copyright (c) 2004 Open Source Applications Foundation"
__license__ = "http://osafoundation.org/Chandler_0.1_license_terms.htm"
import osaf.framework.tasks.Action as Action
+import application.Globals as Globals
import osaf.contentmodel.mail.Mail as Mail
import repository.item.Query as Query
import imap as imap
import smtp as smtp
+import common as common
+import message as message
import logging as logging
@@ -39,6 +42,37 @@
class SMTPSendAction(Action.Action):
def Execute(self, task):
+ accountKind = Mail.MailParcel.getSMTPAccountKind()
+ account = None
- logging.info("SENDING STMP MAIL")
- #smtp.SMTPSender().sendmail()
+ for acc in Query.KindQuery().run([accountKind]):
+ account = acc
+ break
+
+ m = Mail.MailMessage()
+
+ ea = Mail.EmailAddress()
+ ea.emailAddress = "brian at localhost"
+ ea.fullName = "Brian Kirsch"
+
+ ea1 = Mail.EmailAddress()
+ ea1.emailAddress = "bkirsch at osafoundation.org"
+ ea1.fullName = "Brian Kirsch"
+
+ ea2 = Mail.EmailAddress()
+ ea2.emailAddress = "bkmuzic at yahoo.com"
+ ea2.fullName = "Brian Kirsch"
+
+ m.toAddress.append(ea)
+ #m.toAddress.append(ea1)
+ #m.ccAddress.append(ea2)
+
+ m.fromAddress = ea1
+ m.replyToAddress = ea
+ m.subject = "This is a Test From SMTPSenderAction"
+ m.body = message.strToText(m, "body", "This is some body Text")
+ m.inReplyTo = "TEST"
+
+ Globals.repository.commit()
+
+ smtp.SMTPSender(account, m).sendMail()
Index: chandler/parcels/osaf/mail/smtp.py
diff -u chandler/parcels/osaf/mail/smtp.py:1.2 chandler/parcels/osaf/mail/smtp.py:1.3
--- chandler/parcels/osaf/mail/smtp.py:1.2 Tue Aug 17 18:33:21 2004
+++ chandler/parcels/osaf/mail/smtp.py Thu Aug 19 16:59:55 2004
@@ -1,5 +1,5 @@
-__revision__ = "$Revision: 1.2 $"
-__date__ = "$Date: 2004/08/18 01:33:21 $"
+__revision__ = "$Revision: 1.3 $"
+__date__ = "$Date: 2004/08/19 23:59:55 $"
__copyright__ = "Copyright (c) 2004 Open Source Applications Foundation"
__license__ = "http://osafoundation.org/Chandler_0.1_license_terms.htm"
@@ -23,31 +23,34 @@
from StringIO import StringIO
-class SMTPMailException(common.MailException):
+class SMTPException(common.MailException):
pass
class SMTPSender(RepositoryView.AbstractRepositoryViewManager):
def __init__(self, account, mailMessage):
+ #XXX: Perhaps get the first account if None
if account is None or not account.isItemOf(Mail.MailParcel.getSMTPAccountKind()):
raise SMTPMailException("You must pass in a SMTPAccount instance")
- if mailMessage is None or not mailMessage.isItemOf(Mail.MailParcel.getMailMessageKind()):
+ if mailMessage is None or not isinstance(mailMessage, Mail.MailMessage):
raise SMTPMailException("You must pass in a mailParcel instance")
- viewName = "%s_%s" % (account.displayName, str(UUID.UUID()))
+ id = "STMPSender Mail ", DateTime.now().ticks()
+ viewName = "%s_%s_%s" % (id, account.displayName, str(UUID.UUID()))
super(SMTPSender, self).__init__(Globals.repository, viewName)
self.accountUUID = account.itsUUID
self.account = None
+ self.mailMessage = None
self.mailMessageUUID = mailMessage.itsUUID
- self.mailMessage = None
+ self.sent = False
#in thread
def sendMail(self):
if __debug__:
- self.printCurrentView("sendmail")
+ self.printCurrentView("sendMail")
reactor.callFromThread(self.__sendMail)
@@ -59,94 +62,135 @@
if __debug__:
self.printCurrentView("__sendMail")
- self.__getMessageAndAccount()
+ self.__getKinds()
""" Refresh our view before adding items to our mail Message
and commiting. Will not cause merge conflicts since
no data changed in view in yet """
self.view.commit()
- username = self.account.username
- passsword = self.account.password
- host = self.account.host
- port = self.account.port
- portSSL = self.account.portSSL
- useSSL = self.account.useSSL
- useAuth = self.account.useAuth
+ username = self.account.username
+ password = self.account.password
+ host = self.account.host
+ port = self.account.port
+ useSSL = self.account.useSSL
+ useAuth = self.account.useAuth
authRequired = True
- sslRequired = False
-
- if useSSL = 'SSL':
- sslRequired = True
+ sslContext = None
if not useAuth:
authRequired = False
- username = None
- password = None
+ username = None
+ password = None
+
+ if useSSL:
+ sslContext = ssl.ClientContextFactory(useM2=1)
self.mailMessage.outgoingMessage(account=self.account)
messageObject = message.kindToMessageObject(self.mailMessage)
messageText = messageObject.as_string()
- self.mailMessage.rfc2882Message = message.strToText("rfc2822Message", messageText)
-
- msg = StringIO(messageText)
+ self.mailMessage.rfc2882Message = message.strToText(self.mailMessage, "rfc2822Message", messageText)
d = defer.Deferred().addCallbacks(self.__mailSuccess, self.__mailFailure)
+ msg = StringIO(messageText)
+
+ to_addrs = []
- #XXX: perhaps commit here
+ for address in self.mailMessage.toAddress:
+ to_addrs.append(address.emailAddress)
- #XXX: Look in to Bcc Cc
- to_addrs = messageObject['To']
- from_addr = messageObject['From']
+ if self.mailMessage.replyToAddress is not None:
+ from_addr = self.mailMessage.replyToAddress.emailAddress
+
+ else:
+ from_addr = self.mailMessage.fromAddress.emailAddress
finally:
self.restorePreviousView()
- if useSSL = 'SSL':
- factory = smtp.ESMTPSenderFactory(username, password, from_addr, to_addrs, msg, d,
- 0, requireAuthentication=authRequired, requireTransportSecurity=False)
-
- """Won't see StartTLS here"""
- reactor.connectSSL(host, portSSL, factory,
- ssl.ClientContextFactory(useM2=1))
-
+ factory = smtp.ESMTPSenderFactory(username, password, from_addr, to_addrs, msg, d,
+ 0, contextFactory=sslContext, requireAuthentication=authRequired,
+ requireTransportSecurity=False)
+ #XXX: Is this correct
+ if useSSL:
+ reactor.connectSSL(host, port, factory, sslContext)
else:
- #pass the context Factory in trySSL
- factory = smtp.ESMTPSenderFactory(username, password, from_addr, to_addrs, msg, d,
- 0, requireAuthentication=authRequired, requireTransportSecurity=False)
-
reactor.connectTCP(host, port, factory)
- """
- Set the mail as sent
- set dateSent perhaps (need a string api for date sent)
- commit mail
- """
def __mailSuccess(self, result):
- addrs = []
+ self.setViewCurrent()
+
+ try:
+ if __debug__:
+ self.printCurrentView("__mailSuccess")
+
+ addrs = []
+
+ for address in result[1]:
+ addrs.append(address[0])
+
+ str = "recipients"
+
+ if len(addrs) == 1:
+ str = "recipient"
- for address in result[1]:
- addrs.append(address[0])
+ info = "SMTP Message sent to %d %s [%s]" % (result[0], str, ", ".join(addrs))
+ self.log.info(info)
- self.log.info("SMTP Message sent to %d recipients[%s]" % (result[0], ", ".join(addrs))
+ self.mailMessage.dateSent = DateTime.now()
+ self.mailMessage.dateSentString = message.dateTimeToRFC2882Date(DateTime.now())
- date = DateTime.now()
- self.mailMessage.dateSent = date
- self.mailMessage.dateSentString = message.dateTimeToRFC2882Date(date)
+ self.mailMessage.deliveryExtension.sendSucceeded()
+ self.sent = True
- self.mailMessage.deliveryExtension.sendSucceeded()
+ finally:
+ self.restorePreviousView()
- ### NOW Commit the message in a viewThread
+ """Commit the view in a thread to prevent blocking"""
+ self.commitView(True)
- #TODO: Figure out what exc is for all cases
def __mailFailure(self, exc):
- self.log.error("SMTP send failed: %s" % exc)
+ self.setViewCurrent()
+
+ try:
+ if __debug__:
+ self.printCurrentView("__mailFailure")
+
+ print exc
+ self.log.error("SMTP send failed: %s" % exc)
+
+ self.mailMessage.deliveryExtension.sendFailed()
+ self.sent = False
+
+ finally:
+ self.restorePreviousView()
+
+ """Commit the view in a thread to prevent blocking"""
+ self.commitView(True)
- self.mailMessage.deliveryExtension.sendFailed()
- ### Now Commit then post a event back to Don to Display
- def __getMessageAndAccount(self):
+ def _viewCommitSuccess(self):
+ """
+ Overides C{RepositoryView.AbstractRepositoryViewManager}.
+ It posts a commit event to the GUI thread, unpins the C{SMTPAccountKind} and
+ C{MailMessageKind} from memory, and writes commit info to the logger
+ @return: C{None}
+ """
+
+ #XXX: Post a failure event back to the Gui
+ #XXX: Could just look at the message Delivery Extension state as well
+ if not self.sent:
+ pass
+
+ self.account.setPinned(False)
+ self.mailMessage.setPinned(False)
+ self.account = None
+ self.mailMessage = None
+
+ Globals.wxApplication.PostAsyncEvent(Globals.repository.commit)
+
+ def __getKinds(self):
accountKind = Mail.MailParcel.getSMTPAccountKind()
self.account = accountKind.findUUID(self.accountUUID)
@@ -155,11 +199,10 @@
self.mailMessage = mailMessageKind.findUUID(self.mailMessageUUID)
if self.account is None:
- raise SMTPException("No Account for UUID: %s" % self.account.itsUUID)
+ raise SMTPException("No Account for UUID: %s" % self.accountUUID)
if self.mailMessage is None:
- raise SMTPException("No MailMessage for UUID: %s" % self.mailMessage.itsUUID)
+ raise SMTPException("No MailMessage for UUID: %s" % self.mailMessageUUID)
self.account.setPinned()
self.mailMessage.setPinned()
-
More information about the Commits
mailing list