Ejemplo n.º 1
0
 def test_encrypted_mail(self):
     """Test parsing of a pgp encrypted mail."""
     data = load_mail('pgp_crypted_1.eml')
     mail = MailMessage(data)
     self.assertTrue(verifyObject(IMessageParser, mail))
     self.assertTrue(len(mail.participants) > 1)
     self.assertEqual(len(mail.attachments), 2)
     self.assertEqual(mail.subject, 'crypted content')
     self.assertTrue(isinstance(mail.date, datetime))
Ejemplo n.º 2
0
 def test_transport_signature(self):
     mail = load_mail('dkim1.eml')
     message = MailMessage(mail)
     param = NewMessage()
     user = FakeUser()
     featurer = InboundMailFeature(message, {})
     featurer.process(user, param, ([]))
     feats = param.privacy_features
     self.assertEqual(feats.get('transport_signed'), True)
Ejemplo n.º 3
0
 def test_encrypted_message(self):
     mail = load_mail('pgp_crypted_1.eml')
     message = MailMessage(mail)
     param = NewMessage()
     user = FakeUser()
     featurer = InboundMailFeature(message, {})
     featurer.process(user, param, ([]))
     feats = param.privacy_features
     self.assertEqual(feats.get('message_encrypted'), True)
     self.assertEqual(feats.get('message_encryption_method'), 'pgp')
Ejemplo n.º 4
0
 def test_no_encryption_signature(self):
     mail = load_mail('spam1.eml')
     message = MailMessage(mail)
     param = NewMessage()
     user = FakeUser()
     featurer = InboundMailFeature(message, {})
     featurer.process(user, param, ([]))
     feats = param.privacy_features
     self.assertEqual(feats.get('message_signed'), False)
     self.assertEqual(feats.get('message_encrypted'), False)
     self.assertEqual(feats.get('message_encryption_method'), '')
     self.assertEqual(feats.get('message_signature_type'), '')
     self.assertEqual(feats.get('transport_signed'), False)
Ejemplo n.º 5
0
def import_email(email, import_path, format, contact_probability, **kwargs):
    """Import emails for an user."""
    from caliopen_main.user.core import User
    from caliopen_main.contact.core import Contact, ContactLookup
    from caliopen_main.message.parsers.mail import MailMessage
    from caliopen_main.contact.parameters import NewContact, NewEmail
    from caliopen_nats.delivery import UserMessageDelivery
    from caliopen_main.message.core import RawMessage
    from caliopen_storage.config import Configuration

    max_size = int(Configuration("global").get("object_store.db_size_limit"))

    if format == 'maildir':
        emails = Maildir(import_path, factory=message_from_file)
        mode = 'maildir'
    else:
        if os.path.isdir(import_path):
            mode = 'mbox_directory'
            emails = {}
            files = [
                f for f in os.listdir(import_path)
                if os.path.isfile(os.path.join(import_path, f))
            ]
            for f in files:
                try:
                    log.debug('Importing mail from file {}'.format(f))
                    with open('%s/%s' % (import_path, f)) as fh:
                        emails[f] = message_from_file(fh)
                except Exception as exc:
                    log.error('Error importing email {}'.format(exc))
        else:
            mode = 'mbox'
            emails = mbox(import_path)

    user = User.by_local_identity(email)

    log.info("Processing mode %s" % mode)

    for key, data in emails.iteritems():
        # Prevent creating message too large to fit in db.
        # (should use inject cmd for large messages)
        size = len(data.as_string())
        if size > max_size:
            log.warn("Message too large to fit into db. \
            Please, use 'inject' cmd for importing large emails.")
            continue

        raw = RawMessage.create(data.as_string())
        log.debug('Created raw message {}'.format(raw.raw_msg_id))
        message = MailMessage(data.as_string())
        dice = random()
        if dice <= contact_probability:
            for participant in message.participants:
                try:
                    ContactLookup.get(user, participant.address)
                except NotFound:
                    log.info('Creating contact %s' % participant.address)
                    name, domain = participant.address.split('@')
                    contact_param = NewContact()
                    contact_param.family_name = name
                    if participant.address:
                        e_mail = NewEmail()
                        e_mail.address = participant.address
                        contact_param.emails = [e_mail]
                    Contact.create(user, contact_param)
        log.info('No contact associated to raw {} '.format(raw.raw_msg_id))

        processor = UserMessageDelivery(user)
        obj_message = processor.process_raw(raw.raw_msg_id)
        log.info('Created message {}'.format(obj_message.message_id))
