def decorate_message(self, event, message, decorates=None):
        if event.realm == 'ticket':
            if 'status' in event.changes:
                action = 'Status -> %s' % (event.target['status'])
            template = NewTextTemplate(
                self.ticket_email_subject.encode('utf8'))
            # Create a fallback for invalid custom Genshi template in option.
            default_template = NewTextTemplate(
                Option.registry[
                    ('announcer', 'ticket_email_subject')
                ].default.encode('utf8'))
            try:
                subject = template.generate(
                    ticket=event.target,
                    event=event,
                    action=event.category
                ).render('text', encoding=None)
            except TemplateError:
                # Use fallback template.
                subject = default_template.generate(
                    ticket=event.target,
                    event=event,
                    action=event.category
                ).render('text', encoding=None)

            prefix = self.config.get('announcer', 'email_subject_prefix')
            if prefix == '__default__':
                prefix = '[%s] ' % self.env.project_name
            if prefix:
                subject = "%s%s" % (prefix, subject)
            if event.category != 'created':
                subject = 'Re: %s' % subject
            set_header(message, 'Subject', subject)

        return next_decorator(event, message, decorates)
Пример #2
0
    def decorate_message(self, event, message, decorates=None):
        if event.realm == 'ticket':
            for k in ('id', 'priority', 'severity'):
                name = 'X-Announcement-%s'%k.capitalize()
                set_header(message, name, event.target[k])

        return next_decorator(event, message, decorates)
Пример #3
0
    def decorate_message(self, event, message, decorates=None):
        if event.realm == 'ticket':
            for k in ('id', 'priority', 'severity'):
                name = 'X-Announcement-%s' % k.capitalize()
                set_header(message, name, event.target[k])

        return next_decorator(event, message, decorates)
Пример #4
0
    def decorate_message(self, event, message, decorates=None):
        if event.realm == 'ticket':
            if 'status' in event.changes:
                action = 'Status -> %s' % (event.target['status'])
            template = NewTextTemplate(
                self.ticket_email_subject.encode('utf8'))
            # Create a fallback for invalid custom Genshi template in option.
            default_template = NewTextTemplate(Option.registry[(
                'announcer', 'ticket_email_subject')].default.encode('utf8'))
            try:
                subject = template.generate(ticket=event.target,
                                            event=event,
                                            action=event.category).render(
                                                'text', encoding=None)
            except TemplateError:
                # Use fallback template.
                subject = default_template.generate(
                    ticket=event.target, event=event,
                    action=event.category).render('text', encoding=None)

            prefix = self.config.get('announcer', 'email_subject_prefix')
            if prefix == '__default__':
                prefix = '[%s] ' % self.env.project_name
            if prefix:
                subject = "%s%s" % (prefix, subject)
            if event.category != 'created':
                subject = 'Re: %s' % subject
            set_header(message, 'Subject', subject)

        return next_decorator(event, message, decorates)
Пример #5
0
 def decorate_message(self, event, message, decorates=None):
     if event.realm == "acct_mgr":
         prjname = self.env.project_name
         subject = '[%s] %s: %s' \
                   % (prjname, event.category, event.username)
         set_header(message, 'Subject', subject)
     return next_decorator(event, message, decorates)
Пример #6
0
 def decorate_message(self, event, message, decorates=None):
     if event.realm == "acct_mgr":
         prjname = self.env.project_name
         subject = '[%s] %s: %s' \
                   % (prjname, event.category, event.username)
         set_header(message, 'Subject', subject)
     return next_decorator(event, message, decorates)
Пример #7
0
 def decorate_message(self, event, message, decorates=None):
     if event.realm == "blog":
         template = NewTextTemplate(self.blog_email_subject.encode('utf8'))
         subject = template.generate(blog=event.blog_post,
                                     action=event.category).render(
                                         'text', encoding=None)
         set_header(message, 'Subject', subject)
     return next_decorator(event, message, decorates)
