[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