Ejemplo n.º 6
0
    def process_inbound(self, raw):
        """Process inbound message.

        @param raw: a RawMessage object
        @rtype: NewMessage
        """
        message = MailMessage(raw.raw_data)
        new_message = NewInboundMessage()
        new_message.raw_msg_id = raw.raw_msg_id
        new_message.subject = message.subject
        new_message.body_html = message.body_html
        new_message.body_plain = message.body_plain
        new_message.date = message.date
        new_message.size = message.size
        new_message.protocol = message.message_protocol
        new_message.is_unread = True
        new_message.is_draft = False
        new_message.is_answered = False
        new_message.is_received = True
        new_message.importance_level = 0  # XXX tofix on parser
        new_message.external_references = message.external_references

        participants = []
        for p in message.participants:
            participant, contact = self.get_participant(message, p)
            new_message.participants.append(participant)
            participants.append((participant, contact))

        if not participants:
            raise Exception("no participant found in raw message {}".format(
                raw.raw_msg_id))

        for a in message.attachments:
            attachment = Attachment()
            attachment.content_type = a.content_type
            attachment.file_name = a.filename
            attachment.size = a.size
            attachment.mime_boundary = a.mime_boundary
            if hasattr(a, "is_inline"):
                attachment.is_inline = a.is_inline
            new_message.attachments.append(attachment)

        # Compute PI !!
        conf = Configuration('global').configuration
        extractor = InboundMailFeature(message, conf)
        extractor.process(self.user, new_message, participants)

        # compute tags
        self._get_tags(new_message)
        if new_message.tags:
            log.debug('Resolved tags {}'.format(new_message.tags))

        # lookup by external references
        lookup_sequence = self.lookup_discussion_sequence(message, new_message)
        lkp = self.lookup(lookup_sequence)
        log.debug('Lookup with sequence {} give {}'.
                  format(lookup_sequence, lkp))

        if lkp:
            new_message.discussion_id = lkp.discussion_id
        else:
            discussion = Discussion.create_from_message(self.user, message)
            log.debug('Created discussion {}'.format(discussion.discussion_id))
            new_message.discussion_id = discussion.discussion_id
            self.create_lookups(lookup_sequence, new_message)
        # Format features
        new_message.privacy_features = \
            marshal_features(new_message.privacy_features)
        try:
            new_message.validate()
        except Exception as exc:
            log.error(
                "validation failed with error : « {} » \
                for new_message {}[dump : {}]".format(
                    exc, new_message, vars(new_message)))
            raise exc

        return new_message
Ejemplo n.º 7
0
 def parse(self):
     """Parse raw message to get a formatted object."""
     return MailMessage(self)
