Exemplo n.º 1
0
 def test_makeHeader(self):
     e = mimeutil.EmailAddress(
         '  =?ISO-8859-1?Q?C=E9sar______?= fu   bar  <*****@*****.**>'
     )
     header = e.makeHeader('To')
     e2 = mimeutil.EmailAddress(header.encode())
     self.assertEquals(e, e2)
Exemplo n.º 2
0
 def test_slotData(self):
     """
     Verify that L{DraftComposeFragment.slotData} returns a dictionary
     which reflects the message which was used as the draft.
     """
     subject = u'subject text'
     body = u'hello, world?\n'
     to = u'*****@*****.**'
     cc = u'*****@*****.**'
     bcc = u'*****@*****.**'
     message = createMessage(
         self.composer,
         None,
         None,
         self.defaultFromAddress,
         [mimeutil.EmailAddress(to, mimeEncoded=False)],
         subject,
         body,
         [mimeutil.EmailAddress(cc, mimeEncoded=False)],
         [mimeutil.EmailAddress(bcc, mimeEncoded=False)],
         [],
     )
     fragment = self.messageDetail._composeSomething(draft=message)
     slotData = fragment.slotData()
     self.assertEqual(slotData['to'], to)
     self.assertEqual(slotData['from'][0], self.defaultFromAddress)
     self.assertEqual(slotData['subject'], subject)
     self.assertEqual(slotData['message-body'], body)
     self.assertEqual(slotData['cc'], cc)
Exemplo n.º 3
0
 def test_ListHeader(self):
     emails = []
     emails.append(
         mimeutil.EmailAddress(
             '  =?ISO-8859-1?Q?C=E9sar______?= fu   bar  <*****@*****.**>'
         ))
     emails.append(mimeutil.EmailAddress(' n o  name  @ examplE.com  '))
     header = mimeutil.makeEmailListHeader(emails, 'To')
     parsed = mimeutil.parseEmailAddresses(header.encode())
     self.assertEquals(emails, parsed)
Exemplo n.º 4
0
 def test_flattenEmailAddresses(self):
     """
     Test that L{xquotient.mimeutil.flattenEmailAddresses} works as
     expected
     """
     self.assertEquals(
         mimeutil.flattenEmailAddresses(
             (mimeutil.EmailAddress('One <one@two>'),
              mimeutil.EmailAddress('two@three'))),
         'One <one@two>, two@three')
Exemplo n.º 5
0
    def test_invoke(self):
        """
        L{ComposeFragment.invoke} accepts a browser-generated structure
        representing the values in the compose form, coerces it according to
        the L{Parameters} it defines, and passes the result to the LiveForm
        callable.
        """
        # The from addresses are web ids for FromAddress items.
        fromAddr = IWebTranslator(self.userStore).toWebID(self.defaultFromAddr)

        # Override the callable to see what happens.
        sent = []
        expectedResult = object()

        def fakeSend(fromAddress, toAddresses, subject, messageBody, cc, bcc,
                     files, draft):
            sent.append((fromAddress, toAddresses, subject, messageBody, cc,
                         bcc, files, draft))
            return expectedResult

        self.cf.callable = fakeSend

        toAddresses = [
            mimeutil.EmailAddress(u'*****@*****.**', False),
            mimeutil.EmailAddress(u'*****@*****.**', False)
        ]
        subject = u'Hello World'
        body = u'How are you'
        cc = [mimeutil.EmailAddress(u'*****@*****.**', False)]
        bcc = [mimeutil.EmailAddress(u'*****@*****.**', False)]
        draft = True

        invokeDeferred = self.cf.invoke({
            u'fromAddress': [fromAddr],
            u'toAddresses': [mimeutil.flattenEmailAddresses(toAddresses)],
            u'subject': [subject],
            u'messageBody': [body],
            u'cc': [mimeutil.flattenEmailAddresses(cc)],
            u'bcc': [mimeutil.flattenEmailAddresses(bcc)],
            u'draft': [draft]
        })

        def cbInvoked(invokeResult):
            self.assertEquals(
                sent,
                [(self.defaultFromAddr, toAddresses, subject, body, cc, bcc,
                  (), draft)])
            self.assertIdentical(invokeResult, expectedResult)

        invokeDeferred.addCallback(cbInvoked)
        return invokeDeferred
 def composeFragFactory(composer):
     return AddrPassthroughComposeFragment(
         composer,
         recipients={
             'to':
             [mimeutil.EmailAddress(e, False) for e in toAddresses]
         })
