def log_action_on_ticket(ticket=None, action=None, user=None, **kwargs): """ Log ticket updates """ if not user: user = User.objects.get(username=settings.GENERAL_CONFIG['bot_user']) log_msg = _get_log_message(ticket, action, user, **kwargs) History.objects.create( date=datetime.now(), ticket=ticket, user=user, action=log_msg, actionType=''.join(word.capitalize() for word in action.split('_')), ticketStatus=ticket.status, ) if ImplementationFactory.instance.is_implemented('KPIServiceBase'): _generates_kpi_infos(ticket, log_msg) Logger.debug( unicode(action), extra={ 'ticket': ticket.id, 'public_id': ticket.publicId, 'user': user.username, 'action': action, } )
def _apply_timeout_action(ticket, ip_addr, action): Logger.info(unicode('Executing action %s for ticket %d' % (action.name, ticket.id))) ticket.action = action database.log_action_on_ticket( ticket=ticket, action='set_action', action_name=action.name ) ticket.save() async_job = utils.scheduler.schedule( scheduled_time=datetime.utcnow() + timedelta(seconds=3), func='action.apply_action', kwargs={ 'ticket_id': ticket.id, 'action_id': action.id, 'ip_addr': ip_addr, 'user_id': BOT_USER.id, }, interval=1, repeat=1, result_ttl=500, timeout=3600, ) Logger.info(unicode('Task has %s job id' % (async_job.id))) job = ServiceActionJob.objects.create(ip=ip_addr, action=action, asynchronousJobId=async_job.id, creationDate=datetime.now()) ticket.jobs.add(job) while not async_job.is_finished: sleep(5) return async_job
def follow_the_sun(): """ Set tickets to alarm when user is away """ now = int(time()) where = [~Q(status='Open'), ~Q(status='Reopened'), ~Q(status='Paused'), ~Q(status='Closed')] where = reduce(operator.and_, where) for user in User.objects.filter(~Q(username=BOT_USER.username)): if now > mktime((user.last_login + timedelta(hours=24)).timetuple()): Logger.debug( unicode('user %s logged out, set alarm to True' % (user.username)), extra={ 'user': user.username, } ) user.ticketUser.filter(where).update(alarm=True) else: Logger.debug( str('user %s logged in, set alarm to False' % (user.username)), extra={ 'user': user.username, } ) user.ticketUser.filter(where).update(alarm=False)
def update_paused(): """ Update paused tickets """ now = int(time()) for ticket in Ticket.objects.filter(status=PAUSED): try: if now > int(mktime(ticket.pauseStart.timetuple()) + ticket.pauseDuration): Logger.debug( str('Updating status for ticket %s ' % (ticket.id)), extra={ 'ticket': ticket.id, } ) if ticket.previousStatus == WAITING and ticket.snoozeDuration and ticket.snoozeStart: ticket.snoozeDuration = ticket.snoozeDuration + (datetime.now() - ticket.pauseStart).seconds ticket.status = ticket.previousStatus ticket.pauseStart = None ticket.pauseDuration = None ticket.previousStatus = PAUSED ticket.save() database.log_action_on_ticket( ticket=ticket, action='change_status', previous_value=ticket.previousStatus, new_value=ticket.status ) except (AttributeError, ValueError) as ex: Logger.debug(unicode('Error while updating ticket %d : %s' % (ticket.id, ex)))
def update_waiting(): """ Update waiting answer tickets """ now = int(time()) for ticket in Ticket.objects.filter(status=WAITING): try: if now > int(mktime(ticket.snoozeStart.timetuple()) + ticket.snoozeDuration): Logger.debug( unicode('Updating status for ticket %s ' % (ticket.id)), extra={ 'ticket': ticket.id, } ) _check_auto_unassignation(ticket) ticket.status = ALARM ticket.snoozeStart = None ticket.snoozeDuration = None ticket.previousStatus = WAITING ticket.reportTicket.all().update(status='Attached') ticket.save() database.log_action_on_ticket( ticket=ticket, action='change_status', previous_value=ticket.previousStatus, new_value=ticket.status ) except (AttributeError, ValueError) as ex: Logger.debug(unicode('Error while updating ticket %d : %s' % (ticket.id, ex)))
def delay_jobs(ticket=None, delay=None, back=True): """ Delay pending jobs for given `abuse.models.Ticket` :param `abuse.models.Ticket` ticket: The Cerberus ticket :param int delay: Postpone duration :param bool back: In case of unpause, reschedule jobs with effectively elapsed time """ if not delay: Logger.error(unicode('Missing delay. Skipping...')) return if not isinstance(ticket, Ticket): try: ticket = Ticket.objects.get(id=ticket) except (AttributeError, ObjectDoesNotExist, TypeError, ValueError): Logger.error(unicode('Ticket %d cannot be found in DB. Skipping...' % (ticket))) return # a job is here a tuple (Job instance, datetime instance) pending_jobs = {job[0].id: job for job in utils.scheduler.get_jobs(until=timedelta(days=7), with_times=True)} for job in ticket.jobs.all(): if pending_jobs.get(job.asynchronousJobId): current_date = pending_jobs[job.asynchronousJobId][1] new_date = current_date - delay if back else current_date + delay utils.scheduler.change_execution_time( pending_jobs[job.asynchronousJobId][0], new_date )
def _generates_onclose_kpi(ticket): """ Kpi on ticket close """ try: ImplementationFactory.instance.get_singleton_of('KPIServiceBase').close_ticket(ticket) except KPIServiceException as ex: Logger.error(unicode('Error while pushing KPI - %s' % (ex)))
def feedback_to_phishing_service(screenshot_id=None, feedback=None): """ Post phishing feedback for ML and scoring enhancement to Phishing Service :param str screenshot_id: The uuid of the screenshot_id :param bool feedback: Yes or not it's a phishing url """ ImplementationFactory.instance.get_singleton_of('PhishingServiceBase').post_feedback(screenshot_id, feedback) Logger.debug(unicode('Feedback %s sent for %s' % (feedback, screenshot_id)))
def __save_email(filename, email): """ Push email storage service :param str filename: The filename of the email :param str email: The content of the email """ with ImplementationFactory.instance.get_instance_of('StorageServiceBase', settings.GENERAL_CONFIG['email_storage_dir']) as cnx: cnx.write(filename, email) Logger.info(unicode('Email %s pushed to Storage Service' % (filename)))
def __cancel_by_status(ticket): """ Action cancelled because of ticket status """ current_job = get_current_job() Logger.error(unicode('Ticket %d is %s, Skipping...' % (ticket.id, ticket.status))) ServiceActionJob.objects.filter( asynchronousJobId=current_job.id ).update( status='cancelled', comment='ticket is %s' % (ticket.status) )
def __index_report_to_searchservice(parsed_email, filename, reports_id): """ Index a report to the SearchService """ try: Logger.debug(unicode('Pushing email %s document to SearchService' % (filename))) ImplementationFactory.instance.get_singleton_of('SearchServiceBase').index_email( parsed_email, filename, reports_id ) except SearchServiceException as ex: # Not fatal => don't stop current routine Logger.error(unicode('Unable to index mail %s in SearchService -> %s' % (filename, ex)))
def _get_ip_for_action(ticket): """ Extract and check IP address """ # Get ticket IP(s) reports = ticket.reportTicket.all() ips_on_ticket = [itm.ip for rep in reports for itm in rep.reportItemRelatedReport.filter(~Q(ip=None), itemType='IP')] ips_on_ticket.extend([itm.fqdnResolved for rep in reports for itm in rep.reportItemRelatedReport.filter(~Q(fqdnResolved=None), itemType__in=['FQDN', 'URL'])]) ips_on_ticket = list(set(ips_on_ticket)) if len(ips_on_ticket) != 1: Logger.error(unicode('Multiple or no IP on this ticket')) return return ips_on_ticket[0]
def close_ticket(ticket, reason=settings.CODENAMES['fixed_customer'], service_blocked=False): """ Close ticket and add autoclosed Tag """ # Send "case closed" email to already contacted Provider(s) providers_emails = ContactedProvider.objects.filter(ticket_id=ticket.id).values_list('provider__email', flat=True).distinct() for email in providers_emails: try: validate_email(email.strip()) _send_email(ticket, email, settings.CODENAMES['case_closed']) ticket.save() Logger.info(unicode('Mail sent to provider %s' % (email))) except (AttributeError, TypeError, ValueError, ValidationError): pass if service_blocked: template = settings.CODENAMES['service_blocked'] else: template = settings.CODENAMES['ticket_closed'] # Send "ticket closed" email to defendant _send_email(ticket, ticket.defendant.details.email, template, lang=ticket.defendant.details.lang) if ticket.mailerId: ImplementationFactory.instance.get_singleton_of('MailerServiceBase').close_thread(ticket) resolution = Resolution.objects.get(codename=reason) ticket.resolution = resolution ticket.previousStatus = ticket.status ticket.status = 'Closed' ticket.reportTicket.all().update(status='Archived') tag_name = settings.TAGS['phishing_autoclosed'] if ticket.category.name.lower() == 'phishing' else settings.TAGS['copyright_autoclosed'] ticket.tags.add(Tag.objects.get(name=tag_name)) ticket.save() database.log_action_on_ticket( ticket=ticket, action='change_status', previous_value=ticket.previousStatus, new_value=ticket.status, close_reason=ticket.resolution.codename ) database.log_action_on_ticket( ticket=ticket, action='add_tag', tag_name=tag_name )
def _update_ticket_if_answer(ticket, category, recipient, abuse_report, filename): """ If the email is an answer to a cerberus ticket: - update ticket status - cancel all pending ServiceAction jobs and ticket.timeout jobs - append response to ticket's email thread - save attachments :param `abuse.models.Ticket` ticket: A Cerberus `abuse.models.Ticket` instance :param str category: The category of the answer ('Defendant', 'Plaintiff' or 'Other) :param str recipient: The recipient of the answer :param `worker.parsing.parser.ParsedEmail` abuse_report: The ParsedEmail :param str filename: The filename of the email """ Logger.debug( unicode('New %s answer from %s for ticket %s' % (category, abuse_report.provider, ticket.id)), extra={ 'from': abuse_report.provider, 'action': 'new answer', 'hash': filename, 'ticket': ticket.id, } ) database.log_action_on_ticket( ticket=ticket, action='receive_email', email=abuse_report.provider ) try: if ticket.treatedBy.operator.role.modelsAuthorizations['ticket'].get('unassignedOnAnswer'): ticket.treatedBy = None except (AttributeError, KeyError, ObjectDoesNotExist, ValueError): pass if abuse_report.attachments: _save_attachments( filename, abuse_report.attachments, tickets=[ticket], ) for workflow in TicketAnswerWorkflowFactory.instance.registered_instances: if workflow.identify(ticket, abuse_report, recipient, category) and workflow.apply(ticket, abuse_report, recipient, category): Logger.debug(unicode('Specific workflow %s applied' % (str(workflow.__class__.__name__)))) return
def _genereates_oncreate_kpi(ticket): """ Kpi on ticket creation """ Logger.debug( unicode('new ticket %d' % (ticket.id)), extra={ 'ticket': ticket.id, 'action': 'new ticket', 'public_id': ticket.publicId } ) try: ImplementationFactory.instance.get_singleton_of('KPIServiceBase').new_ticket(ticket) except KPIServiceException as ex: Logger.error(unicode('Error while pushing KPI - %s' % (ex)))
def apply_if_no_reply(ticket_id=None, action_id=None, ip_addr=None, resolution_id=None, user_id=None, close=False): """ Action if no reply from customer :param int ticket_id: The id of the Cerberus `Ticket` :param int action_id: The id of the Cerberus `ServiceAction` :param str ip_addr: The ip address :param int resolution_id: The id of the Cerberus `Resolution` :param int user_id: The id of the Cerberus `User` :param bool close: If the ticket has to be closed after action """ # Checking conformance if not all((ticket_id, action_id, user_id)): Logger.error(unicode( 'Invalid parameters [ticket_id=%s, action_id=%s, user_id=%s]' % (ticket_id, action_id, user_id) )) return if close and not resolution_id: Logger.error(unicode('Close requested but no resolution submitted')) return if resolution_id and not Resolution.objects.filter(id=resolution_id).exists(): Logger.error(unicode('Ticket resolution %d not found, Skipping...' % (resolution_id))) return # Apply action applied = apply_action(ticket_id, action_id, ip_addr, user_id) if not applied: return # Updating ticket info ticket = Ticket.objects.get(id=ticket_id) user = User.objects.get(id=user_id) ticket.previousStatus = ticket.status ticket.snoozeDuration = None ticket.snoozeStart = None close_reason = None if close and resolution_id: __close_ticket(ticket, resolution_id) close_reason = ticket.resolution.codename else: ticket.status = 'Alarm' ticket.save() database.log_action_on_ticket( ticket=ticket, action='change_status', user=user, previous_value=ticket.previousStatus, new_value=ticket.status, close_reason=close_reason ) Logger.info(unicode('Ticket %d processed. Next !' % (ticket_id)))
def log_new_report(report): """ Log report creation """ Logger.debug( unicode('New report %d' % (report.id)), extra={ 'from': report.provider.email, 'action': 'new report', 'report': report.id, } ) if ImplementationFactory.instance.is_implemented('KPIServiceBase'): try: ImplementationFactory.instance.get_singleton_of('KPIServiceBase').new_report(report) except KPIServiceException as ex: Logger.error(unicode('Error while pushing KPI - %s' % (ex)))
def set_ticket_higher_priority(ticket): """ Set `abuse.models.Ticket` higher priority available through it's `abuse.models.Report`'s `abuse.models.Provider` """ defendant = Defendant.objects.get(customerId=ticket.defendant.customerId) if defendant.details.creationDate >= datetime.now() - timedelta(days=30): ticket.priority = sorted(PRIORITY_LEVEL.items(), key=operator.itemgetter(1))[1][0] # High ticket.save() return priorities = list(set(ticket.reportTicket.all().values_list('provider__priority', flat=True))) for priority, _ in sorted(PRIORITY_LEVEL.items(), key=operator.itemgetter(1)): if priority in priorities: Logger.debug(unicode('set priority %s to ticket %d' % (priority, ticket.id))) ticket.priority = priority ticket.save() return
def __update_item_status(item, country='FR'): """ Update item status """ if item.itemType != 'URL': return try: Logger.debug(unicode('Checking status for url %s' % (item.rawItem,))) response = ImplementationFactory.instance.get_singleton_of('PhishingServiceBase').ping_url(item.rawItem, country=country) database.insert_url_status( item, response.direct_status, response.proxied_status, response.http_code, response.score, response.is_phishing, ) except PhishingServiceException: pass
def reparse_validated(report_id=None, user_id=None): """ Reparse now validated `abuse.models.Report` :param int report_id: A Cerberus `abuse.models.Report` id :param int user_id: A Cerberus `abuse.models.User` id """ try: report = Report.objects.get(id=report_id) user = User.objects.get(id=user_id) except (ObjectDoesNotExist, ValueError): Logger.error(unicode('Report %d cannot be found in DB. Skipping...' % (report_id))) return if not report.defendant or not report.service: _create_closed_ticket(report, user) else: _reinject_validated(report, user) Logger.error(unicode('Report %d successfully processed' % (report_id)))
def __update_history(defendant, categories, now): """ Update history for given defendant """ Logger.debug(str('Updating history for defendant %s' % (defendant['customerId']))) for category in categories: reports = Report.objects.filter(~Q(status='Archived'), category=category, defendant_id=defendant['id']).count() tickets = Ticket.objects.filter(~Q(status='Closed'), category=category, defendant_id=defendant['id']).count() stats = __get_last_stats(defendant['id'], category) if not len(stats) or reports != stats[0].reports or tickets != stats[0].tickets: Stat.objects.create( defendant_id=defendant['id'], category_id=category, tickets=tickets, reports=reports, date=now, )
def create_ticket_with_threshold(): """ Automatically creates ticket if there are more than `abuse.models.ReportThreshold.threshold` new reports created during `abuse.models.ReportThreshold.interval` (days) for same (category/defendant/service) """ log_msg = 'threshold : Checking report threshold for category %s, threshold %d, interval %d days' for thres in ReportThreshold.objects.all(): Logger.info(unicode(log_msg % (thres.category.name, thres.threshold, thres.interval))) reports = __get_threshold_reports(thres.category, thres.interval) reports = Counter(reports) for data, count in reports.iteritems(): nb_tickets = Ticket.objects.filter( ~Q(status='Closed'), defendant__customerId=data[0], service__id=data[1], ).count() if count >= thres.threshold and not nb_tickets: ticket = __create_threshold_ticket(data, thres) Logger.info(unicode('threshold: tuple %s match, ticket %s has been created' % (str(data), ticket.id)))
def _create_closed_ticket(report, user): report.ticket = common.create_ticket(report, attach_new=False) report.save() # Add temp proof(s) for mail content temp_proofs = [] if not report.ticket.proof.count(): temp_proofs = common.get_temp_proofs(report.ticket) # Send email to Provider try: validate_email(report.provider.email.strip()) Logger.info(unicode('Sending email to provider')) common.send_email(report.ticket, [report.provider.email], settings.CODENAMES['not_managed_ip']) report.ticket.save() Logger.info(unicode('Mail sent to provider')) ImplementationFactory.instance.get_singleton_of('MailerServiceBase').close_thread(report.ticket) # Delete temp proof(s) for proof in temp_proofs: Proof.objects.filter(id=proof.id).delete() except (AttributeError, TypeError, ValueError, ValidationError): pass common.close_ticket(report, resolution_codename=settings.CODENAMES['invalid'], user=user) Logger.info(unicode('Ticket %d and report %d closed' % (report.ticket.id, report.id)))
def cancel_rq_scheduler_jobs(ticket_id=None, status='answered'): """ Cancel all rq scheduler jobs for given `abuse.models.Ticket` :param int ticket_id: The id of the `abuse.models.Ticket` :param str status: The `abuse.models.Ticket.TICKET_STATUS' reason of the cancel """ try: ticket = Ticket.objects.get(id=ticket_id) except (AttributeError, ObjectDoesNotExist, TypeError, ValueError): Logger.error(unicode('Ticket %d cannot be found in DB. Skipping...' % (ticket))) return for job in utils.scheduler.get_jobs(): if job.func_name in ASYNC_JOB_TO_CANCEL and job.kwargs['ticket_id'] == ticket.id: utils.scheduler.cancel(job.id) for job in ticket.jobs.all(): if job.asynchronousJobId in utils.scheduler: utils.scheduler.cancel(job.asynchronousJobId) job.status = 'cancelled by %s' % status job.save()
def _reinject_validated(report, user): trusted = True ticket = None if all((report.defendant, report.category, report.service)): msg = 'Looking for opened ticket for (%s, %s, %s)' Logger.debug(unicode(msg % (report.defendant.customerId, report.category.name, report.service.name))) ticket = database.search_ticket(report.defendant, report.category, report.service) # Checking specific processing workflow for workflow in ReportWorkflowFactory.instance.registered_instances: if workflow.identify(report, ticket, is_trusted=trusted) and workflow.apply(report, ticket, trusted, False): Logger.debug(unicode('Specific workflow %s applied' % (str(workflow.__class__.__name__)))) return # Create ticket if trusted new_ticket = False if not ticket: ticket = database.create_ticket(report.defendant, report.category, report.service, priority=report.provider.priority) new_ticket = True if ticket: report.ticket = Ticket.objects.get(id=ticket.id) report.status = 'Attached' report.save() database.set_ticket_higher_priority(report.ticket) database.log_action_on_ticket( ticket=ticket, action='attach_report', report=report, new_ticket=new_ticket, user=user ) try: __send_ack(report, lang='EN') except MailerServiceException as ex: raise MailerServiceException(ex)
def _check_timeout_ticket_conformance(ticket): if not ticket.defendant or not ticket.service: Logger.error(unicode('Ticket %d is invalid (no defendant/service), skipping...' % (ticket.id))) return False if ticket.status.lower() in ['closed', 'answered']: Logger.error(unicode('Ticket %d is invalid (no defendant/service or not Alarm), Skipping...' % (ticket.id))) return False if ticket.category.name.lower() not in ['phishing', 'copyright']: Logger.error(unicode('Ticket %d is in wrong category (%s, Skipping...' % (ticket.id, ticket.category.name))) return False if ticket.treatedBy: Logger.error(unicode('Ticket is %d assigned, skipping' % (ticket.id))) return False if ticket.jobs.count(): Logger.error(unicode('Ticket %d has existing jobs, exiting ...' % (ticket.id))) return False return True
def _check_auto_unassignation(ticket): history = ticket.ticketHistory.filter(actionType='ChangeStatus').order_by('-date').values_list('ticketStatus', flat=True)[:3] try: unassigned_on_multiple_alarm = ticket.treatedBy.operator.role.modelsAuthorizations['ticket']['unassignedOnMultipleAlarm'] if unassigned_on_multiple_alarm and len(history) == 3 and all([STATUS_SEQUENCE[i] == history[i] for i in xrange(3)]): database.log_action_on_ticket( ticket=ticket, action='change_treatedby', previous_value=ticket.treatedBy ) database.log_action_on_ticket( ticket=ticket, action='update_property', property='escalated', previous_value=ticket.escalated, new_value=True, ) ticket.treatedBy = None ticket.escalated = True Logger.debug(unicode('Unassigning ticket %d because of operator role configuration' % (ticket.id))) except (AttributeError, KeyError, ObjectDoesNotExist, ValueError): pass
def apply_then_close(ticket_id=None, action_id=None, ip_addr=None, resolution_id=None, user_id=None): """ Action on service then close :param int ticket_id: The id of the Cerberus `Ticket` :param int action_id: The id of the Cerberus `ServiceAction` :param str ip_addr: The ip address :param int resolution_id: The id of the Cerberus `Resolution` :param int user_id: The id of the Cerberus `User` """ # Checking conformance if not all((ticket_id, action_id, resolution_id, user_id)): msg = 'Invalid parameters submitted [ticket_id=%d, action_id=%s, resolution_id=%s, user_id=%s]' Logger.error(unicode(msg % (ticket_id, action_id, resolution_id, user_id))) return # Apply action applied = apply_action(ticket_id, action_id, ip_addr, user_id) if not applied: return # Closing ticket and updating ticket info ticket = Ticket.objects.get(id=ticket_id) user = User.objects.get(id=user_id) __close_ticket(ticket, resolution_id) database.log_action_on_ticket( ticket=ticket, action='change_status', user=user, previous_value=ticket.previousStatus, new_value=ticket.status, close_reason=ticket.resolution.codename ) ticket.resolution_id = resolution_id ticket.save() Logger.info(unicode('Ticket %d processed. Next !' % (ticket_id)))
def block_url_and_mail(ticket_id=None, report_id=None): """ Block url with PhishingService and send mail to defendant :param int ticket_id: The id of the Cerberus `abuse.models.Ticket` :param int report_id: The id of the Cerberus `abuse.models.Report` """ if not isinstance(ticket_id, Ticket): try: ticket = Ticket.objects.get(id=ticket_id) if not ticket.defendant or not ticket.service: Logger.error(unicode('Ticket %d has no defendant/service' % (ticket_id))) return except (ObjectDoesNotExist, ValueError): Logger.error(unicode('Ticket %d cannot be found in DB. Skipping...' % (ticket_id))) return else: ticket = ticket_id if not isinstance(report_id, Report): try: report = Report.objects.get(id=report_id) except (ObjectDoesNotExist, ValueError): Logger.error(unicode('Report %d cannot be found in DB. Skipping...' % (report_id))) return else: report = report_id for item in report.reportItemRelatedReport.filter(itemType='URL'): ImplementationFactory.instance.get_singleton_of('PhishingServiceBase').block_url(item.rawItem, item.report) database.add_phishing_blocked_tag(report) __send_email(ticket, report.defendant.details.email, settings.CODENAMES['phishing_blocked'], report.defendant.details.lang) ticket = Ticket.objects.get(id=ticket.id) ticket_snooze = settings.GENERAL_CONFIG['phishing']['wait'] if not ticket.status == 'WaitingAnswer' and not ticket.snoozeDuration and not ticket.snoozeStart: ticket.previousStatus = ticket.status ticket.status = 'WaitingAnswer' ticket.snoozeDuration = ticket_snooze ticket.snoozeStart = datetime.now() ticket.save() Logger.info(unicode('Ticket %d now with status WaitingAnswer for %d' % (ticket.id, ticket_snooze)))
def close_because_all_down(report=None, denied_by=None): """ Create and close a ticket when all report's items are down :param `abuse.models.Report` report: A Cerberus `abuse.models.Report` instance :param int denied_by: The id of the `abuse.models.User` who takes the decision to close the ticket """ if not isinstance(report, Report): try: report = Report.objects.get(id=report) except (AttributeError, ObjectDoesNotExist, TypeError, ValueError): Logger.error(unicode('Report %d cannot be found in DB. Skipping...' % (report))) return if not report.ticket: report.ticket = common.create_ticket(report, denied_by) report.save() # Add temp proof(s) for mail content temp_proofs = [] if not report.ticket.proof.count(): temp_proofs = common.get_temp_proofs(report.ticket) # Send email to Provider try: validate_email(report.provider.email.strip()) Logger.info(unicode('Sending email to provider')) __send_email(report.ticket, report.provider.email, settings.CODENAMES['no_more_content']) report.ticket.save() Logger.info(unicode('Mail sent to provider')) ImplementationFactory.instance.get_singleton_of('MailerServiceBase').close_thread(report.ticket) # Delete temp proof(s) for proof in temp_proofs: Proof.objects.filter(id=proof.id).delete() except (AttributeError, TypeError, ValueError, ValidationError): pass # Closing ticket and add tags common.close_ticket(report, resolution_codename=settings.CODENAMES['no_more_content']) report.ticket.tags.remove(Tag.objects.get(name=settings.TAGS['phishing_autoreopen'])) report.ticket.tags.add(Tag.objects.get(name=settings.TAGS['phishing_autoclosed'])) Logger.info(unicode('Ticket %d and report %d closed' % (report.ticket.id, report.id)))