Ejemplo n.º 1
0
 def _accept_comm(self, comm, text):
     """Accept a communication onto the site"""
     comm.communication = text
     comm.hidden = False
     comm.create_agency_notifications()
     comm.save()
     task = ResponseTask.objects.create(communication=comm)
     classify_status.apply_async(args=(task.pk,), countdown=30 * 60)
     PortalCommunication.objects.create(
         communication=comm,
         sent_datetime=timezone.now(),
         portal=self.portal,
         direction='incoming',
     )
Ejemplo n.º 2
0
def _handle_request(request, mail_id):
    """Handle incoming mailgun FOI request messages"""
    # this function needs to be refactored
    # pylint: disable=broad-except
    # pylint: disable=too-many-locals
    # pylint: disable=too-many-branches
    # pylint: disable=too-many-statements
    post = request.POST
    from_email, to_emails, cc_emails = _parse_email_headers(post)
    subject = post.get('Subject') or post.get('subject', '')

    try:
        foia = FOIARequest.objects.get(mail_id=mail_id)

        # extra logging for next request portals for now
        if foia.portal and foia.portal.type == 'nextrequest':
            _log_mail(request)

        if foia.deleted:
            if from_email is not None:
                EmailMessage(
                    subject='Request Withdrawn: {}'.format(subject),
                    body=render_to_string('text/foia/deleted_autoreply.txt'),
                    from_email=foia.get_request_email(),
                    to=[unicode(from_email)],
                    bcc=['*****@*****.**'],
                ).send(fail_silently=False)
            return HttpResponse('WARNING')

        if from_email is not None:
            email_allowed = from_email.allowed(foia)
        else:
            email_allowed = False
        if not email_allowed:
            msg, reason = ('Bad Sender', 'bs')
        if foia.block_incoming:
            msg, reason = ('Incoming Blocked', 'ib')
        if not email_allowed or foia.block_incoming:
            logger.warning('%s: %s', msg, from_email)
            comm = _make_orphan_comm(
                from_email,
                to_emails,
                cc_emails,
                subject,
                post,
                request.FILES,
                foia,
            )
            OrphanTask.objects.create(reason=reason,
                                      communication=comm,
                                      address=mail_id)
            return HttpResponse('WARNING')

        # if this isn't a known email for this agency, add it
        if not from_email.agencies.filter(pk=foia.agency.pk).exists():
            AgencyEmail.objects.create(
                agency=foia.agency,
                email=from_email,
            )

        # if this request is using a portal, hide the incoming messages
        hidden = foia.portal is not None

        with transaction.atomic():
            comm = FOIACommunication.objects.create(
                foia=foia,
                from_user=foia.agency.get_user(),
                to_user=foia.user,
                subject=subject[:255],
                response=True,
                datetime=timezone.now(),
                communication=_get_mail_body(post, foia),
                hidden=hidden,
            )
            email_comm = EmailCommunication.objects.create(
                communication=comm,
                sent_datetime=timezone.now(),
                from_email=from_email,
            )
            email_comm.to_emails.set(to_emails)
            email_comm.cc_emails.set(cc_emails)
            RawEmail.objects.create(
                email=email_comm,
                raw_email='%s\n%s' %
                (post.get('message-headers', ''), post.get('body-plain', '')))
            comm.process_attachments(request.FILES)
            transaction.on_commit(lambda: download_links(comm.pk))

        # attempt to autodetect a known portal
        _detect_portal(comm, from_email.email, post)

        # if agency isn't currently using an outgoing email or a portal, flag it
        if (not foia.agency.get_emails().exists() and not foia.agency.portal
                and not FlaggedTask.objects.filter(
                    agency=foia.agency, category='agency new email').exists()):
            FlaggedTask.objects.create(
                agency=foia.agency,
                foia=foia,
                category='agency new email',
                text='We received an email from {} for a request to this '
                'agency, but this agency does not currently have a primary '
                'email address set'.format(from_email, ),
            )

        comm.extract_tracking_id()

        if foia.portal:
            foia.portal.receive_msg(comm)
        else:
            task = comm.responsetask_set.create()
            classify_status.apply_async(args=(task.pk, ), countdown=30 * 60)
            comm.create_agency_notifications()

        muckrock_domains = (settings.MAILGUN_SERVER_NAME, 'muckrock.com')
        new_cc_emails = [
            e for e in (to_emails + cc_emails)
            if e.domain not in muckrock_domains
        ]
        if from_email.domain not in muckrock_domains:
            foia.email = from_email
        foia.cc_emails.set(new_cc_emails)

        if foia.status == 'ack':
            foia.status = 'processed'
        foia.save(comment='incoming mail')

    except FOIARequest.DoesNotExist:
        logger.warning('Invalid Address: %s', mail_id)
        try:
            # try to get the foia by the PK before the dash
            foia = FOIARequest.objects.get(pk=mail_id.split('-')[0])
        except FOIARequest.DoesNotExist:
            foia = None
        comm = _make_orphan_comm(
            from_email,
            to_emails,
            cc_emails,
            subject,
            post,
            request.FILES,
            foia,
        )
        OrphanTask.objects.create(reason='ia',
                                  communication=comm,
                                  address=mail_id)
        return HttpResponse('WARNING')
    except Exception as exc:
        # If anything I haven't accounted for happens, at the very least forward
        # the email to requests so it isn't lost
        logger.error(
            'Uncaught Mailgun Exception - %s: %s',
            mail_id,
            exc,
            exc_info=sys.exc_info(),
        )
        _forward(post, request.FILES, 'Uncaught Mailgun Exception', info=True)
        return HttpResponse('ERROR')

    return HttpResponse('OK')