Exemplo n.º 7
0
    def test_redirectHeaderOrdering(self):
        """
        Test that Resent headers get added after Received headers but
        before the rest.
        """
        msgtext = """\
Received: from bob by example.com with smtp (SuparMTA 9.99)
        id 1BfraZ-0001D0-QA
        for [email protected]; Thu, 01 Jul 2004 02:46:15 +0000
received: from bob by example.com with smtp (SuparMTA 9.99)
        id 1BfraZ-0001D0-QA
        for [email protected]; Thu, 01 Jul 2004 02:46:17 +0000
From: <*****@*****.**>
To: <*****@*****.**>
Subject: Hi

Hi
""".replace('\n', '\r\n')

        class StubMsgFile:
            def open(self):
                return StringIO(msgtext)

        message = StubStoredMessageAndImplAndSource(store=self.userStore)
        message.__dict__['_source'] = StubMsgFile()
        msg = self.composer.createRedirectedMessage(
            self.defaultFromAddr,
            [mimeutil.EmailAddress(u'testuser@localhost', mimeEncoded=False)],
            message)
        m = Parser.Parser().parse(msg.impl.source.open())
        self.assertEqual(len(m._headers), 9)
        self.assertEqual(m._headers[0][0].lower(), "received")
        self.assertEqual(m._headers[6][0].lower(), "from")
Exemplo n.º 8
0
    def test_setStatus(self):
        """
        Test that statuses requested for parent messages get set after
        the created message is sent.
        """
        # (bypass Item.__setattr__)
        object.__setattr__(self.composer, 'sendMessage',
                           lambda fromA, toA, msg: None)

        class MsgStub:
            impl = MIMEPart()
            statuses = None

            def addStatus(self, status):
                if self.statuses is None:
                    self.statuses = [status]
                else:
                    self.statuses.append(status)

        parent = MsgStub()
        parent.impl.headers = [
            Header("message-id", "<*****@*****.**>"),
            Header("references", "<*****@*****.**>"),
            Header("references", "<*****@*****.**>")
        ]

        toAddresses = [
            mimeutil.EmailAddress('*****@*****.**', mimeEncoded=False)
        ]
        cf = self.msgDetail._composeSomething(toAddresses, u'Sup dood',
                                              u'A body', [], parent,
                                              REPLIED_STATUS)
        cf._sendOrSave(self.store.findFirst(smtpout.FromAddress), toAddresses,
                       u'Sup dood', u'A body', [], [], [], False)
        self.assertEqual(parent.statuses, [REPLIED_STATUS])
Exemplo n.º 9
0
 def _createCCMessage(self):
     """
     Use L{xquotient.mimebakery.createMessage} to make a
     message with a BCC
     """
     return self._createMessage(
         cc=[mimeutil.EmailAddress('*****@*****.**', mimeEncoded=False)])