Пример #8
0
 def decorate_message(self, event, message, decorates=None):
     if event.realm == "blog":
         template = NewTextTemplate(self.blog_email_subject.encode('utf8'))
         subject = template.generate(
             blog=event.blog_post,
             action=event.category
         ).render('text', encoding=None)
         set_header(message, 'Subject', subject)
     return next_decorator(event, message, decorates)
 def decorate_message(self, event, message, decorates=None):
     for k, v in {'Cc': self.always_cc, 'Bcc': self.always_bcc}.items():
         if v:
             self.log.debug("StaticEmailDecorator added '%s' because of "
                            "rule: email_always_%s", v, k.lower()),
             if message[k] and str(message[k]).split(','):
                 recipients = ", ".join([str(message[k]), v])
             else:
                 recipients = v
             set_header(message, k, recipients)
     return next_decorator(event, message, decorates)
Пример #10
0
 def decorate_message(self, event, message, decorates=None):
     for k, v in {'Cc': self.always_cc, 'Bcc': self.always_bcc}.items():
         if v:
             self.log.debug("StaticEmailDecorator added '%s' "
                            "because of rule: email_always_%s" %
                            (v, k.lower())),
             if message[k] and len(str(message[k]).split(',')) > 0:
                 recips = ", ".join([str(message[k]), v])
             else:
                 recips = v
             set_header(message, k, recips)
     return next_decorator(event, message, decorates)
    def decorate_message(self, event, message, decorates=None):
        """
        Added headers to the outgoing email to track it's relationship
        with a resource.  Reply-To will encode a UID as a email parameter
        so replies to the resource announcement can be handled by an 
        ITracGateEmailHandler.  
        """
        if event.realm in self.reply_to_realms:
            name, email_addr = parseaddr(str(message['Reply-To']))
            uid = uid_encode(self.env.abs_href(), event.realm, event.target)

            m = ADDR_REGEX.match(email_addr)
            new_email_addr = '%s+%s@%s'%(m.group(1), uid, m.group(2))
            new_addr = formataddr((name, new_email_addr))
            set_header(message, 'Reply-To', new_email_addr)

        return next_decorator(event, message, decorates)
Пример #12
0
    def decorate_message(self, event, message, decorates=None):
        if event.realm == 'wiki':
            template = NewTextTemplate(self.wiki_email_subject.encode('utf8'))
            subject = template.generate(page=event.target,
                                        event=event,
                                        action=event.category).render(
                                            'text', encoding=None)

            prefix = self.config.get('announcer', 'email_subject_prefix')
            if prefix == '__default__':
                prefix = '[%s] ' % self.env.project_name
            if prefix:
                subject = "%s%s" % (prefix, subject)
            if event.category != 'created':
                subject = 'Re: %s' % subject
            set_header(message, 'Subject', subject)

        return next_decorator(event, message, decorates)
    def decorate_message(self, event, message, decorates=None):
        if event.realm == 'wiki':
            template = NewTextTemplate(self.wiki_email_subject.encode('utf8'))
            subject = template.generate(
                page=event.target,
                event=event,
                action=event.category
            ).render('text', encoding=None)

            prefix = self.config.get('announcer', 'email_subject_prefix')
            if prefix == '__default__':
                prefix = '[%s] ' % self.env.project_name
            if prefix:
                subject = "%s%s" % (prefix, subject)
            if event.category != 'created':
                subject = 'Re: %s' % subject
            set_header(message, 'Subject', subject)

        return next_decorator(event, message, decorates)
Пример #14
0
 def decorate_message(self, event, message, decorates=None):
     if event.realm == "bitten":
         build_id = str(event.target.id)
         build_link = self._build_link(event.target)
         subject = '[%s Build] %s [%s] %s' % (self.readable_states.get(
             event.target.status,
             event.target.status), self.env.project_name, event.target.rev,
                                              event.target.config)
         set_header(message, 'X-Trac-Build-ID', build_id)
         set_header(message, 'X-Trac-Build-URL', build_link)
         set_header(message, 'Subject', subject)
     return next_decorator(event, message, decorates)
Пример #15
0
 def decorate_message(self, event, message, decorates=None):
     if event.realm == "bitten":
         build_id = str(event.target.id)
         build_link = self._build_link(event.target)
         subject = "[%s Build] %s [%s] %s" % (
             self.readable_states.get(event.target.status, event.target.status),
             self.env.project_name,
             event.target.rev,
             event.target.config,
         )
         set_header(message, "X-Trac-Build-ID", build_id)
         set_header(message, "X-Trac-Build-URL", build_link)
         set_header(message, "Subject", subject)
     return next_decorator(event, message, decorates)