Ejemplo n.º 3
0
def _handle_request(request, mail_id):
    """Handle incoming mailgun FOI request messages"""
    # pylint: disable=broad-except
    # pylint: disable=too-many-locals
    post = request.POST
    from_ = post.get('From')
    to_ = post.get('To') or post.get('to')
    subject = post.get('Subject') or post.get('subject', '')

    try:
        from_realname, from_email = parseaddr(from_)
        foia = FOIARequest.objects.get(mail_id=mail_id)

        if not _allowed_email(from_email, foia):
            msg, reason = ('Bad Sender', 'bs')
        if foia.block_incoming:
            msg, reason = ('Incoming Blocked', 'ib')
        if not _allowed_email(from_email, foia) or foia.block_incoming:
            logger.warning('%s: %s', msg, from_)
            comm = _make_orphan_comm(from_, to_, subject, post, request.FILES, foia)
            OrphanTask.objects.create(
                reason=reason,
                communication=comm,
                address=mail_id)
            return HttpResponse('WARNING')

        comm = FOIACommunication.objects.create(
                foia=foia,
                from_who=from_realname[:255],
                priv_from_who=from_[:255],
                to_who=foia.user.get_full_name(),
                priv_to_who=to_[:255],
                subject=subject[:255],
                response=True,
                date=datetime.now(),
                full_html=False,
                delivered='email',
                communication=_get_mail_body(post),
                )
        RawEmail.objects.create(
            communication=comm,
            raw_email='%s\n%s' % (post.get('message-headers', ''), post.get('body-plain', '')))

        comm.process_attachments(request.FILES)

        task = ResponseTask.objects.create(communication=comm)
        classify_status.apply_async(args=(task.pk,), countdown=30 * 60)
        # resolve any stale agency tasks for this agency
        if foia.agency:
            foia.agency.unmark_stale()

        foia.email = from_email
        foia.other_emails = ','.join(
                email for name, email
                in getaddresses([post.get('To', ''), post.get('Cc', '')])
                if email and not email.endswith('muckrock.com'))
        while len(foia.other_emails) > 255:
            # drop emails until it fits in db
            foia.other_emails = foia.other_emails[:foia.other_emails.rindex(',')]

        if foia.status == 'ack':
            foia.status = 'processed'
        foia.save(comment='incoming mail')
        comm.create_agency_notifications()

    except FOIARequest.DoesNotExist:
        logger.warning('Invalid Address: %s', mail_id)
        foia = None
        try:
            # try to get the foia by the PK before the dash
            foia = FOIARequest.objects.get(pk=mail_id.split('-')[0])
        except FOIARequest.DoesNotExist:
            pass
        comm = _make_orphan_comm(from_, to_, subject, post, request.FILES, foia)
        OrphanTask.objects.create(
            reason='ia',
            communication=comm,
            address=mail_id)
        return HttpResponse('WARNING')
    except Exception:
        # If anything I haven't accounted for happens, at the very least forward
        # the email to requests so it isn't lost
        logger.error('Uncaught Mailgun Exception: %s', mail_id, exc_info=sys.exc_info())
        _forward(post, request.FILES, 'Uncaught Mailgun Exception', info=True)
        return HttpResponse('ERROR')

    return HttpResponse('OK')