Exemplo n.º 10
0
    def test_createMessageWrapsLines(self):
        """
        Ensure that the text of an outgoing message is wrapped to 78
        characters and that its MIME type is 'text/plain; format=flowed'.
        """
        self.cf._sendOrSave(fromAddress=self.defaultFromAddr,
                            toAddresses=[
                                mimeutil.EmailAddress(u'[email protected]',
                                                      mimeEncoded=False)
                            ],
                            subject=u'The subject of the message.',
                            messageBody=u' '.join([u'some words'] * 1000),
                            cc=[],
                            bcc=[],
                            files=[],
                            draft=False)

        msg = self.userStore.findUnique(
            smtpout.DeliveryToAddress)._getMessageSource()
        textPart = Parser.Parser().parse(msg)
        self.assertEqual(textPart.get_content_type(), "text/plain")
        self.assertEqual(textPart.get_param("format"), "flowed")
        body = textPart.get_payload().decode("quoted-printable")
        maxLineLength = max([len(line) for line in body.split("\n")])
        self.failIf(maxLineLength > 78)
Exemplo n.º 11
0
    def test_redirectRelatedAddresses(self):
        """
        Test that an outgoing redirected message has the resent from/to
        addresses stored
        """
        message = StubStoredMessageAndImplAndSource(store=self.userStore)

        RESENT_TO_ADDRESS = mimeutil.EmailAddress(u'Joe <joe@nowhere>', False)
        self.composer.redirect(self.defaultFromAddr, [RESENT_TO_ADDRESS],
                               message)

        msg = self.userStore.findUnique(exmess.Message)

        def checkCorrespondents(relation, address):
            self.assertEquals(
                self.userStore.query(
                    exmess.Correspondent,
                    attributes.AND(
                        exmess.Correspondent.message == msg,
                        exmess.Correspondent.address == address,
                        exmess.Correspondent.relation == relation)).count(), 1)

        checkCorrespondents(exmess.RESENT_FROM_RELATION,
                            self.defaultFromAddr.address)
        checkCorrespondents(exmess.RESENT_TO_RELATION, RESENT_TO_ADDRESS.email)
Exemplo n.º 12
0
    def relatedAddresses(self):
        """
        Implement L{IMessageData.relatedAddresses} by looking at relevant
        RFC2822 headers for sender and recipient addresses.
        """
        for header in (u'from', u'sender', u'reply-to'):
            try:
                v = self.getHeader(header)
            except equotient.NoSuchHeader:
                continue

            email = mimeutil.EmailAddress(v, mimeEncoded=False)
            yield (exmess.SENDER_RELATION, email)
            break

        for header, relationship in [(u'cc', exmess.COPY_RELATION),
                                     (u'to', exmess.RECIPIENT_RELATION),
                                     (u'bcc', exmess.BLIND_COPY_RELATION),
                                     (u'resent-to', exmess.RESENT_TO_RELATION),
                                     (u'resent-from',
                                      exmess.RESENT_FROM_RELATION)]:
            try:
                v = self.getHeader(header)
            except equotient.NoSuchHeader:
                pass
            else:
                for addressObject in mimeutil.parseEmailAddresses(
                        v, mimeEncoded=False):
                    yield (relationship, addressObject)
Exemplo n.º 13
0
 def test_cmp(self):
     self.assertEquals(mimeutil.EmailAddress('    '),
                       mimeutil.EmailAddress(''))
     self.assertEquals(mimeutil.EmailAddress('Fu@bAr'),
                       mimeutil.EmailAddress('  fu  @ bar  '))
     self.assertEquals(mimeutil.EmailAddress('bleh <Fu@bAr>'),
                       mimeutil.EmailAddress(('  bleh  ', '  fu  @ bar  ')))
     self.assertNotEquals(mimeutil.EmailAddress('bleh <Fu@bAr>'),
                          mimeutil.EmailAddress('  fu  @ bar  '))
Exemplo n.º 14
0
 def test_createMessageHonorsBCC(self):
     """
     Sending a message through the compose UI should honor the BCC
     addresses we give to it
     """
     sendMail(
         self.cf._savedDraft, self.composer, self.cabinet, None, None,
         self.defaultFromAddr,
         [mimeutil.EmailAddress('*****@*****.**', mimeEncoded=False)], u'',
         u'', [], [
             mimeutil.EmailAddress('*****@*****.**', mimeEncoded=False),
             mimeutil.EmailAddress('*****@*****.**', mimeEncoded=False)
         ], u'')
     self.assertEquals(
         list(
             self.userStore.query(
                 smtpout.DeliveryToAddress).getColumn('toAddress')),
         ['*****@*****.**', '*****@*****.**', '*****@*****.**'])
