Beispiel #1
0
def process_email_message(self, message_id):
    from .models import TaskAttachment, TaskStore

    with open('/tmp/out.log', 'w') as out:
        import json
        out.write(json.dumps(settings.LOGGING, indent=4))
        out.write(__name__)

    def get_secret_id_and_args(address):
        inbox_id = address[0:36]
        args = []

        arg_string = address[36:]
        for arg in re.split('__|\+', arg_string):
            if not arg:
                continue
            if '=' in arg:
                params = arg.split('=')
                if params[0] == 'priority':
                    params[1] = params[1].upper()
                args.append('%s:"%s"' % tuple(params))
            else:
                args.append('+%s' % arg)

        return inbox_id, args

    message = Message.objects.get(pk=message_id)
    message.read = now()
    message.save()

    store = None
    additional_args = []
    # Check for matching To: addresses.
    for address in message.to_addresses:
        try:
            inbox_id, additional_args = get_secret_id_and_args(
                address.split('@')[0])

            store = TaskStore.objects.get(secret_id=inbox_id)
            break
        except (TaskStore.DoesNotExist, IndexError):
            pass

    # Check for 'Received' headers matching a known e-mail address.
    if store is None:
        email_regex = re.compile(r'([0-9a-fA-F-]{36}@inthe.am)')
        all_received_headers = message.get_email_object().get_all('Received')
        for header in all_received_headers:
            matched_email = email_regex.search(header)
            if matched_email:
                address = matched_email.group(1)
                try:
                    inbox_id, additional_args = get_secret_id_and_args(
                        address.split('@')[0])

                    store = TaskStore.objects.get(secret_id=inbox_id)
                    break
                except (TaskStore.DoesNotExist, IndexError):
                    pass

    if store is None:
        logger.error(
            "Could not find task store for e-mail message (ID %s) addressed "
            "to %s", message.pk, message.to_addresses)
        return

    allowed = False
    for address in store.email_whitelist.split('\n'):
        if glob(message.from_address[0], address):
            allowed = True

    if not allowed:
        log_args = ("Incoming task creation e-mail (ID: %s) from '%s' "
                    "does not match email whitelist and was ignored." %
                    (message.pk, message.from_address[0]), )
        logger.info(*log_args)
        store.log_message(*log_args)
        return

    if (not message.subject
            or message.subject.lower() in ['add', 'create', 'new'], ):
        with git_checkpoint(store, 'Incoming E-mail'):
            task_args = [
                'add',
                'intheamoriginalemailsubject:"%s"' % message.subject,
                'intheamoriginalemailid:%s' % message.pk,
            ] + additional_args + shlex.split(
                message.text.split('\n\n')[0]  # Only use text up to the first
                # blank line.
            )
            stdout, stderr = store.client._execute_safe(*task_args)
            task = store.client.get_task(intheamoriginalemailid=message.pk)[1]
            task_id = str(task['uuid'])

            attachment_urls_raw = task.get('intheamattachments')
            if not attachment_urls_raw:
                attachment_urls = []
            else:
                attachment_urls = attachment_urls_raw.split('|')

            for record in message.attachments.all():
                attachment = record.document
                if attachment.file.size > settings.FILE_UPLOAD_MAXIMUM_BYTES:
                    logger.info(
                        "File %s too large (%s bytes).",
                        attachment.file.name,
                        attachment.file.size,
                    )
                    store.log_message("Attachments must be smaller than %s "
                                      "bytes to be saved to a task, but the "
                                      "attachment %s received for task ID %s "
                                      "is %s bytes in size and was not saved "
                                      "as a result." % (
                                          settings.FILE_UPLOAD_MAXIMUM_BYTES,
                                          attachment.file.name,
                                          task_id,
                                          attachment.file.size,
                                      ))
                    attachment.delete()
                    continue

                document = TaskAttachment.objects.create(
                    store=store,
                    task_id=task_id,
                    name=record.get_filename(),
                    size=attachment.file.size,
                )
                document.document.save(
                    record.get_filename(),
                    attachment.file,
                )
                attachment_urls.append(document.document.url)
                store.client.task_annotate(
                    task, 'Attached File: %s' % document.document.url)

            if attachment_urls:
                task['intheamattachments'] = ' '.join(attachment_urls)
                store.client.task_update(task)

        log_args = ("Added task %s via e-mail %s from %s." %
                    (task_id, message.pk, message.from_address[0]), )
        logger.info(*log_args)
        store.log_message(*log_args)
    else:
        log_args = (
            "Unable to process e-mail %s from %s; unknown subject '%s'" % (
                message.pk,
                message.from_address[0],
                message.subject,
            ), )
        logger.info(*log_args)
        store.log_message(*log_args)