Пример #16
0
    def decorate_message(self, event, message, decorates=None):
        """
        Added headers to the outgoing email to track it's relationship
        with a ticket.

        References, In-Reply-To and Message-ID are just so email clients can
        make sense of the threads.
        """
        if to_unicode(event.realm) in self.supported_realms:
            uid = uid_encode(self.env.abs_href(), event.realm, event.target)
            email_from = self.config.get('announcer', 'email_from', 'localhost')
            _, email_addr = parseaddr(email_from)
            host = re.sub('^.+@', '', email_addr)
            mymsgid = msgid(uid, host)
            if event.category == 'created':
                set_header(message, 'Message-ID', mymsgid)
            else:
                set_header(message, 'In-Reply-To', mymsgid)
                set_header(message, 'References', mymsgid)

        return next_decorator(event, message, decorates)
Пример #17
0
    def decorate_message(self, event, message, decorates=None):
        """
        Added headers to the outgoing email to track it's relationship
        with a ticket.

        References, In-Reply-To and Message-ID are just so email clients can
        make sense of the threads.
        """
        if to_unicode(event.realm) in self.supported_realms:
            uid = uid_encode(self.env.abs_href(), event.realm, event.target)
            email_from = self.config.get('announcer', 'email_from',
                                         'localhost')
            _, email_addr = parseaddr(email_from)
            host = re.sub('^.+@', '', email_addr)
            mymsgid = msgid(uid, host)
            if event.category == 'created':
                set_header(message, 'Message-ID', mymsgid)
            else:
                set_header(message, 'In-Reply-To', mymsgid)
                set_header(message, 'References', mymsgid)

        return next_decorator(event, message, decorates)
 def send_as_email(self, req, sender, recipients, subject, text, mode,  *resources):
     """
     `authname` Trac username of sender
     `sender` Tuple of (real name, email address)
     `recipients` List of (real name, email address) recipient address tuples
     `subject` The e-mail subject
     `text` The text body of the e-mail
     `files` List of paths to the files to send
     """
     assert len(resources) > 0, 'Nothing to send!'
     mailsys = self.distributor(self.env)
     from_addr = sender[1]
     root = MIMEMultipart('related')
     root.set_charset(self._make_charset())
     root.preamble = 'This is a multi-part message in MIME format.'
     headers = {}
     recp = [r[1] for r in recipients]
     headers['Subject'] = subject
     headers['To'] = ', '.join(recp)
     headers['From'] = from_addr
     headers['Date'] = formatdate()
     authname = req.authname
     files = []
     links = []
     attachments = []
     mimeview = Mimeview(self.env)
     for r in resources:
         repo = RepositoryManager(self.env).get_repository(r.parent.id)
         n = repo.get_node(r.id, rev=r.version)
         files.append(n.path)
         f = os.path.join(repo.repos.path, n.path)
         if mode in (self.LINKS_ONLY, self.LINKS_ATTACHMENTS):
             links.append((req.abs_href.browser(repo.reponame or None, n.path, format='raw'), os.path.basename(f)))
         if mode in (self.ATTACHMENTS_ONLY, self.LINKS_ATTACHMENTS):
             content = n.get_content().read()                
             mtype = n.get_content_type() or mimeview.get_mimetype(f, content)
             if not mtype:
                 mtype = 'application/octet-stream'
             if '; charset=' in mtype:
                 # What to use encoding for?
                 mtype, encoding = mtype.split('; charset=', 1)
             attachments.append(os.path.basename(f))
             maintype, subtype = mtype.split('/', 1)
             part = MIMEBase(maintype, subtype)
             part.set_payload(content)
             part.add_header('content-disposition', 'attachment', filename=os.path.basename(f))
             encode_base64(part)
             root.attach(part)
     body = self._format_email(authname, sender, recipients, subject, text, mode, links, attachments)
     msg = MIMEText(body, 'html', 'utf-8')
     root.attach(msg)
     del root['Content-Transfer-Encoding']
     for k, v in headers.items():
         set_header(root, k, v)
     email = (from_addr, recp, root.as_string())
     # Write mail to /tmp
     #import logging
     #if self.log.isEnabledFor(logging.DEBUG):
     #   (fd, tmpname) = mkstemp()
     #   os.write(fd, email[2])
     #   os.close(fd)
     #   self.log.debug('Wrote mail from %s to %s to %s', email[0], email[1], tmpname)
     self.log.info('Sending mail with items %s from %s to %s', resources, from_addr, recp)
     try:
         if using_announcer:
             if mailsys.use_threaded_delivery:
                 mailsys.get_delivery_queue().put(email)
             else:
                 mailsys.send(*email)
         else:
             mailsys.send_email(*email)
     except Exception, e:
         raise TracError(e.message)