Exemplo n.º 15
0
 def test_notAPerson(self):
     """
     Test L{xquotient.exmess.MessageDetail.personStanFromEmailAddress} when
     there is a L{xmantissa.people.Organizer}, but the email we give isn't
     assigned to a person
     """
     email = mimeutil.EmailAddress('foo@bar', mimeEncoded=False)
     res = self.md.personStanFromEmailAddress(email)
     self.failUnless(isinstance(res, SenderPersonFragment))
Exemplo n.º 16
0
    def test_noOrganizer(self):
        """
        Test L{xquotient.exmess.MessageDetail.personStanFromEmailAddress} when
        there is no L{xmantissa.people.Organizer} in the store
        """
        self.md.organizer = None

        email = mimeutil.EmailAddress('foo@bar', mimeEncoded=False)
        stan = self.md.personStanFromEmailAddress(email)
        self._checkNoAddressBookStan(stan, email)
Exemplo n.º 17
0
    def test_createsPlaintextMessage(self):
        """
        Test that L{mimebakery.createMessage} produces a message of
        type text/plain.
        """

        msg = createMessage(
            self.composer, None, None, self.defaultFromAddr,
            [mimeutil.EmailAddress('*****@*****.**', mimeEncoded=False)],
            u'Sup dood', u'A body', u'', u'', u'')

        self.assertEqual(msg.impl.getContentType(), 'text/plain')
Exemplo n.º 18
0
 def test_createReplyNoMessageID(self):
     """
     Test replying to messages with no message ID.
     """
     parent = MsgStub()
     parent.impl.headers = []
     msg = createMessage(
         self.composer, self.cabinet, parent, self.defaultFromAddr,
         [mimeutil.EmailAddress('*****@*****.**', mimeEncoded=False)],
         u'Sup dood', u'A body', (), (), u'')
     self.assertEqual([h.value for h in msg.impl.getHeaders('References')],
                      [])
Exemplo n.º 19
0
 def test_createMessageHonorsSmarthostFromAddress(self):
     """
     Sending a message through the Compose UI should honor the from
     address we give to it
     """
     self.defaultFromAddr.address = u'*****@*****.**'
     msg = createMessage(
         self.composer, self.cabinet, None, self.defaultFromAddr,
         [mimeutil.EmailAddress('*****@*****.**', mimeEncoded=False)],
         u'Sup dood', u'A body', (), (), u'')
     file = msg.impl.source.open()
     msg = Parser.Parser().parse(file)
     self.assertEquals(msg["from"], '*****@*****.**')
Exemplo n.º 20
0
    def test_redirectNameAddr(self):
        """
        Test that L{compose.Composer.redirect} removes the display name
        portion of an email address if present before trying to deliver
        directed mail to it
        """
        message = StubStoredMessageAndImplAndSource(store=self.userStore)
        msg = self.composer.redirect(
            self.defaultFromAddr,
            [mimeutil.EmailAddress(u'Joe <joe@nowhere>', mimeEncoded=False)],
            message)

        self.assertEquals(list(self.reactor.factory.toEmail), ['joe@nowhere'])
Exemplo n.º 21
0
 def _createMessageWithFiles(self, files):
     """
     Create a message with attachments corresponding to the
     L{xquotient.compose.File} items C{files}
     """
     return createMessage(
         self.composer,
         self.cabinet,
         None,
         self.defaultFromAddr,
         [mimeutil.EmailAddress('*****@*****.**', mimeEncoded=False)],
         u'subject',
         u'body', (), (),
         files=list(f.storeID for f in files))