Ejemplo n.º 8
0
def import_email(email, import_path, format, contact_probability, **kwargs):
    """Import emails for an user."""
    from caliopen_main.user.core import User
    from caliopen_main.contact.core import Contact, ContactLookup
    from caliopen_main.message.parsers.mail import MailMessage
    from caliopen_main.contact.parameters import NewContact, NewEmail
    from caliopen_nats.delivery import UserMailDelivery
    from caliopen_main.message.core import RawMessage
    from caliopen_storage.config import Configuration

    max_size = int(Configuration("global").get("object_store.db_size_limit"))

    if 'to' in kwargs and kwargs['to']:
        dest_email = kwargs['to']
    else:
        dest_email = email

    if format == 'maildir':
        if dest_email != email:
            raise Exception('Cannot change To email using maildir format')
        emails = Maildir(import_path, factory=message_from_file)
        mode = 'maildir'
    else:
        if os.path.isdir(import_path):
            mode = 'mbox_directory'
            emails = {}
            files = [
                f for f in os.listdir(import_path)
                if os.path.isfile(os.path.join(import_path, f))
            ]
            for f in files:
                try:
                    log.debug('Importing mail from file {}'.format(f))
                    with open('%s/%s' % (import_path, f)) as fh:
                        data = fh.read()
                        data = re.sub('^To: (.*)',
                                      'To: %s' % dest_email,
                                      data,
                                      flags=re.MULTILINE)
                        emails[f] = message_from_string(data)
                except Exception as exc:
                    log.error('Error importing email {}'.format(exc))
        else:
            mode = 'mbox'
            emails = mbox(import_path)

    user = User.by_local_identifier(dest_email, 'email')

    log.info("Processing mode %s" % mode)

    for key, data in emails.iteritems():
        # Prevent creating message too large to fit in db.
        # (should use inject cmd for large messages)
        size = len(data.as_string())
        if size > max_size:
            log.warn("Message too large to fit into db. \
            Please, use 'inject' cmd for importing large emails.")
            continue

        raw = RawMessage.create(data.as_string())
        log.debug('Created raw message {}'.format(raw.raw_msg_id))
        message = MailMessage(data.as_string())
        dice = random()
        if dice <= contact_probability:
            for participant in message.participants:
                try:
                    ContactLookup.get(user, participant.address)
                except NotFound:
                    log.info('Creating contact %s' % participant.address)
                    name, domain = participant.address.split('@')
                    contact_param = NewContact()
                    contact_param.family_name = name
                    if participant.address:
                        e_mail = NewEmail()
                        e_mail.address = participant.address
                        contact_param.emails = [e_mail]
                    Contact.create(user, contact_param)
        else:
            log.info('No contact associated to raw {} '.format(raw.raw_msg_id))

        processor = UserMailDelivery(
            user, user.local_identities[0])  # assume one local identity
        try:
            obj_message = processor.process_raw(raw.raw_msg_id)
        except Exception as exc:
            if isinstance(exc, DuplicateMessage):
                log.info('duplicate message {}, not imported'.format(
                    raw.raw_msg_id))
            else:
                log.exception(exc)
        else:
            log.info('Created message {}'.format(obj_message.message_id))
Ejemplo n.º 9
0
    def process_inbound(self, raw):
        """Process inbound message.

        @param raw: a RawMessage object
        @rtype: NewMessage
        """
        email = MailMessage(raw.raw_data)
        new_message = NewInboundMessage()
        new_message.raw_msg_id = raw.raw_msg_id
        new_message.subject = email.subject
        new_message.body_html = email.body_html
        new_message.body_plain = email.body_plain
        new_message.date = email.date
        new_message.size = email.size
        new_message.protocol = email.message_protocol
        new_message.is_unread = True
        new_message.is_draft = False
        new_message.is_answered = False
        new_message.is_received = True
        new_message.importance_level = 0  # XXX tofix on parser
        new_message.external_references = email.external_references

        participants = []
        for p in email.participants:
            p.address = p.address.lower()
            try:
                participant, contact = self.get_participant(email, p)
                new_message.participants.append(participant)
                participants.append((participant, contact))
            except Exception as exc:
                log.error(
                    "process_inbound failed to lookup participant for email {} : {}"
                    .format(vars(email), exc))
                raise exc

        if not participants:
            raise Exception("no participant found in raw email {}".format(
                raw.raw_msg_id))

        for a in email.attachments:
            attachment = Attachment()
            attachment.content_type = a.content_type
            attachment.file_name = a.filename
            attachment.size = a.size
            attachment.mime_boundary = a.mime_boundary
            if hasattr(a, "is_inline"):
                attachment.is_inline = a.is_inline
            new_message.attachments.append(attachment)

        # Compute PI !!
        conf = Configuration('global').configuration
        extractor = InboundMailFeature(email, conf)
        extractor.process(self.user, new_message, participants)

        # compute user tags
        self._get_tags(new_message)
        # embed external flags if any
        new_message.ext_tags = email.external_flags
        if new_message.tags:
            log.debug('Resolved tags {}'.format(new_message.tags))

        # build discussion_id from lookup_sequence
        lookup_sequence, discussion_id = self.lookup_discussion_sequence(
            email, new_message)
        log.debug('Lookup with sequence {} gives {}'.format(
            lookup_sequence, discussion_id))
        new_message.discussion_id = discussion_id

        # upsert lookup tables
        discuss = Discussion(self.user)
        discuss.upsert_lookups_for_participants(new_message.participants)
        # Format features
        new_message.privacy_features = \
            marshal_features(new_message.privacy_features)
        try:
            new_message.validate()
        except Exception as exc:
            log.error("validation failed with error : « {} » \
                for new_message {}[dump : {}]".format(exc, new_message,
                                                      vars(new_message)))
            raise exc

        return new_message