Beispiel #2
0
def process_email_message(self, message_id):
    from .models import TaskStore

    def get_secret_id_and_args(address):
        inbox_id = address[0:36]
        args = []

        arg_string = address[36:]
        for arg in re.split('__|\+', arg_string):
            if not arg:
                continue
            if '=' in arg:
                args.append(
                    '%s:"%s"' % tuple(arg.split('='))
                )
            else:
                args.append('+%s' % arg)

        return inbox_id, args

    message = Message.objects.get(pk=message_id)
    message.read = now()
    message.save()

    store = None
    additional_args = []
    for address in message.to_addresses:
        try:
            inbox_id, additional_args = get_secret_id_and_args(
                address.split('@')[0]
            )

            store = TaskStore.objects.get(
                secret_id=inbox_id
            )
            break
        except (TaskStore.DoesNotExist, IndexError):
            pass

    if store is None:
        logger.error(
            "Could not find task store for e-mail message (ID %s) addressed "
            "to %s",
            message.pk,
            message.to_addresses
        )
        return

    allowed = False
    for address in store.email_whitelist.split('\n'):
        if glob(message.from_address[0], address):
            allowed = True

    if not allowed:
        log_args = (
            "Incoming task creation e-mail (ID: %s) from '%s' "
            "does not match email whitelist and was ignored." % (
                message.pk,
                message.from_address[0]
            ),
        )
        logger.info(*log_args)
        store.log_message(*log_args)
        return

    if (
        not message.subject
        or message.subject.lower() in ['add', 'create', 'new'],
    ):
        task_id = str(uuid.uuid4())
        with git_checkpoint(store, 'Incoming E-mail'):
            task_args = [
                'add',
                'uuid:%s' % task_id,
                'intheamoriginalemailsubject:"%s"' % message.subject,
                'intheamoriginalemailid:%s' % message.pk,
            ] + additional_args + shlex.split(message.text)

        stdout, stderr = store.client._execute_safe(*task_args)

        log_args = (
            "Added task %s via e-mail %s from %s." % (
                task_id,
                message.pk,
                message.from_address[0]
            ),
        )
        logger.info(*log_args)
        store.log_message(*log_args)
    else:
        log_args = (
            "Unable to process e-mail %s from %s; unknown subject '%s'" % (
                message.pk,
                message.from_address[0],
                message.subject,
            ),
        )
        logger.info(*log_args)
        store.log_message(*log_args)