Exemplo n.º 22
0
    def test_aPerson(self):
        """
        Test L{xquotient.exmess.MessageDetail.personStanFromEmailAddress} when
        there is a L{xmantissa.people.Organizer}, and the email we give is
        assigned to a person
        """
        email = mimeutil.EmailAddress('foo@bar', mimeEncoded=False)

        people.EmailAddress(store=self.store,
                            address=u'foo@bar',
                            person=people.Person(store=self.store))

        res = self.md.personStanFromEmailAddress(email)
        self.failUnless(isinstance(res, people.PersonFragment))
Exemplo n.º 23
0
 def test_createMessageNotIncoming(self):
     """
     Verify that a message composed via the compose form does not deposit
     anything into the 'incoming' state, so the spam filter will not be
     triggered.
     """
     sq = exmess.MailboxSelector(self.userStore)
     msg = createMessage(
         self.composer, self.cabinet, None, self.defaultFromAddr,
         [mimeutil.EmailAddress('*****@*****.**', mimeEncoded=False)],
         u'Sup dood', u'A body', u'', u'', u'')
     sq.refineByStatus(exmess.INCOMING_STATUS)
     self.assertEquals(list(sq), [])
     self.assertEquals(msg.hasStatus(exmess.CLEAN_STATUS), False)
     self.failIf(msg.shouldBeClassified)
Exemplo n.º 24
0
 def test_createRedirectedMessage(self):
     """
     Test that L{compose.Composer.createRedirectedMessage} sets the right
     headers
     """
     message = StubStoredMessageAndImplAndSource(store=self.userStore)
     msg = self.composer.createRedirectedMessage(
         self.defaultFromAddr,
         [mimeutil.EmailAddress(u'testuser@localhost', mimeEncoded=False)],
         message)
     m = Parser.Parser().parse(msg.impl.source.open())
     self.assertEquals(m['Resent-To'], 'testuser@localhost')
     self.assertEquals(m['Resent-From'], self.defaultFromAddr.address)
     self.failIfEqual(m['Resent-Date'], None)
     self.failIfEqual(m['Resent-Message-ID'], None)
Exemplo n.º 25
0
    def _createMessage(self, cc=(), bcc=()):
        """
        Use L{xquotient.mimebakery.createMessage} to make a
        simple message, optionally with CC/BCC headers set

        @param cc: addresses to CC the message to.  defaults to no addresses
        @type cc: sequence of L{xquotient.mimeutils.EmailAddress}
        @param bcc: addresses to BCC the message to.  defaults to no addresses
        @type bcc: sequence of L{xquotient.mimeutils.EmailAddress}

        @return: L{xquotient.exmess.Message}
        """
        return createMessage(
            self.composer, self.cabinet, None, self.defaultFromAddr,
            [mimeutil.EmailAddress('*****@*****.**', mimeEncoded=False)], u'',
            u'', cc, bcc, u'')
Exemplo n.º 26
0
 def _parseTestCase(self, input, display, email, anyDisplayName,
                    pseudoFormat, localpart, domain):
     """
     Parse the given input and assert that the attributes of the resulting
     L{mimeutil.EmailAddress} are equal to the given values.
     """
     e = mimeutil.EmailAddress(input)
     self.assertEquals(e.display, display)
     self.failUnless(isinstance(e.display, unicode))
     self.assertEquals(e.email, email)
     self.failUnless(isinstance(e.email, unicode))
     self.assertEquals(e.anyDisplayName(), anyDisplayName)
     self.failUnless(isinstance(e.anyDisplayName(), unicode))
     self.assertEquals(e.pseudoFormat(), pseudoFormat)
     self.failUnless(isinstance(e.pseudoFormat(), unicode))
     self.assertEquals(e.localpart, localpart)
     self.failUnless(isinstance(e.localpart, unicode))
     self.assertEquals(e.domain, domain)
     self.failUnless(isinstance(e.domain, unicode))