Пример #19
0
    def _do_send(self,
                 transport,
                 event,
                 format,
                 recipients,
                 formatter,
                 pubkey_ids=[]):

        output = formatter.format(transport, event.realm, format, event)

        # DEVEL: force message body plaintext style for crypto operations
        if self.crypto != '' and pubkey_ids != []:
            if self.crypto == 'sign':
                output = self.enigma.sign(output, self.private_key)
            elif self.crypto == 'encrypt':
                output = self.enigma.encrypt(output, pubkey_ids)
            elif self.crypto == 'sign,encrypt':
                output = self.enigma.sign_encrypt(output, pubkey_ids,
                                                  self.private_key)

            self.log.debug(output)
            self.log.debug(_("EmailDistributor crypto operaton successful."))
            alternate_output = None
        else:
            alternate_style = formatter.alternative_style_for(
                transport, event.realm, format)
            if alternate_style:
                alternate_output = formatter.format(transport, event.realm,
                                                    alternate_style, event)
            else:
                alternate_output = None

        # sanity check
        if not self._charset.body_encoding:
            try:
                dummy = output.encode('ascii')
            except UnicodeDecodeError:
                raise TracError(_("Ticket contains non-ASCII chars. " \
                                  "Please change encoding setting"))

        rootMessage = MIMEMultipart("related")

        headers = dict()
        if self.set_message_id:
            # A different, predictable, but still sufficiently unique
            # message ID will be generated as replacement in
            # announcer.email_decorators.generic.ThreadingEmailDecorator
            # for email threads to work.
            headers['Message-ID'] = self._message_id(event.realm)
        headers['Date'] = formatdate()
        from_header = formataddr((self.from_name
                                  or self.env.project_name, self.email_from))
        headers['From'] = from_header
        headers['To'] = '"%s"' % (self.to)
        if self.use_public_cc:
            headers['Cc'] = ', '.join([x[2] for x in recipients if x])
        headers['Reply-To'] = self.replyto
        for k, v in headers.iteritems():
            set_header(rootMessage, k, v)

        rootMessage.preamble = 'This is a multi-part message in MIME format.'
        if alternate_output:
            parentMessage = MIMEMultipart('alternative')
            rootMessage.attach(parentMessage)

            alt_msg_format = 'html' in alternate_style and 'html' or 'plain'
            msgText = MIMEText(alternate_output, alt_msg_format)
            parentMessage.attach(msgText)
        else:
            parentMessage = rootMessage

        msg_format = 'html' in format and 'html' or 'plain'
        msgText = MIMEText(output, msg_format)
        del msgText['Content-Transfer-Encoding']
        msgText.set_charset(self._charset)
        parentMessage.attach(msgText)
        decorators = self._get_decorators()
        if len(decorators) > 0:
            decorator = decorators.pop()
            decorator.decorate_message(event, rootMessage, decorators)

        recip_adds = [x[2] for x in recipients if x]
        # Append any to, cc or bccs added to the recipient list
        for field in ('To', 'Cc', 'Bcc'):
            if rootMessage[field] and \
                    len(str(rootMessage[field]).split(',')) > 0:
                for addy in str(rootMessage[field]).split(','):
                    self._add_recipient(recip_adds, addy)
        # replace with localized bcc hint
        if headers['To'] == 'undisclosed-recipients: ;':
            set_header(rootMessage, 'To', _('undisclosed-recipients: ;'))

        self.log.debug("Content of recip_adds: %s" % (recip_adds))
        package = (from_header, recip_adds, rootMessage.as_string())
        start = time.time()
        if self.use_threaded_delivery:
            self.get_delivery_queue().put(package)
        else:
            self.send(*package)
        stop = time.time()
        self.log.debug("EmailDistributor took %s seconds to send."\
                %(round(stop-start,2)))