Beispiel #3
0
def process_email_message(self, message_id):
    from .models import TaskAttachment, TaskStore

    with open('/tmp/out.log', 'w') as out:
        import json
        out.write(
            json.dumps(settings.LOGGING, indent=4)
        )
        out.write(__name__)

    def get_secret_id_and_args(address):
        inbox_id = address[0:36]
        args = []

        arg_string = address[36:]
        for arg in re.split('__|\+', arg_string):
            if not arg:
                continue
            if '=' in arg:
                params = arg.split('=')
                if params[0] == 'priority':
                    params[1] = params[1].upper()
                args.append('%s:"%s"' % tuple(params))
            else:
                args.append('+%s' % arg)

        return inbox_id, args

    message = Message.objects.get(pk=message_id)
    message.read = now()
    message.save()

    store = None
    additional_args = []
    # Check for matching To: addresses.
    for address in message.to_addresses:
        try:
            inbox_id, additional_args = get_secret_id_and_args(
                address.split('@')[0]
            )

            store = TaskStore.objects.get(
                secret_id=inbox_id
            )
            break
        except (TaskStore.DoesNotExist, IndexError):
            pass

    # Check for 'Received' headers matching a known e-mail address.
    if store is None:
        email_regex = re.compile(r'([0-9a-fA-F-]{36}@inthe.am)')
        all_received_headers = message.get_email_object().get_all('Received')
        for header in all_received_headers:
            matched_email = email_regex.search(header)
            if matched_email:
                address = matched_email.group(1)
                try:
                    inbox_id, additional_args = get_secret_id_and_args(
                        address.split('@')[0]
                    )

                    store = TaskStore.objects.get(
                        secret_id=inbox_id
                    )
                    break
                except (TaskStore.DoesNotExist, IndexError):
                    pass

    if store is None:
        logger.error(
            "Could not find task store for e-mail message (ID %s) addressed "
            "to %s",
            message.pk,
            message.to_addresses
        )
        return

    allowed = False
    for address in store.email_whitelist.split('\n'):
        if glob(message.from_address[0], address):
            allowed = True

    if not allowed:
        log_args = (
            "Incoming task creation e-mail (ID: %s) from '%s' "
            "does not match email whitelist and was ignored." % (
                message.pk,
                message.from_address[0]
            ),
        )
        logger.info(*log_args)
        store.log_message(*log_args)
        return

    if (
        not message.subject
        or message.subject.lower() in ['add', 'create', 'new'],
    ):
        with git_checkpoint(store, 'Incoming E-mail'):
            task_args = [
                'add',
                'intheamoriginalemailsubject:"%s"' % message.subject,
                'intheamoriginalemailid:%s' % message.pk,
            ] + additional_args + shlex.split(
                message.text.split('\n\n')[0]  # Only use text up to the first
                                               # blank line.
            )
            stdout, stderr = store.client._execute_safe(*task_args)
            task = store.client.get_task(intheamoriginalemailid=message.pk)[1]
            task_id = str(task['uuid'])

            attachment_urls_raw = task.get('intheamattachments')
            if not attachment_urls_raw:
                attachment_urls = []
            else:
                attachment_urls = attachment_urls_raw.split('|')

            for record in message.attachments.all():
                attachment = record.document
                if attachment.file.size > settings.FILE_UPLOAD_MAXIMUM_BYTES:
                    logger.info(
                        "File %s too large (%s bytes).",
                        attachment.file.name,
                        attachment.file.size,
                    )
                    store.log_message(
                        "Attachments must be smaller than %s "
                        "bytes to be saved to a task, but the "
                        "attachment %s received for task ID %s "
                        "is %s bytes in size and was not saved "
                        "as a result." % (
                            settings.FILE_UPLOAD_MAXIMUM_BYTES,
                            attachment.file.name,
                            task_id,
                            attachment.file.size,
                        )
                    )
                    attachment.delete()
                    continue

                document = TaskAttachment.objects.create(
                    store=store,
                    task_id=task_id,
                    name=record.get_filename(),
                    size=attachment.file.size,
                )
                document.document.save(
                    record.get_filename(),
                    attachment.file,
                )
                attachment_urls.append(
                    document.document.url
                )
                store.client.task_annotate(
                    task, 'Attached File: %s' % document.document.url
                )

            if attachment_urls:
                task['intheamattachments'] = ' '.join(attachment_urls)
                store.client.task_update(task)

        log_args = (
            "Added task %s via e-mail %s from %s." % (
                task_id,
                message.pk,
                message.from_address[0]
            ),
        )
        logger.info(*log_args)
        store.log_message(*log_args)
    else:
        log_args = (
            "Unable to process e-mail %s from %s; unknown subject '%s'" % (
                message.pk,
                message.from_address[0],
                message.subject,
            ),
        )
        logger.info(*log_args)
        store.log_message(*log_args)
