Example #1
0
    def _NH_SIPEngineGotMessage(self, notification):
        account_manager = AccountManager()
        account = account_manager.find_account(notification.data.request_uri)

        if account is None:
            return

        data = notification.data
        content_type = data.headers.get('Content-Type', Null).content_type
        from_header = data.headers.get('From', Null)
        x_replicated_message = data.headers.get('X-Replicated-Message', Null)
        to_header = data.headers.get('To', Null)

        if x_replicated_message is Null:
            cpim_message = None
            if content_type == "message/cpim":
                try:
                    cpim_message = CPIMPayload.decode(data.body)
                except CPIMParserError:
                    log.warning(
                        'SIP message from %s to %s rejected: CPIM parse error'
                        % (from_header.uri, '%s@%s' %
                           (to_header.uri.user, to_header.uri.host)))
                    return
                body = cpim_message.content if isinstance(
                    cpim_message.content,
                    str) else cpim_message.content.decode()
                content_type = cpim_message.content_type
                sender = cpim_message.sender or from_header
                disposition = next(
                    ([item.strip() for item in header.value.split(',')]
                     for header in cpim_message.additional_headers
                     if header.name == 'Disposition-Notification'), None)
                message_id = next(
                    (header.value for header in cpim_message.additional_headers
                     if header.name == 'Message-ID'), str(uuid.uuid4()))
            else:
                payload = SimplePayload.decode(data.body, data.content_type)
                body = payload.content.decode()
                content_type = payload.content_type
                sender = from_header
                disposition = None
                message_id = str(uuid.uuid4())

            if (content_type.lower().startswith('text/')
                    and '-----BEGIN PGP MESSAGE-----' in body
                    and body.strip().endswith('-----END PGP MESSAGE-----')
                    and content_type != 'text/pgp-private-key'):
                return

            if content_type.lower() == 'text/pgp-public-key':
                return

            from blink.contacts import URIUtils
            contact, contact_uri = URIUtils.find_contact(sender.uri)
            session_manager = SessionManager()

            notification_center = NotificationCenter()
            try:
                blink_session = next(
                    session for session in self.sessions if session.reusable
                    and session.contact.settings is contact.settings)
            except StopIteration:
                if content_type.lower() in [
                        IsComposingDocument.content_type,
                        IMDNDocument.content_type
                ]:
                    return
                else:
                    blink_session = session_manager.create_session(
                        contact,
                        contact_uri, [StreamDescription('messages')],
                        account=account,
                        connect=False)

            if content_type.lower() == IsComposingDocument.content_type:
                try:
                    document = IsComposingMessage.parse(body)
                except ParserError as e:
                    log.warning('Failed to parse Is-Composing payload: %s' %
                                str(e))
                else:
                    data = NotificationData(
                        state=document.state.value,
                        refresh=document.refresh.value
                        if document.refresh is not None else 120,
                        content_type=document.content_type.value
                        if document.content_type is not None else None,
                        last_active=document.last_active.value
                        if document.last_active is not None else None,
                        sender=sender)
                    notification_center.post_notification(
                        'BlinkGotComposingIndication',
                        sender=blink_session,
                        data=data)
                return

            timestamp = str(
                cpim_message.timestamp
            ) if cpim_message is not None and cpim_message.timestamp is not None else str(
                ISOTimestamp.now())

            if account.sms.use_cpim and account.sms.enable_imdn and content_type.lower(
            ) == IMDNDocument.content_type:
                # print("-- IMDN received")
                document = IMDNDocument.parse(body)
                imdn_message_id = document.message_id.value
                imdn_status = document.notification.status.__str__()
                imdn_datetime = document.datetime.__str__()
                notification_center.post_notification(
                    'BlinkGotDispositionNotification',
                    sender=blink_session,
                    data=NotificationData(id=imdn_message_id,
                                          status=imdn_status))
                return

            message = BlinkMessage(body,
                                   content_type,
                                   sender,
                                   timestamp=timestamp,
                                   id=message_id,
                                   disposition=disposition)
            notification_center.post_notification('BlinkMessageIsParsed',
                                                  sender=blink_session,
                                                  data=message)

            if disposition is not None and 'positive-delivery' in disposition:
                # print("-- Should send delivered imdn")
                self.send_imdn_message(blink_session, message_id, timestamp,
                                       'delivered')

            self._add_contact_to_messages_group(blink_session)
            notification_center.post_notification('BlinkGotMessage',
                                                  sender=blink_session,
                                                  data=message)
        else:
            # TODO handle replicated messages
            pass