Пример #20
0
    def _do_send(self, transport, event, format, recipients, formatter,
                 pubkey_ids=None):
        pubkey_ids = pubkey_ids or []
        # Prepare sender for use in IEmailSender component and message header.
        from_header = formataddr(
            (self.from_name and self.from_name or self.env.project_name,
             self.email_from)
        )
        headers = dict()
        headers['Message-ID'] = self._message_id(event.realm)
        headers['Date'] = formatdate()
        headers['From'] = from_header
        headers['Reply-To'] = self.reply_to

        recip_adds = [x[2] for x in recipients if x]

        if self.use_public_cc:
            headers['Cc'] = ', '.join(recip_adds)
        else:
            # Use localized Bcc: hint for default To: content.
            if self.to == self.to_default:
                headers['To'] = _("undisclosed-recipients: ;")
            else:
                headers['To'] = '"%s"' % self.to
                if self.to:
                    recip_adds += [self.to]
        if not recip_adds:
            self.log.debug("EmailDistributor stopped (no recipients).")
            return
        self.log.debug("All email recipients: %s", recip_adds)

        root_message = MIMEMultipart('related')

        # Write header data into message object.
        for k, v in headers.iteritems():
            set_header(root_message, k, v)

        output = formatter.format(transport, event.realm, format, event)

        # DEVEL: Currently crypto operations work with format text/plain only.
        alternate_output = None
        alternate_style = []
        if self.crypto != '' and pubkey_ids:
            if self.crypto == 'sign':
                output = self.enigma.sign(output, self.private_key)
            elif self.crypto == 'encrypt':
                output = self.enigma.encrypt(output, pubkey_ids)
            elif self.crypto == 'sign,encrypt':
                output = self.enigma.sign_encrypt(output, pubkey_ids,
                                                  self.private_key)
            self.log.debug(output)
            self.log.debug("EmailDistributor crypto operation successful.")
        else:
            alternate_style = formatter.alternative_style_for(
                transport,
                event.realm,
                format
            )
            if alternate_style:
                alternate_output = formatter.format(
                    transport,
                    event.realm,
                    alternate_style,
                    event
                )

        # Sanity check for suitable encoding setting.
        if not self._charset.body_encoding:
            try:
                output.encode('ascii')
            except UnicodeDecodeError:
                raise TracError(_("Ticket contains non-ASCII chars. Please "
                                  "change encoding setting"))

        root_message.preamble = "This is a multi-part message in MIME format."
        if alternate_output:
            parent_message = MIMEMultipart('alternative')
            root_message.attach(parent_message)

            alt_msg_format = 'html' in alternate_style and 'html' or 'plain'
            if isinstance(alternate_output, unicode):
                alternate_output = alternate_output.encode('utf-8')
            msg_text = MIMEText(alternate_output, alt_msg_format)
            msg_text.set_charset(self._charset)
            parent_message.attach(msg_text)
        else:
            parent_message = root_message

        msg_format = 'html' in format and 'html' or 'plain'
        if isinstance(output, unicode):
            output = output.encode('utf-8')
        msg_text = MIMEText(output, msg_format)
        del msg_text['Content-Transfer-Encoding']
        msg_text.set_charset(self._charset)
        # According to RFC 2046, the last part of a multipart message is best
        #   and preferred.
        parent_message.attach(msg_text)

        # DEVEL: Decorators can interfere with crypto operation here. Fix it.
        decorators = self._get_decorators()
        if decorators:
            decorator = decorators.pop()
            decorator.decorate_message(event, root_message, decorators)

        package = (from_header, recip_adds, root_message.as_string())
        start = time.time()
        if self.use_threaded_delivery:
            self.get_delivery_queue().put(package)
        else:
            self.send(*package)
        stop = time.time()
        self.log.debug("EmailDistributor took %s seconds to send.",
                       round(stop - start, 2))
Пример #21
0
    def decorate_message(self, event, message, decorators):
        mailer = 'AnnouncerPlugin v%s on Trac v%s' % (announcer_version,
                                                      trac_version)
        set_header(message, 'Auto-Submitted', 'auto-generated')
        set_header(message, 'Precedence', 'bulk')
        set_header(message, 'X-Announcer-Version', announcer_version)
        set_header(message, 'X-Mailer', mailer)
        set_header(message, 'X-Trac-Announcement-Realm', event.realm)
        set_header(message, 'X-Trac-Project', self.env.project_name)
        set_header(message, 'X-Trac-Version', trac_version)

        return next_decorator(event, message, decorators)