Ejemplo n.º 4
0
def _handle_request(request, mail_id):
    """Handle incoming mailgun FOI request messages"""
    # this function needs to be refactored
    # pylint: disable=broad-except
    # pylint: disable=too-many-locals
    # pylint: disable=too-many-branches
    # pylint: disable=too-many-statements
    post = request.POST
    from_email, to_emails, cc_emails = _parse_email_headers(post)
    subject = post.get("Subject") or post.get("subject", "")

    try:
        foia = FOIARequest.objects.get(mail_id=mail_id)

        # extra logging for next request portals for now
        if foia.portal and foia.portal.type == "nextrequest":
            _log_mail(request)

        if foia.deleted:
            if from_email is not None:
                EmailMessage(
                    subject="Request Withdrawn: {}".format(subject),
                    body=render_to_string("text/foia/deleted_autoreply.txt"),
                    from_email=foia.get_request_email(),
                    to=[str(from_email)],
                    bcc=[settings.DIAGNOSTIC_EMAIL],
                ).send(fail_silently=False)
            return HttpResponse("WARNING")

        if from_email is not None:
            email_allowed = from_email.allowed(foia)
        else:
            email_allowed = False
        if not email_allowed:
            msg, reason = ("Bad Sender", "bs")
        if foia.block_incoming:
            msg, reason = ("Incoming Blocked", "ib")
        if not email_allowed or foia.block_incoming:
            logger.warning("%s: %s", msg, from_email)
            comm = _make_orphan_comm(from_email, to_emails, cc_emails, subject,
                                     post, request.FILES, foia)
            OrphanTask.objects.create(reason=reason,
                                      communication=comm,
                                      address=mail_id)
            return HttpResponse("WARNING")

        # if this isn't a known email for this agency, add it
        if not from_email.agencies.filter(pk=foia.agency.pk).exists():
            AgencyEmail.objects.create(agency=foia.agency, email=from_email)

        # if this request is using a portal, hide the incoming messages
        hidden = foia.portal is not None

        with transaction.atomic():
            comm = FOIACommunication.objects.create(
                foia=foia,
                from_user=foia.agency.get_user(),
                to_user=foia.user,
                subject=subject[:255],
                response=True,
                datetime=timezone.now(),
                communication=_get_mail_body(post, foia),
                hidden=hidden,
            )
            email_comm = EmailCommunication.objects.create(
                communication=comm,
                sent_datetime=timezone.now(),
                from_email=from_email)
            email_comm.to_emails.set(to_emails)
            email_comm.cc_emails.set(cc_emails)
            RawEmail.objects.create(
                email=email_comm,
                raw_email="%s\n%s" %
                (post.get("message-headers", ""), post.get("body-plain", "")),
            )
            comm.process_attachments(request.FILES)
            transaction.on_commit(lambda: download_links(comm.pk))

            if foia.portal:
                transaction.on_commit(lambda: foia.portal.receive_msg(comm))
            else:
                task = comm.responsetask_set.create()
                transaction.on_commit(lambda: classify_status.apply_async(
                    args=(task.pk, ), countdown=30 * 60))
                comm.create_agency_notifications()

        # attempt to autodetect a known portal
        _detect_portal(comm, from_email.email, post)
        # attempt to find file download links
        _detect_file_download_links(comm)

        # if agency isn't currently using an outgoing email or a portal, flag it
        if (not foia.agency.get_emails().exists() and not foia.agency.portal
                and not FlaggedTask.objects.filter(
                    agency=foia.agency, category="agency new email").exists()):
            FlaggedTask.objects.create(
                agency=foia.agency,
                foia=foia,
                category="agency new email",
                text="We received an email from {} for a request to this "
                "agency, but this agency does not currently have a primary "
                "email address set".format(from_email),
            )

        comm.extract_tracking_id()

        muckrock_domains = (settings.MAILGUN_SERVER_NAME, "muckrock.com")
        new_cc_emails = [
            e for e in (to_emails + cc_emails)
            if e.domain not in muckrock_domains
        ]
        if from_email.domain not in muckrock_domains:
            foia.email = from_email
        foia.cc_emails.set(new_cc_emails)

        if foia.status == "ack":
            foia.status = "processed"
        foia.save(comment="incoming mail")

    except FOIARequest.DoesNotExist:
        logger.warning("Invalid Address: %s", mail_id)
        try:
            # try to get the foia by the PK before the dash
            foia = FOIARequest.objects.get(pk=mail_id.split("-")[0])
        except FOIARequest.DoesNotExist:
            foia = None
        comm = _make_orphan_comm(from_email, to_emails, cc_emails, subject,
                                 post, request.FILES, foia)
        OrphanTask.objects.create(reason="ia",
                                  communication=comm,
                                  address=mail_id)
        return HttpResponse("WARNING")
    except Exception as exc:
        # If anything I haven't accounted for happens, at the very least forward
        # the email to requests so it isn't lost
        logger.error("Uncaught Mailgun Exception - %s: %s",
                     mail_id,
                     exc,
                     exc_info=sys.exc_info())
        _forward(post, request.FILES, "Uncaught Mailgun Exception", info=True)
        return HttpResponse("ERROR")

    return HttpResponse("OK")