Exemplo n.º 27
0
    def test_redirect(self):
        """
        Test L{compose.Composer.redirect}
        """
        message = StubStoredMessageAndImplAndSource(store=self.userStore)
        msg = self.composer.redirect(
            self.defaultFromAddr,
            [mimeutil.EmailAddress(u'testuser@localhost', mimeEncoded=False)],
            message)

        self.assertEquals(str(self.reactor.factory.fromEmail),
                          self.defaultFromAddr.address)

        self.assertEquals(list(self.reactor.factory.toEmail),
                          ['testuser@localhost'])

        m = Parser.Parser().parse(
            self.userStore.findUnique(exmess.Message).impl.source.open())

        self.assertEquals(m['Resent-From'], self.defaultFromAddr.address)
        self.assertEquals(m['Resent-To'], 'testuser@localhost')
        self.assertEquals(message.statuses, [exmess.REDIRECTED_STATUS])
Exemplo n.º 28
0
 def test_createReply(self):
     """
     Ensure that References and In-Reply-To headers are added to
     outgoing messages.
     """
     parent = MsgStub()
     parent.impl.headers = [
         Header("message-id", "<*****@*****.**>"),
         Header("references", "<*****@*****.**>"),
         Header("references", "<*****@*****.**>")
     ]
     msg = createMessage(
         self.composer, self.cabinet, parent, self.defaultFromAddr,
         [mimeutil.EmailAddress('*****@*****.**', mimeEncoded=False)],
         u'Sup dood', u'A body', (), (), u'')
     self.assertEqual([h.value for h in msg.impl.getHeaders('References')],
                      [
                          "<*****@*****.**>", "<*****@*****.**>",
                          "<*****@*****.**>"
                      ])
     self.assertEqual(msg.impl.getHeader("In-Reply-To"),
                      "<*****@*****.**>")
Exemplo n.º 29
0
    def test_clientFacingAPISend(self):
        """
        Verify that the client-facing '_sendOrSave' method, invoked by the
        liveform, generates a sent message when told to send the message.

        This is a white-box test.
        """
        self.cf._sendOrSave(fromAddress=self.defaultFromAddr,
                            toAddresses=[
                                mimeutil.EmailAddress(u'[email protected]',
                                                      mimeEncoded=False)
                            ],
                            subject=u'The subject of the message.',
                            messageBody=u'The body of the message.',
                            cc=[],
                            bcc=[],
                            files=[],
                            draft=False)
        m = self.userStore.findUnique(exmess.Message)
        self.assertEquals(set(m.iterStatuses()),
                          set([exmess.UNREAD_STATUS, exmess.OUTBOX_STATUS]))
        nd = self.userStore.findUnique(smtpout.DeliveryToAddress)
        self.assertIdentical(nd.message, m)
Exemplo n.º 30
0
    def sendmail(self):
        """
        Send this queued message.

        @param fromAddress: An optional address to use in the SMTP
            conversation.
        """
        fromAddress = self.fromAddress
        if fromAddress is None:
            fromAddress = FromAddress.findDefault(self.store)

        if fromAddress.smtpHost:
            return _esmtpSendmail(fromAddress.smtpUsername,
                                  fromAddress.smtpPassword,
                                  fromAddress.smtpHost, fromAddress.smtpPort,
                                  fromAddress.address, [self.toAddress],
                                  self._getMessageSource())
        else:
            d = self.getMailExchange(
                mimeutil.EmailAddress(self.toAddress,
                                      mimeEncoded=False).domain)

            def sendMail(mx):
                host = str(mx.name)
                log.msg(interface=iaxiom.IStatEvent,
                        stat_messagesSent=1,
                        userstore=self.store)
                return smtp.sendmail(
                    host,
                    fromAddress.address,
                    [self.toAddress],
                    # XXX
                    self._getMessageSource())

            d.addCallback(sendMail)
            return d