Пример #22
0
    def _do_send(self, transport, event, format, recipients, formatter,
                 pubkey_ids=[]):

        # Prepare sender for use in IEmailSender component and message header.
        from_header = formataddr(
            (self.from_name and self.from_name or self.env.project_name,
             self.email_from)
        )
        headers = dict()
        headers['Message-ID'] = self._message_id(event.realm)
        headers['Date'] = formatdate()
        headers['From'] = from_header
        headers['Reply-To'] = self.reply_to

        recip_adds = [x[2] for x in recipients if x]

        if self.use_public_cc:
            headers['Cc'] = ', '.join(recip_adds)
        else:
            # Use localized Bcc: hint for default To: content.
            if self.to == self.to_default:
                headers['To'] = _('undisclosed-recipients: ;')
            else:
                headers['To'] = '"%s"' % self.to
                if self.to:
                    recip_adds += [self.to]
        if not recip_adds:
            self.log.debug(
                "EmailDistributor stopped (no recipients)."
            )
            return
        self.log.debug("All email recipients: %s" % recip_adds)

        rootMessage = MIMEMultipart("related")
        # TODO: Is this good? (from jabber branch)
        #rootMessage.set_charset(self._charset)

        # Write header data into message object.
        for k, v in headers.iteritems():
            set_header(rootMessage, k, v)

        output = formatter.format(transport, event.realm, format, event)

        # DEVEL: Currently crypto operations work with format text/plain only.
        if self.crypto != '' and pubkey_ids != []:
            if self.crypto == 'sign':
                output = self.enigma.sign(output, self.private_key)
            elif self.crypto == 'encrypt':
                output = self.enigma.encrypt(output, pubkey_ids)
            elif self.crypto == 'sign,encrypt':
                output = self.enigma.sign_encrypt(output, pubkey_ids,
                                                     self.private_key)
            self.log.debug(output)
            self.log.debug("EmailDistributor crypto operation successful.")
            alternate_output = None
        else:
            alternate_style = formatter.alternative_style_for(
                transport,
                event.realm,
                format
            )
            if alternate_style:
                alternate_output = formatter.format(
                    transport,
                    event.realm,
                    alternate_style,
                    event
                )
            else:
                alternate_output = None

        # Sanity check for suitable encoding setting.
        if not self._charset.body_encoding:
            try:
                dummy = output.encode('ascii')
            except UnicodeDecodeError:
                raise TracError(_("Ticket contains non-ASCII chars. " \
                                  "Please change encoding setting"))

        rootMessage.preamble = 'This is a multi-part message in MIME format.'
        if alternate_output:
            parentMessage = MIMEMultipart('alternative')
            rootMessage.attach(parentMessage)

            alt_msg_format = 'html' in alternate_style and 'html' or 'plain'
            msgText = MIMEText(alternate_output, alt_msg_format)
            msgText.set_charset(self._charset)
            parentMessage.attach(msgText)
        else:
            parentMessage = rootMessage

        msg_format = 'html' in format and 'html' or 'plain'
        msgText = MIMEText(output, msg_format)
        del msgText['Content-Transfer-Encoding']
        msgText.set_charset(self._charset)
        # According to RFC 2046, the last part of a multipart message is best
        #   and preferred.
        parentMessage.attach(msgText)

        # DEVEL: Decorators can interfere with crypto operation here. Fix it.
        decorators = self._get_decorators()
        if len(decorators) > 0:
            decorator = decorators.pop()
            decorator.decorate_message(event, rootMessage, decorators)

        package = (from_header, recip_adds, rootMessage.as_string())
        start = time.time()
        if self.use_threaded_delivery:
            self.get_delivery_queue().put(package)
        else:
            self.send(*package)
        stop = time.time()
        self.log.debug("EmailDistributor took %s seconds to send."
                       % (round(stop - start, 2)))
    def decorate_message(self, event, message, decorators):
        mailer = 'AnnouncerPlugin v%s on Trac v%s' % (
            announcer_version,
            trac_version
        )
        set_header(message, 'Auto-Submitted', 'auto-generated')
        set_header(message, 'Precedence', 'bulk')
        set_header(message, 'X-Announcer-Version', announcer_version)
        set_header(message, 'X-Mailer', mailer)
        set_header(message, 'X-Trac-Announcement-Realm', event.realm)
        set_header(message, 'X-Trac-Project', self.env.project_name)
        set_header(message, 'X-Trac-Version', trac_version)

        return next_decorator(event, message, decorators)