Beispiel #4
0
def process_email_message(self, message_id):
    from .models import TaskAttachment, TaskStore

    def get_secret_id_and_args(address):
        inbox_id = address[0:36]
        args = []

        arg_string = address[36:]
        for arg in re.split(r"__|\+", arg_string):
            if not arg:
                continue
            if "=" in arg:
                params = arg.split("=")
                if params[0] == "priority":
                    params[1] = params[1].upper()
                args.append(f'{params[0]}:"{params[1]}"')
            else:
                args.append(f"+{arg}")

        return inbox_id, args

    message = Message.objects.get(pk=message_id)
    message.read = now()
    message.save()

    store: Optional[TaskStore] = None
    additional_args = []
    # Check for matching To: addresses.
    for address in message.to_addresses:
        try:
            inbox_id, additional_args = get_secret_id_and_args(
                address.split("@")[0])

            store = TaskStore.objects.get(secret_id=inbox_id)
            break
        except (TaskStore.DoesNotExist, IndexError):
            pass

    # Check for 'Received' headers matching a known e-mail address.
    if store is None:
        email_regex = re.compile(r"([0-9a-fA-F-]{36}@inthe.am)")
        all_received_headers = message.get_email_object().get_all("Received")
        for header in all_received_headers:
            matched_email = email_regex.search(header)
            if matched_email:
                address = matched_email.group(1)
                try:
                    inbox_id, additional_args = get_secret_id_and_args(
                        address.split("@")[0])

                    store = TaskStore.objects.get(secret_id=inbox_id)
                    break
                except (TaskStore.DoesNotExist, IndexError):
                    pass

    if store is None:
        logger.error(
            "Could not find task store for e-mail message (ID %s) addressed "
            "to %s",
            message.pk,
            message.to_addresses,
        )
        return

    pubsub_message: Dict[str, Any] = {
        "username": store.user.username,
        "message_id": message.pk,
        "subject": message.subject,
        "accepted": True,
    }

    allowed = False
    for address in store.email_whitelist.split("\n"):
        if glob(message.from_address[0], address):
            allowed = True

    if not allowed:
        log_args = (f"Incoming task creation e-mail (ID: {message.pk}) from "
                    f"'{message.from_address[0]}' does not match email "
                    "whitelist and was ignored.")
        logger.info(*log_args)
        store.log_message(*log_args)

        pubsub_message["accepted"] = False
        pubsub_message["rejection_reason"] = "passlist"
        store.publish_announcement("incoming_mail", pubsub_message)
        return

    if not message.subject or message.subject.lower() in [
            "add", "create", "new"
    ]:
        with git_checkpoint(store, "Incoming E-mail"):
            task_args = ([
                "add",
                f'intheamoriginalemailsubject:"{message.subject}"',
                f"intheamoriginalemailid:{message.pk}",
            ] + additional_args + shlex.split(
                message.text.split("\n\n")[0]  # Only use text up to the first
                # blank line.
            ))
            store.client._execute_safe(*task_args)
            task = store.client.get_task(intheamoriginalemailid=message.pk)[1]
            task_id = str(task["uuid"])

            attachment_urls_raw = task.get("intheamattachments")
            if not attachment_urls_raw:
                attachment_urls = []
            else:
                attachment_urls = attachment_urls_raw.split("|")

            for record in message.attachments.all():
                attachment = record.document
                if attachment.file.size > settings.FILE_UPLOAD_MAXIMUM_BYTES:
                    logger.info(
                        "File %s too large (%s bytes).",
                        attachment.file.name,
                        attachment.file.size,
                    )
                    store.log_message(
                        "Attachments must be smaller than "
                        f"{settings.FILE_UPLOAD_MAXIMUM_BYTES} "
                        "bytes to be saved to a task, but the "
                        f"attachment {attachment.file.name} "
                        f"received for task ID {task_id} "
                        f"is {attachment.file.size} bytes in size "
                        "and was not saved as a result.")
                    attachment.delete()
                    continue

                document = TaskAttachment.objects.create(
                    store=store,
                    task_id=task_id,
                    name=record.get_filename(),
                    size=attachment.file.size,
                )
                document.document.save(
                    record.get_filename(),
                    attachment.file,
                )
                attachment_urls.append(document.document.url)
                store.client.task_annotate(
                    task, f"Attached File: {document.document.url}")

            if attachment_urls:
                task["intheamattachments"] = " ".join(attachment_urls)
                store.client.task_update(task)

        log_args = (f"Added task {task_id} via e-mail {message.pk} "
                    f"from {message.from_address[0]}.")
        logger.info(*log_args)
        store.log_message(*log_args)

        pubsub_message["task_id"] = task_id
        store.publish_announcement("incoming_mail", pubsub_message)
    else:
        log_args = (f"Unable to process e-mail {message.pk} "
                    f"from {message.from_address[0]}; "
                    f"unknown subject '{message.subject}'")
        logger.info(*log_args)
        store.log_message(*log_args)

        pubsub_message["accepted"] = False
        pubsub_message["rejection_reason"] = "subject"
        store.publish_announcement("incoming_mail", pubsub_message)