def iterate_targets(self, counting=False): target_type = self.config['mailer.target_type'] if target_type == 'single': target_name = self.config['mailer.target_name'].split(' ') while len(target_name) < 2: target_name.append('') target = MessageTarget( first_name=target_name[0].strip(), last_name=target_name[1].strip(), email_address=self.config['mailer.target_email_address'].strip(), department=None, uid=utilities.make_message_uid() ) yield target elif target_type == 'file': target_file_h = open(self.target_file, 'rU') csv_reader = csv.DictReader(target_file_h, ('first_name', 'last_name', 'email_address', 'department')) for line_no, raw_target in enumerate(csv_reader, 1): if its.py_v2: # this will intentionally cause a UnicodeDecodeError to be raised as is the behaviour in python 3.x # when csv.DictReader is initialized raw_target = dict((k, (v if v is None else v.decode('utf-8'))) for k, v in raw_target.items()) for required_field in ('first_name', 'last_name', 'email_address'): if raw_target[required_field] is None: raw_target = None if counting: self.tab_notify_status("Target CSV line {0} skipped due to missing field: {1}".format(line_no, required_field.replace('_', ' '))) break if raw_target is None: continue department = raw_target['department'] if department is not None: department = department.strip() if department == '': department = None email_address = raw_target['email_address'] or '' email_address = email_address.strip() target = MessageTarget( first_name=raw_target['first_name'].strip(), last_name=raw_target['last_name'].strip(), email_address=email_address, department=department, uid=utilities.make_message_uid(), line=line_no ) if not target.email_address: self.logger.warning("skipping line {0} in target csv file due to missing email address".format(line_no)) continue if not utilities.is_valid_email_address(target.email_address): self.logger.warning("skipping line {0} in target csv file due to invalid email address: {1}".format(line_no, email_address)) continue yield target target_file_h.close() else: self.logger.error("the configured target type '{0}' is unsupported".format(target_type))
def iterate_targets(self, counting=False): target_type = self.config['mailer.target_type'] if target_type == 'single': target_name = self.config['mailer.target_name'].split(' ') while len(target_name) < 2: target_name.append('') target = MessageTarget( first_name=target_name[0].strip(), last_name=target_name[1].strip(), email_address=self.config['mailer.target_email_address'].strip(), department=None, uid=utilities.make_message_uid() ) yield target elif target_type == 'file': target_file_h = open(self.target_file, 'rU') csv_reader = csv.DictReader(target_file_h, ('first_name', 'last_name', 'email_address', 'department')) for line_no, raw_target in enumerate(csv_reader, 1): if its.py_v2: # this will intentionally cause a UnicodeDecodeError to be raised as is the behaviour in python 3.x # when csv.DictReader is initialized raw_target = dict((k, (v if v is None else v.decode('utf-8'))) for k, v in raw_target.items()) for required_field in ('first_name', 'last_name', 'email_address'): if raw_target[required_field] is None: raw_target = None if counting: self.tab_notify_status("Target CSV line {0} skipped due to missing field: {1}".format(line_no, required_field.replace('_', ' '))) break if raw_target is None: continue department = raw_target['department'] if department is not None: department = department.strip() if department == '': department = None email_address = raw_target['email_address'] or '' email_address = email_address.strip() target = MessageTarget( first_name=raw_target['first_name'].strip(), last_name=raw_target['last_name'].strip(), email_address=email_address, department=department, uid=utilities.make_message_uid(), line=line_no ) if not target.email_address: self.logger.warning("skipping line {0} in target csv file due to missing email address".format(line_no)) continue if not utilities.is_valid_email_address(target.email_address): self.logger.warning("skipping line {0} in target csv file due to invalid email address: {1}".format(line_no, email_address)) continue yield target target_file_h.close() else: self.logger.error("the configured target type '{0}' is unsupported".format(target_type))
def _iterate_targets_file(target_file, config=None): target_file_h = open(target_file, 'rU') csv_reader = csv.DictReader( target_file_h, ('first_name', 'last_name', 'email_address', 'department')) uid_charset = None if config is None else config[ 'mailer.message_uid.charset'] for line_no, raw_target in enumerate(csv_reader, 1): if None in raw_target: # remove the additional fields del raw_target[None] if its.py_v2: # this will intentionally cause a UnicodeDecodeError to be raised as is the behaviour in python 3.x # when csv.DictReader is initialized raw_target = dict((k, (v if v is None else v.decode('utf-8'))) for k, v in raw_target.items()) if uid_charset is not None: raw_target['uid'] = utilities.make_message_uid( upper=uid_charset['upper'], lower=uid_charset['lower'], digits=uid_charset['digits']) target = MessageTarget(line=line_no, **raw_target) # the caller needs to catch and process the missing fields appropriately yield target target_file_h.close()
def iterate_targets(self, counting=False): """ Iterate over each of the targets as defined within the configuration. If *counting* is ``False``, messages will not be displayed to the end user through the notification tab. :param bool counting: Whether or not to iterate strictly for counting purposes. :return: Each message target. :rtype: :py:class:`~.MessageTarget` """ mailer_tab = self.application.main_tabs['mailer'] target_type = self.config['mailer.target_type'] if target_type == 'single': target_name = self.config['mailer.target_name'].split(' ') while len(target_name) < 2: target_name.append('') uid_charset = self.config['mailer.message_uid.charset'] target = MessageTarget( first_name=target_name[0].strip(), last_name=target_name[1].strip(), email_address=self.config['mailer.target_email_address'].strip( ), uid=utilities.make_message_uid(upper=uid_charset['upper'], lower=uid_charset['lower'], digits=uid_charset['digits'])) if not counting: mailer_tab.emit('target-create', target) yield target elif target_type == 'file': for target in _iterate_targets_file(self.target_file, config=self.config): missing_fields = target.missing_fields if missing_fields: if counting: msg = "Target CSV line {0} skipped due to missing field{1}".format( target.line, ('' if len(missing_fields) == 1 else 's')) msg += ':' + ', '.join( field.replace('_', ' ') for field in missing_fields) self.tab_notify_status(msg) continue if not utilities.is_valid_email_address(target.email_address): self.logger.warning( "skipping line {0} in target csv file due to invalid email address: {1}" .format(target.line, target.email_address)) continue if not counting: mailer_tab.emit('target-create', target) yield target else: self.logger.error( "the configured target type '{0}' is unsupported".format( target_type))
def __init__(self, first_name, last_name, email_address, uid=None, department=None, line=None): self.first_name = first_name """The target recipient's first name.""" self.last_name = last_name """The target recipient's last name.""" self.email_address = utilities.nonempty_string(email_address) """The target recipient's email address.""" self.uid = uid """The unique identifier that is going to be used for this target.""" if self.uid is None: self.uid = utilities.make_message_uid() self.department = utilities.nonempty_string(department) """The target recipient's department name.""" self.line = line """The line number in the file from which this target was loaded."""
def iterate_targets(self, counting=False): """ Iterate over each of the targets as defined within the configuration. If *counting* is ``False``, messages will not be displayed to the end user through the notification tab. :param bool counting: Whether or not to iterate strictly for counting purposes. :return: Each message target. :rtype: :py:class:`~.MessageTarget` """ mailer_tab = self.application.main_tabs['mailer'] target_type = self.config['mailer.target_type'] if target_type == 'single': target_name = self.config['mailer.target_name'].split(' ') while len(target_name) < 2: target_name.append('') uid_charset = self.config['mailer.message_uid.charset'] target = MessageTarget( first_name=target_name[0].strip(), last_name=target_name[1].strip(), email_address=self.config['mailer.target_email_address'].strip(), uid=utilities.make_message_uid( upper=uid_charset['upper'], lower=uid_charset['lower'], digits=uid_charset['digits'] ) ) if not counting: mailer_tab.emit('target-create', target) yield target elif target_type == 'file': for target in _iterate_targets_file(self.target_file, config=self.config): missing_fields = target.missing_fields if missing_fields: if counting: msg = "Target CSV line {0} skipped due to missing field{1}".format(target.line, ('' if len(missing_fields) == 1 else 's')) msg += ':' + ', '.join(field.replace('_', ' ') for field in missing_fields) self.tab_notify_status(msg) continue if not utilities.is_valid_email_address(target.email_address): self.logger.warning("skipping line {0} in target csv file due to invalid email address: {1}".format(target.line, target.email_address)) continue if not counting: mailer_tab.emit('target-create', target) yield target else: self.logger.error("the configured target type '{0}' is unsupported".format(target_type))
def _iterate_targets_file(target_file, config=None): target_file_h = open(target_file, 'rU') csv_reader = csv.DictReader(target_file_h, ('first_name', 'last_name', 'email_address', 'department')) uid_charset = None if config is None else config['mailer.message_uid.charset'] for line_no, raw_target in enumerate(csv_reader, 1): if None in raw_target: # remove the additional fields del raw_target[None] if its.py_v2: # this will intentionally cause a UnicodeDecodeError to be raised as is the behaviour in python 3.x # when csv.DictReader is initialized raw_target = dict((k, (v if v is None else v.decode('utf-8'))) for k, v in raw_target.items()) if uid_charset is not None: raw_target['uid'] = utilities.make_message_uid( upper=uid_charset['upper'], lower=uid_charset['lower'], digits=uid_charset['digits'] ) target = MessageTarget(line=line_no, **raw_target) # the caller needs to catch and process the missing fields appropriately yield target target_file_h.close()
def render_message_template(template, config, target=None, analyze=False): """ Take a message from a template and format it to be sent by replacing variables and processing other template directives. If the *target* parameter is not set, a placeholder will be created and the message will be formatted to be previewed. :param str template: The message template. :param dict config: The King Phisher client configuration. :param target: The messages intended target information. :type target: :py:class:`.MessageTarget` :param bool analyze: Set the template environment to analyze mode. :return: The formatted message. :rtype: str """ if target is None: target = MessageTarget( first_name='Alice', last_name='Liddle', email_address='*****@*****.**', department=None, uid=(config['server_config'].get('server.secret_id') or utilities.make_message_uid())) template_environment.set_mode(template_environment.MODE_PREVIEW) if analyze: template_environment.set_mode(template_environment.MODE_ANALYZE) template = template_environment.from_string(template) template_vars = {} template_vars['campaign'] = dict(id=str(config['campaign_id']), name=config['campaign_name']) template_vars['client'] = dict( first_name=target.first_name, last_name=target.last_name, email_address=target.email_address, company_name=config.get('mailer.company_name'), message_id=target.uid) template_vars['sender'] = dict( email=config.get('mailer.source_email'), friendly_alias=config.get('mailer.source_email_alias'), reply_to=config.get('mailer.reply_to_email')) template_vars['uid'] = target.uid message_type = config.get('mailer.message_type', 'email') template_vars['message_type'] = message_type if message_type == 'calendar_invite': template_vars['calendar_invite'] = dict( all_day=config.get('mailer.calendar_invite_all_day'), location=config.get('mailer.calendar_invite_location'), start=get_invite_start_from_config(config), summary=config.get('mailer.calendar_invite_summary')) template_vars['message'] = dict( attachment=config.get('mailer.attachment_file'), importance=config.get('mailer.importance'), recipient=dict( field=config.get('mailer.target_field', 'to'), to=(target.email_address if config.get('mailer.target_field') == 'to' else config.get('mailer.recipient_email_to', '')), cc=(target.email_address if config.get('mailer.target_field') == 'cc' else config.get('mailer.recipient_email_cc', '')), bcc=(target.email_address if config.get('mailer.target_field') == 'bcc' else '')), sensitivity=config.get('mailer.sensitivity'), subject=config.get('mailer.subject'), template=config.get('mailer.html_file'), type=message_type) webserver_url = config.get('mailer.webserver_url', '') webserver_url = urllib.parse.urlparse(webserver_url) tracking_image = config['server_config']['server.tracking_image'] template_vars['webserver'] = webserver_url.netloc tracking_url = urllib.parse.urlunparse( (webserver_url.scheme, webserver_url.netloc, tracking_image, '', 'id=' + target.uid, '')) webserver_url = urllib.parse.urlunparse( (webserver_url.scheme, webserver_url.netloc, webserver_url.path, '', '', '')) template_vars[ 'tracking_dot_image_tag'] = "<img src=\"{0}\" style=\"display:none\" />".format( tracking_url) template_vars_url = {} template_vars_url[ 'rickroll'] = 'http://www.youtube.com/watch?v=oHg5SJYRHA0' template_vars_url['webserver'] = webserver_url + '?id=' + target.uid template_vars_url['webserver_raw'] = webserver_url template_vars_url['tracking_dot'] = tracking_url template_vars['url'] = template_vars_url template_vars.update(template_environment.standard_variables) return template.render(template_vars)
def render_message_template(template, config, target=None, analyze=False): """ Take a message from a template and format it to be sent by replacing variables and processing other template directives. If the *target* parameter is not set, a placeholder will be created and the message will be formatted to be previewed. :param str template: The message template. :param dict config: The King Phisher client configuration. :param target: The messages intended target information. :type target: :py:class:`.MessageTarget` :param bool analyze: Set the template environment to analyze mode. :return: The formatted message. :rtype: str """ if target is None: target = MessageTarget( first_name='Alice', last_name='Liddle', email_address='*****@*****.**', department=None, uid=(config['server_config'].get('server.secret_id') or utilities.make_message_uid()) ) template_environment.set_mode(template_environment.MODE_PREVIEW) if analyze: template_environment.set_mode(template_environment.MODE_ANALYZE) template = template_environment.from_string(template) template_vars = {} template_vars['campaign'] = dict( id=str(config['campaign_id']), name=config['campaign_name'] ) template_vars['client'] = dict( first_name=target.first_name, last_name=target.last_name, email_address=target.email_address, company_name=config.get('mailer.company_name'), message_id=target.uid ) template_vars['sender'] = dict( email=config.get('mailer.source_email'), friendly_alias=config.get('mailer.source_email_alias'), reply_to=config.get('mailer.reply_to_email') ) template_vars['uid'] = target.uid message_type = config.get('mailer.message_type', 'email') template_vars['message_type'] = message_type if message_type == 'calendar_invite': template_vars['calendar_invite'] = dict( all_day=config.get('mailer.calendar_invite_all_day'), location=config.get('mailer.calendar_invite_location'), start=get_invite_start_from_config(config), summary=config.get('mailer.calendar_invite_summary') ) template_vars['message'] = dict( attachment=config.get('mailer.attachment_file'), importance=config.get('mailer.importance'), recipient=dict( field=config.get('mailer.target_field', 'to'), to=(target.email_address if config.get('mailer.target_field') == 'to' else config.get('mailer.recipient_email_to', '')), cc=(target.email_address if config.get('mailer.target_field') == 'cc' else config.get('mailer.recipient_email_cc', '')), bcc=(target.email_address if config.get('mailer.target_field') == 'bcc' else '') ), sensitivity=config.get('mailer.sensitivity'), subject=config.get('mailer.subject'), template=config.get('mailer.html_file'), type=message_type ) webserver_url = config.get('mailer.webserver_url', '') webserver_url = urllib.parse.urlparse(webserver_url) tracking_image = config['server_config']['server.tracking_image'] template_vars['webserver'] = webserver_url.netloc tracking_url = urllib.parse.urlunparse((webserver_url.scheme, webserver_url.netloc, tracking_image, '', 'id=' + target.uid, '')) webserver_url = urllib.parse.urlunparse((webserver_url.scheme, webserver_url.netloc, webserver_url.path, '', '', '')) template_vars['tracking_dot_image_tag'] = "<img src=\"{0}\" style=\"display:none\" />".format(tracking_url) template_vars_url = {} template_vars_url['rickroll'] = 'http://www.youtube.com/watch?v=oHg5SJYRHA0' template_vars_url['webserver'] = webserver_url + '?id=' + target.uid template_vars_url['webserver_raw'] = webserver_url template_vars_url['tracking_dot'] = tracking_url template_vars['url'] = template_vars_url template_vars.update(template_environment.standard_variables) return template.render(template_vars)