Пример #24
0
    def _do_send(self, transport, event, format, recipients, formatter,
                 pubkey_ids=[]):

        output = formatter.format(transport, event.realm, format, event)

        # DEVEL: force message body plaintext style for crypto operations
        if self.crypto != '' and pubkey_ids != []:
            if self.crypto == 'sign':
                output = self.enigma.sign(output, self.private_key)
            elif self.crypto == 'encrypt':
                output = self.enigma.encrypt(output, pubkey_ids)
            elif self.crypto == 'sign,encrypt':
                output = self.enigma.sign_encrypt(output, pubkey_ids,
                                                     self.private_key)

            self.log.debug(output)
            self.log.debug(_("EmailDistributor crypto operaton successful."))
            alternate_output = None
        else:
            alternate_style = formatter.alternative_style_for(
                transport,
                event.realm,
                format
            )
            if alternate_style:
                alternate_output = formatter.format(
                    transport,
                    event.realm,
                    alternate_style,
                    event
                )
            else:
                alternate_output = None

        # sanity check
        if not self._charset.body_encoding:
            try:
                dummy = output.encode('ascii')
            except UnicodeDecodeError:
                raise TracError(_("Ticket contains non-ASCII chars. " \
                                  "Please change encoding setting"))

        rootMessage = MIMEMultipart("related")

        headers = dict()
        if self.set_message_id:
            # A different, predictable, but still sufficiently unique
            # message ID will be generated as replacement in
            # announcer.email_decorators.generic.ThreadingEmailDecorator
            # for email threads to work.
            headers['Message-ID'] = self._message_id(event.realm)
        headers['Date'] = formatdate()
        from_header = formataddr((
            self.from_name or self.env.project_name,
            self.email_from
        ))
        headers['From'] = from_header
        headers['To'] = '"%s"'%(self.to)
        if self.use_public_cc:
            headers['Cc'] = ', '.join([x[2] for x in recipients if x])
        headers['Reply-To'] = self.replyto
        for k, v in headers.iteritems():
            set_header(rootMessage, k, v)

        rootMessage.preamble = 'This is a multi-part message in MIME format.'
        if alternate_output:
            parentMessage = MIMEMultipart('alternative')
            rootMessage.attach(parentMessage)

            alt_msg_format = 'html' in alternate_style and 'html' or 'plain'
            msgText = MIMEText(alternate_output, alt_msg_format)
            parentMessage.attach(msgText)
        else:
            parentMessage = rootMessage

        msg_format = 'html' in format and 'html' or 'plain'
        msgText = MIMEText(output, msg_format)
        del msgText['Content-Transfer-Encoding']
        msgText.set_charset(self._charset)
        parentMessage.attach(msgText)
        decorators = self._get_decorators()
        if len(decorators) > 0:
            decorator = decorators.pop()
            decorator.decorate_message(event, rootMessage, decorators)

        recip_adds = [x[2] for x in recipients if x]
        # Append any to, cc or bccs added to the recipient list
        for field in ('To', 'Cc', 'Bcc'):
            if rootMessage[field] and \
                    len(str(rootMessage[field]).split(',')) > 0:
                for addy in str(rootMessage[field]).split(','):
                    self._add_recipient(recip_adds, addy)
        # replace with localized bcc hint
        if headers['To'] == 'undisclosed-recipients: ;':
            set_header(rootMessage, 'To', _('undisclosed-recipients: ;'))

        self.log.debug("Content of recip_adds: %s" %(recip_adds))
        package = (from_header, recip_adds, rootMessage.as_string())
        start = time.time()
        if self.use_threaded_delivery:
            self.get_delivery_queue().put(package)
        else:
            self.send(*package)
        stop = time.time()
        self.log.debug("EmailDistributor took %s seconds to send."\
                %(round(stop-start,2)))