From 10ef6fc1354d7446aa6e2ed7f9e5ae8ea5dfe8a7 Mon Sep 17 00:00:00 2001 From: Sean Whalen Date: Mon, 4 Mar 2024 10:50:50 -0500 Subject: [PATCH] Update docs --- _modules/index.html | 6 +- _modules/parsedmarc.html | 28 +- _modules/parsedmarc/elastic.html | 95 +-- _modules/parsedmarc/opensearch.html | 860 ++++++++++++++++++++++++++++ _modules/parsedmarc/splunk.html | 5 +- _modules/parsedmarc/utils.html | 5 +- _sources/api.md.txt | 8 + _sources/index.md.txt | 5 +- _sources/opensearch.md.txt | 14 + _sources/usage.md.txt | 26 + _static/documentation_options.js | 2 +- api.html | 146 ++++- contributing.html | 5 +- davmail.html | 5 +- dmarc.html | 5 +- elasticsearch.html | 9 +- genindex.html | 47 +- index.html | 15 +- installation.html | 5 +- kibana.html | 9 +- mailing-lists.html | 5 +- objects.inv | Bin 1016 -> 1085 bytes opensearch.html | 141 +++++ output.html | 5 +- py-modindex.html | 10 +- search.html | 5 +- searchindex.js | 2 +- splunk.html | 5 +- usage.html | 35 +- 29 files changed, 1408 insertions(+), 100 deletions(-) create mode 100644 _modules/parsedmarc/opensearch.html create mode 100644 _sources/opensearch.md.txt create mode 100644 opensearch.html diff --git a/_modules/index.html b/_modules/index.html index 065e3344..87e4244c 100644 --- a/_modules/index.html +++ b/_modules/index.html @@ -3,7 +3,7 @@ - Overview: module code — parsedmarc 8.7.0 documentation + Overview: module code — parsedmarc 8.8.0 documentation @@ -35,7 +35,7 @@ parsedmarc
- 8.7.0 + 8.8.0
@@ -51,6 +51,7 @@
  • Using parsedmarc
  • Sample outputs
  • Elasticsearch and Kibana
  • +
  • OpenSearch and Grafana
  • Using the Kibana dashboards
  • Splunk
  • Accessing an inbox using OWA/EWS
  • @@ -85,6 +86,7 @@

    All modules for which code is available

    diff --git a/_modules/parsedmarc.html b/_modules/parsedmarc.html index 2f3e6ca2..dc6e4162 100644 --- a/_modules/parsedmarc.html +++ b/_modules/parsedmarc.html @@ -3,7 +3,7 @@ - parsedmarc — parsedmarc 8.7.0 documentation + parsedmarc — parsedmarc 8.8.0 documentation @@ -35,7 +35,7 @@ parsedmarc
    - 8.7.0 + 8.8.0
    @@ -51,6 +51,7 @@
  • Using parsedmarc
  • Sample outputs
  • Elasticsearch and Kibana
  • +
  • OpenSearch and Grafana
  • Using the Kibana dashboards
  • Splunk
  • Accessing an inbox using OWA/EWS
  • @@ -120,7 +121,7 @@

    Source code for parsedmarc

     from parsedmarc.utils import parse_email
     from parsedmarc.utils import timestamp_to_human, human_timestamp_to_datetime
     
    -__version__ = "8.7.0"
    +__version__ = "8.8.0"
     
     logger.debug("parsedmarc v{0}".format(__version__))
     
    @@ -300,10 +301,14 @@ 

    Source code for parsedmarc

             new_failure_details = OrderedDict(
                 result_type=failure_details["result-type"],
                 failed_session_count=failure_details["failed-session-count"],
    -            sending_mta_ip=failure_details["sending-mta-ip"],
    -            receiving_ip=failure_details["receiving-ip"]
             )
     
    +        if "sending-mta-ip" in failure_details:
    +            new_failure_details["sending_mta_ip"] = failure_details[
    +                "sending-mta-ip"]
    +        if "receiving-ip" in failure_details:
    +            new_failure_details["receiving_ip"] = failure_details[
    +                "receiving-ip"]
             if "receiving-mx-hostname" in failure_details:
                 new_failure_details["receiving_mx_hostname"] = failure_details[
                     "receiving-mx-hostname"]
    @@ -389,6 +394,7 @@ 

    Source code for parsedmarc

                 organization_name=report["organization-name"],
                 begin_date=report["date-range"]["start-datetime"],
                 end_date=report["date-range"]["end-datetime"],
    +            contact_info=report["contact-info"],
                 report_id=report["report-id"],
                 policies=policies
             )
    @@ -449,10 +455,10 @@ 

    Source code for parsedmarc

         """
     
         fields = ["organization_name", "begin_date", "end_date", "report_id",
    -              "successful_session_count", "failed_session_count",
    -              "policy_domain", "policy_type", "policy_strings",
    -              "mx_host_patterns", "sending_mta_ip", "receiving_ip",
    -              "receiving_mx_hostname", "receiving_mx_helo",
    +              "result_type", "successful_session_count",
    +              "failed_session_count", "policy_domain", "policy_type",
    +              "policy_strings", "mx_host_patterns", "sending_mta_ip",
    +              "receiving_ip", "receiving_mx_hostname", "receiving_mx_helo",
                   "additional_info_uri", "failure_reason_code"]
     
         csv_file_object = StringIO(newline="\n")
    @@ -546,7 +552,7 @@ 

    Source code for parsedmarc

             new_report_metadata["report_id"] = report_id
             date_range = report["report_metadata"]["date_range"]
             if int(date_range["end"]) - int(date_range["begin"]) > 2*86400:
    -            _error = "Timespan > 24 hours - RFC 7489 section 7.2"
    +            _error = "Time span > 24 hours - RFC 7489 section 7.2"
                 errors.append(_error)
             date_range["begin"] = timestamp_to_human(date_range["begin"])
             date_range["end"] = timestamp_to_human(date_range["end"])
    @@ -1539,7 +1545,7 @@ 

    Source code for parsedmarc

                         message = "Moving message"
                         logger.debug("{0} {1} of {2}: UID {3}".format(
                             message,
    -                        i + 1, smtp_tls_msg_uids, msg_uid))
    +                        i + 1, number_of_smtp_tls_uids, msg_uid))
                         try:
                             connection.move_message(msg_uid,
                                                     smtp_tls_reports_folder)
    diff --git a/_modules/parsedmarc/elastic.html b/_modules/parsedmarc/elastic.html
    index be7ad03c..dfbd81f1 100644
    --- a/_modules/parsedmarc/elastic.html
    +++ b/_modules/parsedmarc/elastic.html
    @@ -3,7 +3,7 @@
     
       
       
    -  parsedmarc.elastic — parsedmarc 8.7.0 documentation
    +  parsedmarc.elastic — parsedmarc 8.8.0 documentation
           
           
     
    @@ -35,7 +35,7 @@
                 parsedmarc
               
                   
    - 8.7.0 + 8.8.0
    @@ -51,6 +51,7 @@
  • Using parsedmarc
  • Sample outputs
  • Elasticsearch and Kibana
  • +
  • OpenSearch and Grafana
  • Using the Kibana dashboards
  • Splunk
  • Accessing an inbox using OWA/EWS
  • @@ -274,12 +275,14 @@

    Source code for parsedmarc.elastic

                                 receiving_ip,
                                 receiving_mx_helo,
                                 failed_session_count,
    +                            sending_mta_ip=None,
                                 receiving_mx_hostname=None,
                                 additional_information_uri=None,
                                 failure_reason_code=None):
    -        self.failure_details.append(
    +        _details = _SMTPTLSFailureDetailsDoc(
                 result_type=result_type,
                 ip_address=ip_address,
    +            sending_mta_ip=sending_mta_ip,
                 receiving_mx_hostname=receiving_mx_hostname,
                 receiving_mx_helo=receiving_mx_helo,
                 receiving_ip=receiving_ip,
    @@ -287,9 +290,10 @@ 

    Source code for parsedmarc.elastic

                 additional_information=additional_information_uri,
                 failure_reason_code=failure_reason_code
             )
    +        self.failure_details.append(_details)
     
     
    -class _SMTPTLSFailureReportDoc(Document):
    +class _SMTPTLSReportDoc(Document):
     
         class Index:
             name = "smtp_tls"
    @@ -436,7 +440,7 @@ 

    Source code for parsedmarc.elastic

                                                number_of_shards=1,
                                                number_of_replicas=0):
         """
    -    Saves a parsed DMARC aggregate report to ElasticSearch
    +    Saves a parsed DMARC aggregate report to Elasticsearch
     
         Args:
             aggregate_report (OrderedDict): A parsed forensic report
    @@ -571,7 +575,7 @@ 

    Source code for parsedmarc.elastic

                                               number_of_shards=1,
                                               number_of_replicas=0):
         """
    -        Saves a parsed DMARC forensic report to ElasticSearch
    +        Saves a parsed DMARC forensic report to Elasticsearch
     
             Args:
                 forensic_report (OrderedDict): A parsed forensic report
    @@ -714,7 +718,7 @@ 

    Source code for parsedmarc.elastic

                                               number_of_shards=1,
                                               number_of_replicas=0):
         """
    -    Saves a parsed SMTP TLS report to elasticSearch
    +    Saves a parsed SMTP TLS report to Elasticsearch
     
         Args:
             report (OrderedDict): A parsed SMTP TLS report
    @@ -726,8 +730,8 @@ 

    Source code for parsedmarc.elastic

         Raises:
                 AlreadySaved
         """
    -    logger.info("Saving aggregate report to Elasticsearch")
    -    org_name = report["org_name"]
    +    logger.info("Saving smtp tls report to Elasticsearch")
    +    org_name = report["organization_name"]
         report_id = report["report_id"]
         begin_date = human_timestamp_to_datetime(report["begin_date"],
                                                  to_utc=True)
    @@ -750,7 +754,7 @@ 

    Source code for parsedmarc.elastic

         if index_suffix is not None:
             search = Search(index="smtp_tls_{0}*".format(index_suffix))
         else:
    -        search = Search(index="smtp_tls")
    +        search = Search(index="smtp_tls*")
         query = org_name_query & report_id_query
         query = query & begin_date_query & end_date_query
         search.query = query
    @@ -775,11 +779,11 @@ 

    Source code for parsedmarc.elastic

         index_settings = dict(number_of_shards=number_of_shards,
                               number_of_replicas=number_of_replicas)
     
    -    smtp_tls_doc = _SMTPTLSFailureReportDoc(
    -        organization_name=report["organization_name"],
    -        date_range=[report["date_begin"], report["date_end"]],
    -        date_begin=report["date_begin"],
    -        date_end=report["date_end"],
    +    smtp_tls_doc = _SMTPTLSReportDoc(
    +        org_name=report["organization_name"],
    +        date_range=[report["begin_date"], report["end_date"]],
    +        date_begin=report["begin_date"],
    +        date_end=report["end_date"],
             contact_info=report["contact_info"],
             report_id=report["report_id"]
         )
    @@ -794,32 +798,49 @@ 

    Source code for parsedmarc.elastic

             policy_doc = _SMTPTLSPolicyDoc(
                 policy_domain=policy["policy_domain"],
                 policy_type=policy["policy_type"],
    +            succesful_session_count=policy["successful_session_count"],
    +            failed_session_count=policy["failed_session_count"],
                 policy_string=policy_strings,
                 mx_host_patterns=mx_host_patterns
             )
             if "failure_details" in policy:
    -            failure_details = policy["failure_details"]
    -            receiving_mx_hostname = None
    -            additional_information_uri = None
    -            failure_reason_code = None
    -            if "receiving_mx_hostname" in failure_details:
    -                receiving_mx_hostname = failure_details[
    -                    "receiving_mx_hostname"]
    -            if "additional_information_uri" in failure_details:
    -                additional_information_uri = failure_details[
    -                    "additional_information_uri"]
    -            if "failure_reason_code" in failure_details:
    -                failure_reason_code = failure_details["failure_reason_code"]
    -            policy_doc.add_failure_details(
    -                result_type=failure_details["result_type"],
    -                ip_address=failure_details["ip_address"],
    -                receiving_ip=failure_details["receiving_ip"],
    -                receiving_mx_helo=failure_details["receiving_mx_helo"],
    -                failed_session_count=failure_details["failed_session_count"],
    -                receiving_mx_hostname=receiving_mx_hostname,
    -                additional_information_uri=additional_information_uri,
    -                failure_reason_code=failure_reason_code
    -            )
    +            for failure_detail in policy["failure_details"]:
    +                receiving_mx_hostname = None
    +                additional_information_uri = None
    +                failure_reason_code = None
    +                ip_address = None
    +                receiving_ip = None
    +                receiving_mx_helo = None
    +                sending_mta_ip = None
    +
    +                if "receiving_mx_hostname" in failure_detail:
    +                    receiving_mx_hostname = failure_detail[
    +                        "receiving_mx_hostname"]
    +                if "additional_information_uri" in failure_detail:
    +                    additional_information_uri = failure_detail[
    +                        "additional_information_uri"]
    +                if "failure_reason_code" in failure_detail:
    +                    failure_reason_code = failure_detail["failure_reason_code"]
    +                if "ip_address" in failure_detail:
    +                    ip_address = failure_detail["ip_address"]
    +                if "receiving_ip" in failure_detail:
    +                    receiving_ip = failure_detail["receiving_ip"]
    +                if "receiving_mx_helo" in failure_detail:
    +                    receiving_mx_helo = failure_detail["receiving_mx_helo"]
    +                if "sending_mta_ip" in failure_detail:
    +                    sending_mta_ip = failure_detail["sending_mta_ip"]
    +                policy_doc.add_failure_details(
    +                    result_type=failure_detail["result_type"],
    +                    ip_address=ip_address,
    +                    receiving_ip=receiving_ip,
    +                    receiving_mx_helo=receiving_mx_helo,
    +                    failed_session_count=failure_detail[
    +                        "failed_session_count"],
    +                    sending_mta_ip=sending_mta_ip,
    +                    receiving_mx_hostname=receiving_mx_hostname,
    +                    additional_information_uri=additional_information_uri,
    +                    failure_reason_code=failure_reason_code
    +                )
             smtp_tls_doc.policies.append(policy_doc)
     
         create_indexes([index], index_settings)
    diff --git a/_modules/parsedmarc/opensearch.html b/_modules/parsedmarc/opensearch.html
    new file mode 100644
    index 00000000..01fd6da3
    --- /dev/null
    +++ b/_modules/parsedmarc/opensearch.html
    @@ -0,0 +1,860 @@
    +
    +
    +
    +  
    +  
    +  parsedmarc.opensearch — parsedmarc 8.8.0 documentation
    +      
    +      
    +
    +  
    +  
    +  
    +        
    +        
    +        
    +        
    +        
    +        
    +    
    +    
    +     
    +
    +
    + 
    +  
    + + +
    + +
    +
    +
    + +
    +
    +
    +
    + +

    Source code for parsedmarc.opensearch

    +# -*- coding: utf-8 -*-
    +
    +from collections import OrderedDict
    +
    +from opensearchpy import Q, connections, Object, Document, Index, Nested, \
    +    InnerDoc, Integer, Text, Boolean, Ip, Date, Search
    +from opensearchpy.helpers import reindex
    +
    +from parsedmarc.log import logger
    +from parsedmarc.utils import human_timestamp_to_datetime
    +from parsedmarc import InvalidForensicReport
    +
    +
    +
    [docs]class OpenSearchError(Exception): + """Raised when an OpenSearch error occurs"""
    + + +class _PolicyOverride(InnerDoc): + type = Text() + comment = Text() + + +class _PublishedPolicy(InnerDoc): + domain = Text() + adkim = Text() + aspf = Text() + p = Text() + sp = Text() + pct = Integer() + fo = Text() + + +class _DKIMResult(InnerDoc): + domain = Text() + selector = Text() + result = Text() + + +class _SPFResult(InnerDoc): + domain = Text() + scope = Text() + results = Text() + + +class _AggregateReportDoc(Document): + class Index: + name = "dmarc_aggregate" + + xml_schema = Text() + org_name = Text() + org_email = Text() + org_extra_contact_info = Text() + report_id = Text() + date_range = Date() + date_begin = Date() + date_end = Date() + errors = Text() + published_policy = Object(_PublishedPolicy) + source_ip_address = Ip() + source_country = Text() + source_reverse_dns = Text() + source_Base_domain = Text() + message_count = Integer + disposition = Text() + dkim_aligned = Boolean() + spf_aligned = Boolean() + passed_dmarc = Boolean() + policy_overrides = Nested(_PolicyOverride) + header_from = Text() + envelope_from = Text() + envelope_to = Text() + dkim_results = Nested(_DKIMResult) + spf_results = Nested(_SPFResult) + + def add_policy_override(self, type_, comment): + self.policy_overrides.append(_PolicyOverride(type=type_, + comment=comment)) + + def add_dkim_result(self, domain, selector, result): + self.dkim_results.append(_DKIMResult(domain=domain, + selector=selector, + result=result)) + + def add_spf_result(self, domain, scope, result): + self.spf_results.append(_SPFResult(domain=domain, + scope=scope, + result=result)) + + def save(self, ** kwargs): + self.passed_dmarc = False + self.passed_dmarc = self.spf_aligned or self.dkim_aligned + + return super().save(** kwargs) + + +class _EmailAddressDoc(InnerDoc): + display_name = Text() + address = Text() + + +class _EmailAttachmentDoc(Document): + filename = Text() + content_type = Text() + sha256 = Text() + + +class _ForensicSampleDoc(InnerDoc): + raw = Text() + headers = Object() + headers_only = Boolean() + to = Nested(_EmailAddressDoc) + subject = Text() + filename_safe_subject = Text() + _from = Object(_EmailAddressDoc) + date = Date() + reply_to = Nested(_EmailAddressDoc) + cc = Nested(_EmailAddressDoc) + bcc = Nested(_EmailAddressDoc) + body = Text() + attachments = Nested(_EmailAttachmentDoc) + + def add_to(self, display_name, address): + self.to.append(_EmailAddressDoc(display_name=display_name, + address=address)) + + def add_reply_to(self, display_name, address): + self.reply_to.append(_EmailAddressDoc(display_name=display_name, + address=address)) + + def add_cc(self, display_name, address): + self.cc.append(_EmailAddressDoc(display_name=display_name, + address=address)) + + def add_bcc(self, display_name, address): + self.bcc.append(_EmailAddressDoc(display_name=display_name, + address=address)) + + def add_attachment(self, filename, content_type, sha256): + self.attachments.append(_EmailAttachmentDoc(filename=filename, + content_type=content_type, sha256=sha256)) + + +class _ForensicReportDoc(Document): + class Index: + name = "dmarc_forensic" + + feedback_type = Text() + user_agent = Text() + version = Text() + original_mail_from = Text() + arrival_date = Date() + domain = Text() + original_envelope_id = Text() + authentication_results = Text() + delivery_results = Text() + source_ip_address = Ip() + source_country = Text() + source_reverse_dns = Text() + source_authentication_mechanisms = Text() + source_auth_failures = Text() + dkim_domain = Text() + original_rcpt_to = Text() + sample = Object(_ForensicSampleDoc) + + +class _SMTPTLSFailureDetailsDoc(InnerDoc): + result_type = Text() + sending_mta_ip = Ip() + receiving_mx_helo = Text() + receiving_ip = Ip() + failed_session_count = Integer() + additional_information_uri = Text() + failure_reason_code = Text() + + +class _SMTPTLSPolicyDoc(InnerDoc): + policy_domain = Text() + policy_type = Text() + policy_strings = Text() + mx_host_patterns = Text() + successful_session_count = Integer() + failed_session_count = Integer() + failure_details = Nested(_SMTPTLSFailureDetailsDoc) + + def add_failure_details(self, result_type, ip_address, + receiving_ip, + receiving_mx_helo, + failed_session_count, + receiving_mx_hostname=None, + additional_information_uri=None, + failure_reason_code=None): + self.failure_details.append( + result_type=result_type, + ip_address=ip_address, + receiving_mx_hostname=receiving_mx_hostname, + receiving_mx_helo=receiving_mx_helo, + receiving_ip=receiving_ip, + failed_session_count=failed_session_count, + additional_information=additional_information_uri, + failure_reason_code=failure_reason_code + ) + + +class _SMTPTLSFailureReportDoc(Document): + + class Index: + name = "smtp_tls" + + organization_name = Text() + date_range = Date() + date_begin = Date() + date_end = Date() + contact_info = Text() + report_id = Text() + policies = Nested(_SMTPTLSPolicyDoc) + + def add_policy(self, policy_type, policy_domain, + successful_session_count, + failed_session_count, + policy_string=None, + mx_host_patterns=None, + failure_details=None): + self.policies.append(policy_type=policy_type, + policy_domain=policy_domain, + successful_session_count=successful_session_count, + failed_session_count=failed_session_count, + policy_string=policy_string, + mx_host_patterns=mx_host_patterns, + failure_details=failure_details) + + +
    [docs]class AlreadySaved(ValueError): + """Raised when a report to be saved matches an existing report"""
    + + +
    [docs]def set_hosts(hosts, use_ssl=False, ssl_cert_path=None, + username=None, password=None, apiKey=None, timeout=60.0): + """ + Sets the OpenSearch hosts to use + + Args: + hosts (str|list): A hostname or URL, or list of hostnames or URLs + use_ssl (bool): Use an HTTPS connection to the server + ssl_cert_path (str): Path to the certificate chain + username (str): The username to use for authentication + password (str): The password to use for authentication + apiKey (str): The Base64 encoded API key to use for authentication + timeout (float): Timeout in seconds + """ + if not isinstance(hosts, list): + hosts = [hosts] + conn_params = { + "hosts": hosts, + "timeout": timeout + } + if use_ssl: + conn_params['use_ssl'] = True + if ssl_cert_path: + conn_params['verify_certs'] = True + conn_params['ca_certs'] = ssl_cert_path + else: + conn_params['verify_certs'] = False + if username: + conn_params['http_auth'] = (username+":"+password) + if apiKey: + conn_params['api_key'] = apiKey + connections.create_connection(**conn_params)
    + + +
    [docs]def create_indexes(names, settings=None): + """ + Create OpenSearch indexes + + Args: + names (list): A list of index names + settings (dict): Index settings + + """ + for name in names: + index = Index(name) + try: + if not index.exists(): + logger.debug("Creating OpenSearch index: {0}".format(name)) + if settings is None: + index.settings(number_of_shards=1, + number_of_replicas=0) + else: + index.settings(**settings) + index.create() + except Exception as e: + raise OpenSearchError( + "OpenSearch error: {0}".format(e.__str__()))
    + + +
    [docs]def migrate_indexes(aggregate_indexes=None, forensic_indexes=None): + """ + Updates index mappings + + Args: + aggregate_indexes (list): A list of aggregate index names + forensic_indexes (list): A list of forensic index names + """ + version = 2 + if aggregate_indexes is None: + aggregate_indexes = [] + if forensic_indexes is None: + forensic_indexes = [] + for aggregate_index_name in aggregate_indexes: + if not Index(aggregate_index_name).exists(): + continue + aggregate_index = Index(aggregate_index_name) + doc = "doc" + fo_field = "published_policy.fo" + fo = "fo" + fo_mapping = aggregate_index.get_field_mapping(fields=[fo_field]) + fo_mapping = fo_mapping[list(fo_mapping.keys())[0]]["mappings"] + if doc not in fo_mapping: + continue + + fo_mapping = fo_mapping[doc][fo_field]["mapping"][fo] + fo_type = fo_mapping["type"] + if fo_type == "long": + new_index_name = "{0}-v{1}".format(aggregate_index_name, version) + body = {"properties": {"published_policy.fo": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + } + } + } + Index(new_index_name).create() + Index(new_index_name).put_mapping(doc_type=doc, body=body) + reindex(connections.get_connection(), aggregate_index_name, + new_index_name) + Index(aggregate_index_name).delete() + + for forensic_index in forensic_indexes: + pass
    + + +
    [docs]def save_aggregate_report_to_opensearch(aggregate_report, + index_suffix=None, + monthly_indexes=False, + number_of_shards=1, + number_of_replicas=0): + """ + Saves a parsed DMARC aggregate report to OpenSearch + + Args: + aggregate_report (OrderedDict): A parsed forensic report + index_suffix (str): The suffix of the name of the index to save to + monthly_indexes (bool): Use monthly indexes instead of daily indexes + number_of_shards (int): The number of shards to use in the index + number_of_replicas (int): The number of replicas to use in the index + + Raises: + AlreadySaved + """ + logger.info("Saving aggregate report to OpenSearch") + aggregate_report = aggregate_report.copy() + metadata = aggregate_report["report_metadata"] + org_name = metadata["org_name"] + report_id = metadata["report_id"] + domain = aggregate_report["policy_published"]["domain"] + begin_date = human_timestamp_to_datetime(metadata["begin_date"], + to_utc=True) + end_date = human_timestamp_to_datetime(metadata["end_date"], + to_utc=True) + begin_date_human = begin_date.strftime("%Y-%m-%d %H:%M:%SZ") + end_date_human = end_date.strftime("%Y-%m-%d %H:%M:%SZ") + if monthly_indexes: + index_date = begin_date.strftime("%Y-%m") + else: + index_date = begin_date.strftime("%Y-%m-%d") + aggregate_report["begin_date"] = begin_date + aggregate_report["end_date"] = end_date + date_range = [aggregate_report["begin_date"], + aggregate_report["end_date"]] + + org_name_query = Q(dict(match_phrase=dict(org_name=org_name))) + report_id_query = Q(dict(match_phrase=dict(report_id=report_id))) + domain_query = Q(dict(match_phrase={"published_policy.domain": domain})) + begin_date_query = Q(dict(match=dict(date_begin=begin_date))) + end_date_query = Q(dict(match=dict(date_end=end_date))) + + if index_suffix is not None: + search = Search(index="dmarc_aggregate_{0}*".format(index_suffix)) + else: + search = Search(index="dmarc_aggregate*") + query = org_name_query & report_id_query & domain_query + query = query & begin_date_query & end_date_query + search.query = query + + try: + existing = search.execute() + except Exception as error_: + raise OpenSearchError("OpenSearch's search for existing report \ + error: {}".format(error_.__str__())) + + if len(existing) > 0: + raise AlreadySaved("An aggregate report ID {0} from {1} about {2} " + "with a date range of {3} UTC to {4} UTC already " + "exists in " + "OpenSearch".format(report_id, + org_name, + domain, + begin_date_human, + end_date_human)) + published_policy = _PublishedPolicy( + domain=aggregate_report["policy_published"]["domain"], + adkim=aggregate_report["policy_published"]["adkim"], + aspf=aggregate_report["policy_published"]["aspf"], + p=aggregate_report["policy_published"]["p"], + sp=aggregate_report["policy_published"]["sp"], + pct=aggregate_report["policy_published"]["pct"], + fo=aggregate_report["policy_published"]["fo"] + ) + + for record in aggregate_report["records"]: + agg_doc = _AggregateReportDoc( + xml_schema=aggregate_report["xml_schema"], + org_name=metadata["org_name"], + org_email=metadata["org_email"], + org_extra_contact_info=metadata["org_extra_contact_info"], + report_id=metadata["report_id"], + date_range=date_range, + date_begin=aggregate_report["begin_date"], + date_end=aggregate_report["end_date"], + errors=metadata["errors"], + published_policy=published_policy, + source_ip_address=record["source"]["ip_address"], + source_country=record["source"]["country"], + source_reverse_dns=record["source"]["reverse_dns"], + source_base_domain=record["source"]["base_domain"], + message_count=record["count"], + disposition=record["policy_evaluated"]["disposition"], + dkim_aligned=record["policy_evaluated"]["dkim"] is not None and + record["policy_evaluated"]["dkim"].lower() == "pass", + spf_aligned=record["policy_evaluated"]["spf"] is not None and + record["policy_evaluated"]["spf"].lower() == "pass", + header_from=record["identifiers"]["header_from"], + envelope_from=record["identifiers"]["envelope_from"], + envelope_to=record["identifiers"]["envelope_to"] + ) + + for override in record["policy_evaluated"]["policy_override_reasons"]: + agg_doc.add_policy_override(type_=override["type"], + comment=override["comment"]) + + for dkim_result in record["auth_results"]["dkim"]: + agg_doc.add_dkim_result(domain=dkim_result["domain"], + selector=dkim_result["selector"], + result=dkim_result["result"]) + + for spf_result in record["auth_results"]["spf"]: + agg_doc.add_spf_result(domain=spf_result["domain"], + scope=spf_result["scope"], + result=spf_result["result"]) + + index = "dmarc_aggregate" + if index_suffix: + index = "{0}_{1}".format(index, index_suffix) + index = "{0}-{1}".format(index, index_date) + index_settings = dict(number_of_shards=number_of_shards, + number_of_replicas=number_of_replicas) + create_indexes([index], index_settings) + agg_doc.meta.index = index + + try: + agg_doc.save() + except Exception as e: + raise OpenSearchError( + "OpenSearch error: {0}".format(e.__str__()))
    + + +
    [docs]def save_forensic_report_to_opensearch(forensic_report, + index_suffix=None, + monthly_indexes=False, + number_of_shards=1, + number_of_replicas=0): + """ + Saves a parsed DMARC forensic report to OpenSearch + + Args: + forensic_report (OrderedDict): A parsed forensic report + index_suffix (str): The suffix of the name of the index to save to + monthly_indexes (bool): Use monthly indexes instead of daily + indexes + number_of_shards (int): The number of shards to use in the index + number_of_replicas (int): The number of replicas to use in the + index + + Raises: + AlreadySaved + + """ + logger.info("Saving forensic report to OpenSearch") + forensic_report = forensic_report.copy() + sample_date = None + if forensic_report["parsed_sample"]["date"] is not None: + sample_date = forensic_report["parsed_sample"]["date"] + sample_date = human_timestamp_to_datetime(sample_date) + original_headers = forensic_report["parsed_sample"]["headers"] + headers = OrderedDict() + for original_header in original_headers: + headers[original_header.lower()] = original_headers[original_header] + + arrival_date_human = forensic_report["arrival_date_utc"] + arrival_date = human_timestamp_to_datetime(arrival_date_human) + + if index_suffix is not None: + search = Search(index="dmarc_forensic_{0}*".format(index_suffix)) + else: + search = Search(index="dmarc_forensic*") + arrival_query = {"match": {"arrival_date": arrival_date}} + q = Q(arrival_query) + + from_ = None + to_ = None + subject = None + if "from" in headers: + from_ = headers["from"] + from_query = {"match_phrase": {"sample.headers.from": from_}} + q = q & Q(from_query) + if "to" in headers: + to_ = headers["to"] + to_query = {"match_phrase": {"sample.headers.to": to_}} + q = q & Q(to_query) + if "subject" in headers: + subject = headers["subject"] + subject_query = {"match_phrase": {"sample.headers.subject": subject}} + q = q & Q(subject_query) + + search.query = q + existing = search.execute() + + if len(existing) > 0: + raise AlreadySaved("A forensic sample to {0} from {1} " + "with a subject of {2} and arrival date of {3} " + "already exists in " + "OpenSearch".format( + to_, from_, subject, arrival_date_human + )) + + parsed_sample = forensic_report["parsed_sample"] + sample = _ForensicSampleDoc( + raw=forensic_report["sample"], + headers=headers, + headers_only=forensic_report["sample_headers_only"], + date=sample_date, + subject=forensic_report["parsed_sample"]["subject"], + filename_safe_subject=parsed_sample["filename_safe_subject"], + body=forensic_report["parsed_sample"]["body"] + ) + + for address in forensic_report["parsed_sample"]["to"]: + sample.add_to(display_name=address["display_name"], + address=address["address"]) + for address in forensic_report["parsed_sample"]["reply_to"]: + sample.add_reply_to(display_name=address["display_name"], + address=address["address"]) + for address in forensic_report["parsed_sample"]["cc"]: + sample.add_cc(display_name=address["display_name"], + address=address["address"]) + for address in forensic_report["parsed_sample"]["bcc"]: + sample.add_bcc(display_name=address["display_name"], + address=address["address"]) + for attachment in forensic_report["parsed_sample"]["attachments"]: + sample.add_attachment(filename=attachment["filename"], + content_type=attachment["mail_content_type"], + sha256=attachment["sha256"]) + try: + forensic_doc = _ForensicReportDoc( + feedback_type=forensic_report["feedback_type"], + user_agent=forensic_report["user_agent"], + version=forensic_report["version"], + original_mail_from=forensic_report["original_mail_from"], + arrival_date=arrival_date, + domain=forensic_report["reported_domain"], + original_envelope_id=forensic_report["original_envelope_id"], + authentication_results=forensic_report["authentication_results"], + delivery_results=forensic_report["delivery_result"], + source_ip_address=forensic_report["source"]["ip_address"], + source_country=forensic_report["source"]["country"], + source_reverse_dns=forensic_report["source"]["reverse_dns"], + source_base_domain=forensic_report["source"]["base_domain"], + authentication_mechanisms=forensic_report[ + "authentication_mechanisms"], + auth_failure=forensic_report["auth_failure"], + dkim_domain=forensic_report["dkim_domain"], + original_rcpt_to=forensic_report["original_rcpt_to"], + sample=sample + ) + + index = "dmarc_forensic" + if index_suffix: + index = "{0}_{1}".format(index, index_suffix) + if monthly_indexes: + index_date = arrival_date.strftime("%Y-%m") + else: + index_date = arrival_date.strftime("%Y-%m-%d") + index = "{0}-{1}".format(index, index_date) + index_settings = dict(number_of_shards=number_of_shards, + number_of_replicas=number_of_replicas) + create_indexes([index], index_settings) + forensic_doc.meta.index = index + try: + forensic_doc.save() + except Exception as e: + raise OpenSearchError( + "OpenSearch error: {0}".format(e.__str__())) + except KeyError as e: + raise InvalidForensicReport( + "Forensic report missing required field: {0}".format(e.__str__()))
    + + +
    [docs]def save_smtp_tls_report_to_opensearch(report, + index_suffix=None, + monthly_indexes=False, + number_of_shards=1, + number_of_replicas=0): + """ + Saves a parsed SMTP TLS report to OpenSearch + + Args: + report (OrderedDict): A parsed SMTP TLS report + index_suffix (str): The suffix of the name of the index to save to + monthly_indexes (bool): Use monthly indexes instead of daily indexes + number_of_shards (int): The number of shards to use in the index + number_of_replicas (int): The number of replicas to use in the index + + Raises: + AlreadySaved + """ + logger.info("Saving aggregate report to OpenSearch") + org_name = report["org_name"] + report_id = report["report_id"] + begin_date = human_timestamp_to_datetime(report["begin_date"], + to_utc=True) + end_date = human_timestamp_to_datetime(report["end_date"], + to_utc=True) + begin_date_human = begin_date.strftime("%Y-%m-%d %H:%M:%SZ") + end_date_human = end_date.strftime("%Y-%m-%d %H:%M:%SZ") + if monthly_indexes: + index_date = begin_date.strftime("%Y-%m") + else: + index_date = begin_date.strftime("%Y-%m-%d") + report["begin_date"] = begin_date + report["end_date"] = end_date + + org_name_query = Q(dict(match_phrase=dict(org_name=org_name))) + report_id_query = Q(dict(match_phrase=dict(report_id=report_id))) + begin_date_query = Q(dict(match=dict(date_begin=begin_date))) + end_date_query = Q(dict(match=dict(date_end=end_date))) + + if index_suffix is not None: + search = Search(index="smtp_tls_{0}*".format(index_suffix)) + else: + search = Search(index="smtp_tls") + query = org_name_query & report_id_query + query = query & begin_date_query & end_date_query + search.query = query + + try: + existing = search.execute() + except Exception as error_: + raise OpenSearchError("OpenSearch's search for existing report \ + error: {}".format(error_.__str__())) + + if len(existing) > 0: + raise AlreadySaved(f"An SMTP TLS report ID {report_id} from " + f" {org_name} with a date range of " + f"{begin_date_human} UTC to " + f"{end_date_human} UTC already " + "exists in OpenSearch") + + index = "smtp_tls" + if index_suffix: + index = "{0}_{1}".format(index, index_suffix) + index = "{0}-{1}".format(index, index_date) + index_settings = dict(number_of_shards=number_of_shards, + number_of_replicas=number_of_replicas) + + smtp_tls_doc = _SMTPTLSFailureReportDoc( + organization_name=report["organization_name"], + date_range=[report["date_begin"], report["date_end"]], + date_begin=report["date_begin"], + date_end=report["date_end"], + contact_info=report["contact_info"], + report_id=report["report_id"] + ) + + for policy in report['policies']: + policy_strings = None + mx_host_patterns = None + if "policy_strings" in policy: + policy_strings = policy["policy_strings"] + if "mx_host_patterns" in policy: + mx_host_patterns = policy["mx_host_patterns"] + policy_doc = _SMTPTLSPolicyDoc( + policy_domain=policy["policy_domain"], + policy_type=policy["policy_type"], + policy_string=policy_strings, + mx_host_patterns=mx_host_patterns + ) + if "failure_details" in policy: + failure_details = policy["failure_details"] + receiving_mx_hostname = None + additional_information_uri = None + failure_reason_code = None + if "receiving_mx_hostname" in failure_details: + receiving_mx_hostname = failure_details[ + "receiving_mx_hostname"] + if "additional_information_uri" in failure_details: + additional_information_uri = failure_details[ + "additional_information_uri"] + if "failure_reason_code" in failure_details: + failure_reason_code = failure_details["failure_reason_code"] + policy_doc.add_failure_details( + result_type=failure_details["result_type"], + ip_address=failure_details["ip_address"], + receiving_ip=failure_details["receiving_ip"], + receiving_mx_helo=failure_details["receiving_mx_helo"], + failed_session_count=failure_details["failed_session_count"], + receiving_mx_hostname=receiving_mx_hostname, + additional_information_uri=additional_information_uri, + failure_reason_code=failure_reason_code + ) + smtp_tls_doc.policies.append(policy_doc) + + create_indexes([index], index_settings) + smtp_tls_doc.meta.index = index + + try: + smtp_tls_doc.save() + except Exception as e: + raise OpenSearchError( + "OpenSearch error: {0}".format(e.__str__()))
    +
    + +
    +
    +
    + +
    + +
    +

    © Copyright 2018 - 2023, Sean Whalen and contributors.

    +
    + + Built with Sphinx using a + theme + provided by Read the Docs. + + +
    +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/_modules/parsedmarc/splunk.html b/_modules/parsedmarc/splunk.html index 5956e43b..c18e9803 100644 --- a/_modules/parsedmarc/splunk.html +++ b/_modules/parsedmarc/splunk.html @@ -3,7 +3,7 @@ - parsedmarc.splunk — parsedmarc 8.7.0 documentation + parsedmarc.splunk — parsedmarc 8.8.0 documentation @@ -35,7 +35,7 @@ parsedmarc
    - 8.7.0 + 8.8.0
    @@ -51,6 +51,7 @@
  • Using parsedmarc
  • Sample outputs
  • Elasticsearch and Kibana
  • +
  • OpenSearch and Grafana
  • Using the Kibana dashboards
  • Splunk
  • Accessing an inbox using OWA/EWS
  • diff --git a/_modules/parsedmarc/utils.html b/_modules/parsedmarc/utils.html index cc21b276..275b04c7 100644 --- a/_modules/parsedmarc/utils.html +++ b/_modules/parsedmarc/utils.html @@ -3,7 +3,7 @@ - parsedmarc.utils — parsedmarc 8.7.0 documentation + parsedmarc.utils — parsedmarc 8.8.0 documentation @@ -35,7 +35,7 @@ parsedmarc
    - 8.7.0 + 8.8.0
    @@ -51,6 +51,7 @@
  • Using parsedmarc
  • Sample outputs
  • Elasticsearch and Kibana
  • +
  • OpenSearch and Grafana
  • Using the Kibana dashboards
  • Splunk
  • Accessing an inbox using OWA/EWS
  • diff --git a/_sources/api.md.txt b/_sources/api.md.txt index f631b5f8..45629834 100644 --- a/_sources/api.md.txt +++ b/_sources/api.md.txt @@ -14,6 +14,14 @@ :members: ``` +## parsedmarc.opensearch + +```{eval-rst} +.. automodule:: parsedmarc.opensearch + :members: +``` + + ## parsedmarc.splunk ```{eval-rst} diff --git a/_sources/index.md.txt b/_sources/index.md.txt index dc4dbfbc..aee0802a 100644 --- a/_sources/index.md.txt +++ b/_sources/index.md.txt @@ -26,7 +26,7 @@ Thanks to all [contributors]! ``` `parsedmarc` is a Python module and CLI utility for parsing DMARC reports. -When used with Elasticsearch and Kibana (or Splunk), it works as a self-hosted +When used with Elasticsearch and Kibana (or Splunk), or with OpenSearch and Grafana, it works as a self-hosted open source alternative to commercial DMARC report processing services such as Agari Brand Protection, Dmarcian, OnDMARC, ProofPoint Email Fraud Defense, and Valimail. @@ -40,7 +40,7 @@ and Valimail. - Consistent data structures - Simple JSON and/or CSV output - Optionally email the results -- Optionally send the results to Elasticsearch and/or Splunk, for use with +- Optionally send the results to Elasticsearch/OpenSearch and/or Splunk, for use with premade dashboards - Optionally send reports to Apache Kafka @@ -52,6 +52,7 @@ installation usage output elasticsearch +opensearch kibana splunk davmail diff --git a/_sources/opensearch.md.txt b/_sources/opensearch.md.txt new file mode 100644 index 00000000..627a25bb --- /dev/null +++ b/_sources/opensearch.md.txt @@ -0,0 +1,14 @@ +# OpenSearch and Grafana + +To set up visual dashboards of DMARC data, install OpenSearch and Grafana. + +## Installation + +OpenSearch: https://opensearch.org/docs/latest/install-and-configure/install-opensearch/index/ +Grafana: https://grafana.com/docs/grafana/latest/setup-grafana/installation/ + +## Records retention + +Starting in version 5.0.0, `parsedmarc` stores data in a separate +index for each day to make it easy to comply with records +retention regulations such as GDPR. diff --git a/_sources/usage.md.txt b/_sources/usage.md.txt index cc0e0352..98f3aafc 100644 --- a/_sources/usage.md.txt +++ b/_sources/usage.md.txt @@ -82,6 +82,10 @@ delete = False hosts = 127.0.0.1:9200 ssl = False +[opensearch] +hosts = https://admin:admin@127.0.0.1:9200 +ssl = True + [splunk_hec] url = https://splunkhec.example.com token = HECTokenGoesHere @@ -238,6 +242,28 @@ The full set of configuration options are: creating the index (Default: `1`) - `number_of_replicas` - int: The number of replicas to use when creating the index (Default: `0`) +- `opensearch` + - `hosts` - str: A comma separated list of hostnames and ports + or URLs (e.g. `127.0.0.1:9200` or + `https://user:secret@localhost`) + + :::{note} + Special characters in the username or password must be + [URL encoded]. + ::: + - `user` - str: Basic auth username + - `password` - str: Basic auth password + - `apiKey` - str: API key + - `ssl` - bool: Use an encrypted SSL/TLS connection + (Default: `True`) + - `timeout` - float: Timeout in seconds (Default: 60) + - `cert_path` - str: Path to a trusted certificates + - `index_suffix` - str: A suffix to apply to the index names + - `monthly_indexes` - bool: Use monthly indexes instead of daily indexes + - `number_of_shards` - int: The number of shards to use when + creating the index (Default: `1`) + - `number_of_replicas` - int: The number of replicas to use when + creating the index (Default: `0`) - `splunk_hec` - `url` - str: The URL of the Splunk HTTP Events Collector (HEC) - `token` - str: The HEC token diff --git a/_static/documentation_options.js b/_static/documentation_options.js index fc208ff3..a3cd8725 100644 --- a/_static/documentation_options.js +++ b/_static/documentation_options.js @@ -1,6 +1,6 @@ var DOCUMENTATION_OPTIONS = { URL_ROOT: document.getElementById("documentation_options").getAttribute('data-url_root'), - VERSION: '8.7.0', + VERSION: '8.8.0', LANGUAGE: 'en', COLLAPSE_INDEX: false, BUILDER: 'html', diff --git a/api.html b/api.html index c33b3963..c81b9045 100644 --- a/api.html +++ b/api.html @@ -4,7 +4,7 @@ - API reference — parsedmarc 8.7.0 documentation + API reference — parsedmarc 8.8.0 documentation @@ -37,7 +37,7 @@ parsedmarc
    - 8.7.0 + 8.8.0
    @@ -53,6 +53,7 @@
  • Using parsedmarc
  • Sample outputs
  • Elasticsearch and Kibana
  • +
  • OpenSearch and Grafana
  • Using the Kibana dashboards
  • Splunk
  • Accessing an inbox using OWA/EWS
  • @@ -97,6 +98,17 @@
  • set_hosts()
  • +
  • parsedmarc.opensearch +
  • parsedmarc.splunk
    • HECClient
      • HECClient.save_aggregate_reports_to_splunk()
      • @@ -657,7 +669,7 @@

        API reference
        parsedmarc.elastic.save_aggregate_report_to_elasticsearch(aggregate_report, index_suffix=None, monthly_indexes=False, number_of_shards=1, number_of_replicas=0)[source]
        -

        Saves a parsed DMARC aggregate report to ElasticSearch

        +

        Saves a parsed DMARC aggregate report to Elasticsearch

        Parameters
          @@ -677,7 +689,7 @@

          API reference
          parsedmarc.elastic.save_forensic_report_to_elasticsearch(forensic_report, index_suffix=None, monthly_indexes=False, number_of_shards=1, number_of_replicas=0)[source]
          -

          Saves a parsed DMARC forensic report to ElasticSearch

          +

          Saves a parsed DMARC forensic report to Elasticsearch

          Parameters
            @@ -699,7 +711,7 @@

            API reference
            parsedmarc.elastic.save_smtp_tls_report_to_elasticsearch(report, index_suffix=None, monthly_indexes=False, number_of_shards=1, number_of_replicas=0)[source]
            -

            Saves a parsed SMTP TLS report to elasticSearch

            +

            Saves a parsed SMTP TLS report to Elasticsearch

            Parameters
              @@ -735,6 +747,130 @@

              API reference +

              parsedmarc.opensearch

              +
              +
              +exception parsedmarc.opensearch.AlreadySaved[source]
              +

              Raised when a report to be saved matches an existing report

              +
              + +
              +
              +exception parsedmarc.opensearch.OpenSearchError[source]
              +

              Raised when an OpenSearch error occurs

              +
              + +
              +
              +parsedmarc.opensearch.create_indexes(names, settings=None)[source]
              +

              Create OpenSearch indexes

              +
              +
              Parameters
              +
                +
              • names (list) – A list of index names

              • +
              • settings (dict) – Index settings

              • +
              +
              +
              +
              + +
              +
              +parsedmarc.opensearch.migrate_indexes(aggregate_indexes=None, forensic_indexes=None)[source]
              +

              Updates index mappings

              +
              +
              Parameters
              +
                +
              • aggregate_indexes (list) – A list of aggregate index names

              • +
              • forensic_indexes (list) – A list of forensic index names

              • +
              +
              +
              +
              + +
              +
              +parsedmarc.opensearch.save_aggregate_report_to_opensearch(aggregate_report, index_suffix=None, monthly_indexes=False, number_of_shards=1, number_of_replicas=0)[source]
              +

              Saves a parsed DMARC aggregate report to OpenSearch

              +
              +
              Parameters
              +
                +
              • aggregate_report (OrderedDict) – A parsed forensic report

              • +
              • index_suffix (str) – The suffix of the name of the index to save to

              • +
              • monthly_indexes (bool) – Use monthly indexes instead of daily indexes

              • +
              • number_of_shards (int) – The number of shards to use in the index

              • +
              • number_of_replicas (int) – The number of replicas to use in the index

              • +
              +
              +
              Raises
              +

              AlreadySaved

              +
              +
              +
              + +
              +
              +parsedmarc.opensearch.save_forensic_report_to_opensearch(forensic_report, index_suffix=None, monthly_indexes=False, number_of_shards=1, number_of_replicas=0)[source]
              +

              Saves a parsed DMARC forensic report to OpenSearch

              +
              +
              Parameters
              +
                +
              • forensic_report (OrderedDict) – A parsed forensic report

              • +
              • index_suffix (str) – The suffix of the name of the index to save to

              • +
              • monthly_indexes (bool) – Use monthly indexes instead of daily +indexes

              • +
              • number_of_shards (int) – The number of shards to use in the index

              • +
              • number_of_replicas (int) – The number of replicas to use in the +index

              • +
              +
              +
              Raises
              +

              AlreadySaved

              +
              +
              +
              + +
              +
              +parsedmarc.opensearch.save_smtp_tls_report_to_opensearch(report, index_suffix=None, monthly_indexes=False, number_of_shards=1, number_of_replicas=0)[source]
              +

              Saves a parsed SMTP TLS report to OpenSearch

              +
              +
              Parameters
              +
                +
              • report (OrderedDict) – A parsed SMTP TLS report

              • +
              • index_suffix (str) – The suffix of the name of the index to save to

              • +
              • monthly_indexes (bool) – Use monthly indexes instead of daily indexes

              • +
              • number_of_shards (int) – The number of shards to use in the index

              • +
              • number_of_replicas (int) – The number of replicas to use in the index

              • +
              +
              +
              Raises
              +

              AlreadySaved

              +
              +
              +
              + +
              +
              +parsedmarc.opensearch.set_hosts(hosts, use_ssl=False, ssl_cert_path=None, username=None, password=None, apiKey=None, timeout=60.0)[source]
              +

              Sets the OpenSearch hosts to use

              +
              +
              Parameters
              +
                +
              • hosts (str|list) – A hostname or URL, or list of hostnames or URLs

              • +
              • use_ssl (bool) – Use an HTTPS connection to the server

              • +
              • ssl_cert_path (str) – Path to the certificate chain

              • +
              • username (str) – The username to use for authentication

              • +
              • password (str) – The password to use for authentication

              • +
              • apiKey (str) – The Base64 encoded API key to use for authentication

              • +
              • timeout (float) – Timeout in seconds

              • +
              +
              +
              +
              +

              parsedmarc.splunk

              diff --git a/contributing.html b/contributing.html index 9d1040c9..03f92624 100644 --- a/contributing.html +++ b/contributing.html @@ -4,7 +4,7 @@ - Contributing to parsedmarc — parsedmarc 8.7.0 documentation + Contributing to parsedmarc — parsedmarc 8.8.0 documentation @@ -38,7 +38,7 @@ parsedmarc
              - 8.7.0 + 8.8.0
              @@ -54,6 +54,7 @@
            • Using parsedmarc
            • Sample outputs
            • Elasticsearch and Kibana
            • +
            • OpenSearch and Grafana
            • Using the Kibana dashboards
            • Splunk
            • Accessing an inbox using OWA/EWS
            • diff --git a/davmail.html b/davmail.html index b53b64c1..a5a40be7 100644 --- a/davmail.html +++ b/davmail.html @@ -4,7 +4,7 @@ - Accessing an inbox using OWA/EWS — parsedmarc 8.7.0 documentation + Accessing an inbox using OWA/EWS — parsedmarc 8.8.0 documentation @@ -38,7 +38,7 @@ parsedmarc
              - 8.7.0 + 8.8.0
              @@ -54,6 +54,7 @@
            • Using parsedmarc
            • Sample outputs
            • Elasticsearch and Kibana
            • +
            • OpenSearch and Grafana
            • Using the Kibana dashboards
            • Splunk
            • Accessing an inbox using OWA/EWS
                diff --git a/dmarc.html b/dmarc.html index d306c6cd..0d4a7814 100644 --- a/dmarc.html +++ b/dmarc.html @@ -4,7 +4,7 @@ - Understanding DMARC — parsedmarc 8.7.0 documentation + Understanding DMARC — parsedmarc 8.8.0 documentation @@ -38,7 +38,7 @@ parsedmarc
                - 8.7.0 + 8.8.0
                @@ -54,6 +54,7 @@
              • Using parsedmarc
              • Sample outputs
              • Elasticsearch and Kibana
              • +
              • OpenSearch and Grafana
              • Using the Kibana dashboards
              • Splunk
              • Accessing an inbox using OWA/EWS
              • diff --git a/elasticsearch.html b/elasticsearch.html index 1ab050a1..7bcd2223 100644 --- a/elasticsearch.html +++ b/elasticsearch.html @@ -4,7 +4,7 @@ - Elasticsearch and Kibana — parsedmarc 8.7.0 documentation + Elasticsearch and Kibana — parsedmarc 8.8.0 documentation @@ -22,7 +22,7 @@ - + @@ -38,7 +38,7 @@ parsedmarc
                - 8.7.0 + 8.8.0
                @@ -59,6 +59,7 @@
              • Records retention
            • +
            • OpenSearch and Grafana
            • Using the Kibana dashboards
            • Splunk
            • Accessing an inbox using OWA/EWS
            • @@ -278,7 +279,7 @@

              Records retention - +


              diff --git a/genindex.html b/genindex.html index d92e6085..0f808cb3 100644 --- a/genindex.html +++ b/genindex.html @@ -3,7 +3,7 @@ - Index — parsedmarc 8.7.0 documentation + Index — parsedmarc 8.8.0 documentation @@ -35,7 +35,7 @@ parsedmarc
              - 8.7.0 + 8.8.0
              @@ -51,6 +51,7 @@
            • Using parsedmarc
            • Sample outputs
            • Elasticsearch and Kibana
            • +
            • OpenSearch and Grafana
            • Using the Kibana dashboards
            • Splunk
            • Accessing an inbox using OWA/EWS
            • @@ -94,6 +95,7 @@

              Index

              | H | I | M + | O | P | Q | S @@ -104,7 +106,7 @@

              Index

              A

              @@ -117,7 +119,11 @@

              C

            @@ -211,7 +217,11 @@

            M

            +

            O

            + + +
            +

            P

            - +
            • parsed_smtp_tls_reports_to_csv_rows() (in module parsedmarc)
            • @@ -271,6 +291,13 @@

              P

            • +
            • + parsedmarc.opensearch + +
            • @@ -304,10 +331,14 @@

              S

              diff --git a/index.html b/index.html index b974fe27..9c502060 100644 --- a/index.html +++ b/index.html @@ -4,7 +4,7 @@ - parsedmarc documentation - Open source DMARC report analyzer and visualizer — parsedmarc 8.7.0 documentation + parsedmarc documentation - Open source DMARC report analyzer and visualizer — parsedmarc 8.8.0 documentation @@ -37,7 +37,7 @@ parsedmarc
              - 8.7.0 + 8.8.0
              @@ -53,6 +53,7 @@
            • Using parsedmarc
            • Sample outputs
            • Elasticsearch and Kibana
            • +
            • OpenSearch and Grafana
            • Using the Kibana dashboards
            • Splunk
            • Accessing an inbox using OWA/EWS
            • @@ -101,7 +102,7 @@

              parsedmarc documentation - Open source DMARC report analyzer and visualizer<

              A screenshot of DMARC summary charts in Kibana

              parsedmarc is a Python module and CLI utility for parsing DMARC reports. -When used with Elasticsearch and Kibana (or Splunk), it works as a self-hosted +When used with Elasticsearch and Kibana (or Splunk), or with OpenSearch and Grafana, it works as a self-hosted open source alternative to commercial DMARC report processing services such as Agari Brand Protection, Dmarcian, OnDMARC, ProofPoint Email Fraud Defense, and Valimail.

              @@ -115,7 +116,7 @@

              FeaturesRecords retention +
            • OpenSearch and Grafana +
            • Using the Kibana dashboards
            • + + +
                  parsedmarc.elastic
                  + parsedmarc.opensearch +
                  diff --git a/search.html b/search.html index 627cf263..429b2afd 100644 --- a/search.html +++ b/search.html @@ -3,7 +3,7 @@ - Search — parsedmarc 8.7.0 documentation + Search — parsedmarc 8.8.0 documentation @@ -38,7 +38,7 @@ parsedmarc
              - 8.7.0 + 8.8.0
              @@ -54,6 +54,7 @@
            • Using parsedmarc
            • Sample outputs
            • Elasticsearch and Kibana
            • +
            • OpenSearch and Grafana
            • Using the Kibana dashboards
            • Splunk
            • Accessing an inbox using OWA/EWS
            • diff --git a/searchindex.js b/searchindex.js index 8e285989..72f7aec9 100644 --- a/searchindex.js +++ b/searchindex.js @@ -1 +1 @@ -Search.setIndex({"docnames": ["api", "contributing", "davmail", "dmarc", "elasticsearch", "index", "installation", "kibana", "mailing-lists", "output", "splunk", "usage"], "filenames": ["api.md", "contributing.md", "davmail.md", "dmarc.md", "elasticsearch.md", "index.md", "installation.md", "kibana.md", "mailing-lists.md", "output.md", "splunk.md", "usage.md"], "titles": ["API reference", "Contributing to parsedmarc", "Accessing an inbox using OWA/EWS", "Understanding DMARC", "Elasticsearch and Kibana", "parsedmarc documentation - Open source DMARC report analyzer and visualizer", "Installation", "Using the Kibana dashboards", "What about mailing lists?", "Sample outputs", "Splunk", "Using parsedmarc"], "terms": {"A": [0, 3, 11], "python": [0, 5, 6], "packag": [0, 4], "pars": [0, 3, 5, 6, 9, 11], "dmarc": [0, 4, 6, 8, 9, 10, 11], "report": [0, 4, 7, 10, 11], "except": [0, 11], "invalidaggregatereport": 0, "sourc": [0, 3, 4, 6, 7, 9], "rais": 0, "when": [0, 3, 5, 7, 8, 11], "an": [0, 3, 5, 7, 8, 9, 11], "invalid": 0, "aggreg": [0, 5, 7, 10, 11], "i": [0, 2, 3, 4, 5, 6, 7, 8, 9, 11], "encount": 0, "invaliddmarcreport": 0, "invalidforensicreport": 0, "forens": [0, 5, 10, 11], "invalidsmtptlsreport": 0, "smtp": [0, 3, 7, 11], "tl": [0, 11], "parsererror": 0, "whenev": [0, 2, 11], "parser": 0, "fail": [0, 3, 7, 8, 9, 11], "some": [0, 2, 3, 4, 7, 8], "reason": [0, 2, 4, 11], "email_result": 0, "result": [0, 5, 7, 9, 11], "host": [0, 2, 3, 4, 5, 8, 11], "mail_from": 0, "mail_to": 0, "mail_cc": 0, "none": [0, 3, 9, 11], "mail_bcc": 0, "port": [0, 2, 11], "0": [0, 2, 3, 4, 5, 6, 8, 9, 10, 11], "require_encrypt": 0, "fals": [0, 2, 6, 9, 11], "verifi": 0, "true": [0, 2, 4, 9, 11], "usernam": [0, 11], "password": [0, 4, 6, 11], "subject": [0, 3, 8, 9, 11], "attachment_filenam": 0, "messag": [0, 2, 3, 4, 6, 7, 8, 9, 11], "email": [0, 3, 5, 6, 7, 8, 9, 10, 11], "zip": [0, 2, 5, 11], "file": [0, 2, 5, 6, 10], "paramet": 0, "ordereddict": 0, "mail": [0, 5, 6, 9, 11], "server": [0, 2, 3, 4, 6, 7, 9, 11], "hostnam": [0, 11], "ip": [0, 3, 4, 6, 7, 11], "address": [0, 2, 3, 4, 7, 8, 9, 11], "The": [0, 3, 6, 7, 10, 11], "valu": [0, 3, 4, 7, 8, 11], "from": [0, 2, 3, 4, 5, 6, 7, 8, 9, 11], "header": [0, 3, 7, 8, 9, 11], "list": [0, 2, 4, 5, 7, 11], "cc": [0, 9], "bcc": [0, 9], "int": [0, 11], "us": [0, 3, 4, 5, 8, 9], "bool": [0, 11], "requir": [0, 2, 3, 4, 6, 8, 11], "secur": [0, 4, 11], "connect": [0, 2, 4, 11], "start": [0, 2, 4, 6, 7, 10, 11], "ssl": [0, 2, 4, 11], "certif": [0, 4, 11], "str": [0, 11], "option": [0, 2, 3, 4, 5, 8, 10, 11], "overrid": 0, "default": [0, 2, 4, 6, 7, 11], "attach": [0, 3, 8, 9, 11], "filenam": [0, 11], "plain": 0, "text": [0, 9], "bodi": [0, 3, 8, 9, 11], "extract_report": 0, "input_": 0, "extract": [0, 2], "gzip": [0, 5], "given": [0, 11], "path": [0, 4, 11], "like": [0, 3, 6, 8], "object": [0, 4], "byte": 0, "input": 0, "return": 0, "type": [0, 9, 11], "get_dmarc_reports_from_mailbox": 0, "mailboxconnect": 0, "reports_fold": [0, 11], "inbox": [0, 3, 5, 8, 11], "archive_fold": [0, 11], "archiv": [0, 11], "delet": [0, 2, 4, 11], "test": [0, 9, 11], "ip_db_path": [0, 6, 11], "offlin": [0, 11], "nameserv": [0, 11], "dns_timeout": [0, 11], "6": [0, 4, 6, 11], "strip_attachment_payload": [0, 11], "batch_siz": [0, 11], "10": [0, 6, 9, 11], "create_fold": 0, "fetch": [0, 11], "mailbox": [0, 7, 11], "folder": [0, 2, 11], "where": [0, 2, 3, 8, 11], "can": [0, 2, 3, 4, 5, 6, 7, 8, 11], "found": [0, 6, 11], "move": [0, 4, 11], "process": [0, 2, 5, 6, 11], "after": [0, 2, 4, 11], "them": [0, 4, 7, 11], "do": [0, 2, 6, 7, 11], "mmdb": [0, 11], "maxmind": [0, 6, 11], "dbip": [0, 11], "queri": [0, 11], "onlin": [0, 2, 11], "geoloc": [0, 11], "dn": [0, 3, 7, 11], "float": [0, 11], "set": [0, 2, 3, 4, 6, 7, 8, 11], "timeout": [0, 2, 11], "remov": [0, 3, 4, 8, 11], "payload": [0, 11], "dict": 0, "previou": [0, 2, 4, 11], "run": [0, 4, 5, 6], "number": [0, 11], "read": [0, 11], "befor": [0, 11], "save": [0, 4, 6, 11], "limit": [0, 2, 11], "whether": 0, "creat": [0, 2, 3, 4, 6, 8, 11], "destin": 0, "watch": [0, 2, 4, 11], "aggregate_report": 0, "forensic_report": 0, "get_dmarc_reports_from_mbox": 0, "2": [0, 4, 9, 11], "parallel": [0, 11], "mbox": [0, 11], "format": [0, 6], "contain": [0, 7, 10, 11], "e": [0, 2, 3, 4, 6, 8, 11], "one": [0, 3, 5, 8, 11], "more": [0, 4, 6, 10, 11], "cloudflar": [0, 11], "": [0, 2, 3, 4, 6, 8, 9, 11], "public": [0, 3, 9, 11], "resolv": [0, 11], "second": [0, 2, 11], "make": [0, 3, 4, 8, 11], "get_report_zip": 0, "output": [0, 5, 11], "parse_aggregate_report_fil": 0, "_input": 0, "keep_al": 0, "callabl": 0, "keep": 0, "aliv": 0, "function": 0, "parse_aggregate_report_xml": 0, "xml": [0, 10], "string": 0, "consist": [0, 5, 9], "parse_forensic_report": 0, "feedback_report": 0, "sampl": [0, 5, 11], "msg_date": 0, "convert": [0, 3, 8], "feedback": 0, "rfc": [0, 3, 8, 9], "822": 0, "date": [0, 3, 8, 9], "parse_report_email": 0, "report_typ": 0, "parse_report_fil": 0, "parse_smtp_tls_report_json": 0, "valid": [0, 7, 9, 11], "parsed_aggregate_reports_to_csv": 0, "flat": 0, "csv": [0, 5, 11], "includ": [0, 3, 6, 7, 8, 11], "data": [0, 4, 5, 7, 10, 11], "parsed_aggregate_reports_to_csv_row": 0, "parsed_forensic_reports_to_csv": 0, "parsed_forensic_reports_to_csv_row": 0, "parsed_smtp_tls_reports_to_csv": 0, "parsed_smtp_tls_reports_to_csv_row": 0, "oor": 0, "singl": 0, "layer": 0, "suitabl": 0, "save_output": 0, "output_directori": 0, "aggregate_json_filenam": [0, 11], "json": [0, 5, 11], "forensic_json_filenam": [0, 11], "smtp_tls_json_filenam": 0, "smtp_tl": 0, "aggregate_csv_filenam": [0, 11], "forensic_csv_filenam": [0, 11], "smtp_tls_csv_filenam": 0, "directori": [0, 11], "watch_inbox": 0, "mailbox_connect": 0, "callback": 0, "check_timeout": [0, 11], "30": [0, 11], "new": [0, 2, 3, 6, 7, 11], "send": [0, 2, 3, 4, 5, 7, 8, 10, 11], "receiv": [0, 9, 11], "imap": [0, 2, 5, 11], "wait": [0, 11], "idl": [0, 2, 11], "respons": [0, 11], "until": [0, 11], "next": [0, 11], "check": [0, 2, 3, 4, 6, 11], "replac": [0, 3, 4, 8], "alreadysav": 0, "match": [0, 4, 10], "exist": [0, 3, 4, 8], "elasticsearcherror": 0, "elasticsearch": [0, 5, 11], "error": [0, 9, 11], "occur": [0, 7], "create_index": 0, "name": [0, 3, 4, 7, 9, 10, 11], "index": [0, 5, 10, 11], "migrate_index": 0, "aggregate_index": 0, "forensic_index": 0, "updat": [0, 4, 6, 11], "map": 0, "save_aggregate_report_to_elasticsearch": 0, "index_suffix": [0, 11], "monthly_index": [0, 11], "number_of_shard": [0, 11], "1": [0, 2, 4, 5, 6, 9, 11], "number_of_replica": [0, 11], "suffix": [0, 11], "monthli": [0, 11], "instead": [0, 3, 6, 8, 11], "daili": [0, 11], "shard": [0, 11], "replica": [0, 11], "save_forensic_report_to_elasticsearch": 0, "save_smtp_tls_report_to_elasticsearch": 0, "set_host": 0, "use_ssl": 0, "ssl_cert_path": 0, "apikei": [0, 11], "60": [0, 11], "url": [0, 2, 11], "http": [0, 1, 2, 3, 4, 6, 8, 9, 10, 11], "chain": 0, "authent": [0, 2, 3, 4, 7, 11], "base64": 0, "encod": [0, 9, 11], "kei": [0, 3, 4, 6, 11], "class": 0, "hecclient": 0, "access_token": 0, "initi": 0, "hec": [0, 10, 11], "access": [0, 4, 5, 6, 11], "token": [0, 4, 11], "give": [0, 4, 11], "up": [0, 2, 4, 6, 7, 11], "save_aggregate_reports_to_splunk": 0, "dictionari": 0, "save_forensic_reports_to_splunk": 0, "save_smtp_tls_reports_to_splunk": 0, "splunkerror": 0, "might": [0, 3, 7, 8], "other": [0, 3, 4, 7, 8], "project": [0, 2, 3, 5, 10], "downloaderror": 0, "download": [0, 2, 4, 6], "emailparsererror": 0, "convert_outlook_msg": 0, "msg_byte": 0, "msgconvert": [0, 6], "perl": [0, 6], "outlook": [0, 2, 6], "m": [0, 6, 9, 11], "standard": [0, 5, 9], "content": [0, 3, 8, 9, 10], "msg": [0, 6], "decode_base64": 0, "decod": 0, "pad": 0, "being": 0, "get_base_domain": 0, "domain": [0, 4, 7, 8, 9], "get": [0, 2, 4, 6, 11], "base": [0, 2, 3, 4, 7, 8, 9], "ar": [0, 2, 3, 4, 6, 7, 8, 9, 11], "publicsuffix": 0, "org": [0, 6, 9], "public_suffix_list": 0, "dat": 0, "subdomain": [0, 3], "get_filename_safe_str": 0, "safe": 0, "get_ip_address_countri": 0, "ip_address": [0, 9], "db_path": 0, "iso": 0, "code": [0, 4, 5], "countri": [0, 6, 7, 9], "associ": 0, "ipv4": 0, "ipv6": 0, "And": 0, "get_ip_address_info": 0, "cach": [0, 11], "revers": [0, 7], "inform": [0, 4, 6, 7, 11], "expiringdict": 0, "storag": [0, 11], "reverse_dn": [0, 9], "get_reverse_dn": 0, "ani": [0, 3, 7, 8, 11], "human_timestamp_to_datetim": 0, "human_timestamp": 0, "to_utc": 0, "human": [0, 7], "readabl": 0, "timestamp": 0, "datetim": 0, "utc": 0, "human_timestamp_to_unix_timestamp": 0, "unix": 0, "yyyi": 0, "mm": 0, "dd": 0, "hh": 0, "ss": 0, "is_mbox": 0, "flag": [0, 2], "is_outlook_msg": 0, "ol": [0, 6], "parse_email": 0, "simplifi": 0, "binari": 0, "query_dn": 0, "record_typ": 0, "about": [0, 5, 6], "record": [0, 5, 6, 9], "answer": [0, 11], "timestamp_to_datetim": 0, "timestamp_to_human": 0, "modul": [0, 5, 11], "pleas": [1, 5, 11], "github": [1, 6, 9, 11], "issu": [1, 5], "tracker": 1, "com": [1, 2, 3, 8, 9, 11], "domainawar": [1, 3, 11], "8": [2, 4, 6, 9, 11], "support": [2, 5, 9, 10], "microsoft": [2, 5, 9, 11], "offic": 2, "365": [2, 4], "via": 2, "graph": [2, 5, 7, 11], "api": [2, 4, 5, 11], "which": [2, 4, 7, 11], "prefer": [2, 6], "over": [2, 5, 7], "organ": [2, 7, 11], "allow": [2, 3, 8, 11], "onli": [2, 3, 6, 7, 8, 11], "exchang": [2, 9, 11], "web": [2, 4], "In": [2, 3, 7, 8, 11], "case": [2, 3, 8], "need": [2, 3, 4, 6, 7, 8, 11], "local": [2, 4, 9, 11], "gatewai": 2, "It": [2, 4, 7, 9, 11], "even": [2, 3, 8, 11], "work": [2, 3, 5, 6, 7, 8], "modern": [2, 3, 8], "auth": [2, 9, 11], "multi": [2, 11], "factor": 2, "To": [2, 4, 6, 7, 9, 11], "thi": [2, 3, 4, 5, 6, 7, 8, 9, 11], "latest": [2, 4, 6], "version": [2, 4, 6, 9, 10, 11], "sourceforg": 2, "net": [2, 9], "unzip": 2, "command": [2, 3, 8, 11], "instal": [2, 5, 11], "java": 2, "sudo": [2, 4, 6, 11], "apt": [2, 4, 6], "jre": 2, "headless": 2, "properti": 2, "see": [2, 3, 4, 5, 7, 11], "document": [2, 11], "basic": [2, 11], "workstat": 2, "mode": [2, 4, 9, 11], "auto": 2, "webdav": 2, "enableew": 2, "office365": 2, "asmx": 2, "listen": [2, 11], "imapport": 2, "1143": 2, "network": [2, 4, 11], "proxi": 2, "enableproxi": 2, "usesystemproxi": 2, "proxyhost": 2, "proxyport": 2, "proxyus": 2, "proxypassword": 2, "exclud": 2, "noproxyfor": 2, "block": [2, 11], "remot": 2, "allowremot": 2, "bind": 2, "socket": 2, "loopback": 2, "bindaddress": 2, "127": [2, 4, 11], "disabl": [2, 11], "specifi": [2, 3], "nosecureimap": 2, "keepal": 2, "charact": [2, 11], "dure": 2, "larg": 2, "enablekeepal": 2, "count": [2, 9], "retriev": 2, "foldersizelimit": 2, "immedi": 2, "store": [2, 4], "imapautoexpung": 2, "enabl": [2, 4, 11], "poll": [2, 11], "delai": [2, 9], "minut": [2, 11], "imapidledelai": 2, "alwai": [2, 4, 11], "repli": [2, 3, 8], "rfc822": 2, "size": [2, 4], "request": [2, 4, 11], "approxim": 2, "perform": [2, 11], "imapalwaysapproxmsgs": 2, "client": [2, 3, 4, 8, 11], "300": 2, "clientsotimeout": 2, "system": [2, 3, 4, 6, 8, 11], "user": [2, 3, 4, 5, 6, 8, 9, 11], "useradd": [2, 6], "r": [2, 6, 9, 11], "bin": [2, 4, 6, 11], "protect": [2, 3, 5, 8, 11], "pry": [2, 11], "ey": [2, 11], "chown": [2, 11], "root": [2, 11], "opt": [2, 6, 11], "chmod": [2, 4, 11], "u": [2, 6, 9, 11], "rw": [2, 11], "g": [2, 3, 4, 8, 11], "o": [2, 4, 11], "nano": [2, 11], "etc": [2, 3, 4, 6, 8, 11], "unit": [2, 11], "descript": [2, 6, 11], "want": [2, 5, 11], "target": [2, 11], "syslog": [2, 11], "execstart": [2, 11], "group": [2, 7, 11], "restart": [2, 3, 4, 8, 11], "restartsec": [2, 11], "5m": [2, 11], "wantedbi": [2, 11], "Then": [2, 3, 4, 6, 8, 11], "systemctl": [2, 4, 11], "daemon": [2, 4, 11], "reload": [2, 4, 11], "you": [2, 3, 4, 5, 6, 7, 8, 11], "must": [2, 3, 8, 11], "also": [2, 3, 7, 8, 11], "abov": [2, 11], "edit": [2, 6, 11], "everi": [2, 6, 11], "time": [2, 4, 6, 7, 11], "upgrad": [2, 5, 6, 11], "statu": [2, 11], "event": [2, 10, 11], "crash": [2, 4, 11], "5": [2, 4], "show": [2, 7, 11], "log": [2, 11], "current": [2, 4, 11], "vew": 2, "well": [2, 11], "newest": [2, 11], "oldest": [2, 11], "journalctl": [2, 11], "becaus": [2, 3, 7, 8, 11], "interact": [2, 4], "add": [2, 3, 4, 6, 7, 8, 11], "follow": [2, 4], "ini": [2, 11], "config": [2, 6, 11], "demystifi": 3, "complet": [3, 4], "If": [3, 4, 6, 7, 8, 11], "look": [3, 7], "out": [3, 4, 7], "sister": 3, "checkdmarc": 3, "against": [3, 8], "spoof": [3, 8], "open": 3, "monitor": [3, 11], "ensur": [3, 6, 8], "dkm": 3, "mechan": 3, "actual": [3, 9], "same": [3, 4, 6, 7, 10], "end": [3, 4], "pass": [3, 7, 9], "long": 3, "relat": 3, "indic": [3, 5], "signatur": [3, 7, 8], "publish": 3, "envelop": 3, "sign": [3, 4, 6], "vendor": 3, "don": 3, "know": 3, "yet": 3, "ask": 3, "thei": [3, 6, 7, 8, 11], "through": 3, "your": [3, 4, 6, 7, 8, 10, 11], "relai": [3, 8], "theirs": 3, "realli": 3, "why": [3, 7], "displai": [3, 7, 10], "worst": 3, "have": [3, 4, 6, 7, 8, 10, 11], "specif": [3, 11], "norepli": [3, 9], "exampl": [3, 4, 6, 8, 9, 11], "separ": [3, 4, 6, 7, 10, 11], "p": [3, 6, 9], "alter": [3, 8], "sp": [3, 9], "top": [3, 7], "level": [3, 4], "tld": 3, "would": [3, 5, 6, 8], "leav": 3, "vulner": 3, "deploi": [3, 8], "find": [3, 7, 8], "most": [3, 4, 7, 8, 11], "modifi": [3, 8, 11], "footer": [3, 8], "part": [3, 4, 7, 8], "therebi": [3, 8], "break": [3, 4, 8], "ideal": [3, 8], "should": [3, 6, 7, 8, 11], "forward": [3, 7, 8], "without": [3, 4, 7, 8], "all": [3, 5, 7, 8, 10, 11], "joe": [3, 8], "nelson": [3, 8], "doe": [3, 8], "fantast": [3, 8], "job": [3, 6, 8], "explain": [3, 8], "exactli": [3, 8], "shouldn": [3, 8], "fulli": [3, 8], "compliant": [3, 8], "rather": [3, 8], "than": [3, 4, 8, 11], "repeat": [3, 8], "hi": [3, 8], "fine": [3, 8], "here": [3, 8, 9, 11], "summari": [3, 5, 8], "retain": [3, 8], "origin": [3, 8, 11], "2369": [3, 8], "unsubscrib": [3, 8], "outgo": [3, 8, 11], "ad": [3, 6, 8, 11], "link": [3, 4, 7, 8], "2919": [3, 8], "id": [3, 8, 9, 11], "webmail": [3, 7, 8], "servic": [3, 4, 5, 7, 8], "gener": [3, 4, 6, 8, 9, 11], "button": [3, 8], "tradit": [3, 8], "disclaim": [3, 8], "addit": [3, 8], "compli": [3, 4, 6, 8], "configur": [3, 4, 5, 6, 7, 8], "action": [3, 8], "prefix": [3, 8], "still": [3, 6, 8, 9, 11], "tell": [3, 6, 7, 8], "came": [3, 8], "wa": [3, 4, 6, 8], "sent": [3, 8, 11], "post": [3, 8], "step": [3, 4, 8], "common": [3, 4, 6, 8], "platform": [3, 8], "below": [3, 8, 11], "navig": [3, 6, 8], "subject_prefix": [3, 8], "from_is_list": [3, 8], "No": [3, 8], "first_strip_reply_to": [3, 8], "reply_goes_to_list": [3, 8], "poster": [3, 8], "include_rfc2369_head": [3, 8], "ye": [3, 8], "include_list_post_head": [3, 8], "include_sender_head": [3, 8], "non": [3, 8, 11], "digest": [3, 8], "msg_header": [3, 8], "msg_footer": [3, 8], "scrub_nondigest": [3, 8], "privaci": [3, 6, 7, 8, 11], "filter": [3, 7, 8, 10], "dmarc_moderation_act": [3, 8], "accept": [3, 4, 8], "dmarc_quarantine_moderation_act": [3, 8], "dmarc_none_moderation_act": [3, 8], "ident": [3, 8, 11], "blank": [3, 8], "html": [3, 4, 8, 9], "plaintext": [3, 8], "rfc2369": [3, 8], "explicit": [3, 8], "first": [3, 6, 8, 11], "strip": [3, 8, 11], "replyto": [3, 8], "goe": [3, 8], "mung": [3, 8], "mitig": [3, 8], "uncondition": [3, 8], "templat": [3, 8], "unfortun": [3, 8], "postoriu": [3, 8], "admin": [3, 8, 11], "ui": [3, 8], "empti": [3, 8], "so": [3, 6, 7, 8, 11], "ll": [3, 8], "line": [3, 8], "touch": [3, 8], "var": [3, 8], "en": [3, 4, 8, 9], "member": [3, 8], "regular": [3, 8], "languag": [3, 8], "core": [3, 8], "16": [3, 8], "2017a": [3, 8], "higher": [3, 8], "rewrit": [3, 8], "enforc": [3, 8], "quarantin": [3, 8], "reject": [3, 8], "polici": [3, 8, 9, 11], "linux": [3, 6, 8], "go": [3, 8], "legal": [3, 8], "administr": [3, 8], "known": [3, 7, 8, 11], "longer": [3, 8], "wrap": [3, 8], "could": [3, 4, 8, 11], "interfer": [3, 8], "search": [3, 8, 11], "mobil": [3, 8], "On": [3, 4, 6, 7, 8], "hand": [3, 8], "caus": [3, 4, 7, 8], "accident": [3, 8], "entir": [3, 7, 8], "intend": [3, 8], "choos": [3, 8], "fit": [3, 8], "commun": [3, 8], "tab": [3, 4, 8], "page": [3, 4, 6, 7, 8], "visual": 4, "dashboard": [4, 5, 10], "later": [4, 6, 11], "debian": [4, 6], "ubuntu": [4, 6], "y": [4, 6], "transport": 4, "wget": 4, "qo": 4, "artifact": 4, "elast": [4, 5], "co": 4, "gpg": 4, "dearmor": 4, "usr": 4, "share": [4, 11], "keyr": 4, "echo": 4, "deb": 4, "x": [4, 9], "stabl": 4, "main": 4, "tee": 4, "d": 4, "For": [4, 11], "cento": [4, 6], "rhel": [4, 6], "rpm": 4, "guid": [4, 5], "previous": [4, 7], "jvm": 4, "heap": 4, "veri": [4, 7, 11], "small": 4, "1g": 4, "under": [4, 6, 7], "heavi": 4, "load": 4, "fix": 4, "increas": [4, 11], "minimum": 4, "maximum": 4, "depend": [4, 5, 11], "resourc": [4, 5, 11], "sure": [4, 6], "ha": [4, 7, 11], "least": [4, 6, 11], "gb": 4, "ram": 4, "assign": 4, "4": [4, 6, 10], "xms4g": 4, "xmx4g": 4, "www": [4, 6, 11], "refer": [4, 5], "import": [4, 7], "As": [4, 7], "7": [4, 6], "activ": [4, 6], "xpack": 4, "vim": 4, "yml": 4, "featur": 4, "enrol": 4, "encrypt": [4, 11], "logstash": 4, "agent": 4, "keystor": 4, "cert": 4, "p12": 4, "mutual": 4, "between": [4, 7], "cluster": [4, 11], "node": 4, "verification_mod": 4, "truststor": 4, "self": [4, 5], "openssl": 4, "req": 4, "x509": 4, "dai": [4, 11], "newkei": 4, "rsa": 4, "4096": 4, "keyout": 4, "crt": 4, "Or": [4, 6], "csr": 4, "ca": 4, "fill": [4, 6], "prompt": 4, "fqdn": 4, "field": 4, "rm": 4, "f": 4, "place": [4, 7, 11], "mv": 4, "660": 4, "server_ip": 4, "publicbaseurl": 4, "connexion": 4, "9200": [4, 11], "5601": 4, "past": [4, 10], "verif": [4, 11], "put": [4, 11], "browser": 4, "setup": [4, 11], "encryptedsavedobject": 4, "encryptionkei": 4, "xxxx": 4, "now": [4, 7], "parsedmarc": [4, 9, 10], "right": [4, 7], "click": [4, 7], "export": 4, "ndjson": 4, "provid": [4, 7], "consol": [4, 11], "stack": 4, "manag": [4, 11], "hamburg": 4, "menu": [4, 7], "overwrit": 4, "restor": 4, "someon": 4, "els": 4, "permiss": [4, 11], "control": 4, "commerci": [4, 5], "pack": 4, "chang": [4, 7, 10, 11], "wai": [4, 7], "releas": [4, 6], "login": 4, "checkbox": 4, "dmarc_aggreg": 4, "dmarc_forens": 4, "conform": 4, "each": [4, 6, 10, 11], "easi": 4, "regul": [4, 6, 11], "gdpr": 4, "effici": 4, "help": 5, "maintain": 5, "develop": 5, "consid": [5, 7], "review": [5, 7], "how": 5, "contribut": 5, "assist": 5, "pin": 5, "particularli": [5, 11], "thank": [5, 9], "contributor": 5, "cli": 5, "util": 5, "kibana": [5, 10], "splunk": [5, 11], "altern": [5, 11], "agari": 5, "brand": [5, 7], "dmarcian": 5, "ondmarc": 5, "proofpoint": 5, "fraud": 5, "defens": 5, "valimail": 5, "draft": [5, 9], "rua": [5, 6], "failur": [5, 7, 9, 11], "ruf": [5, 6, 7, 11], "gmail": [5, 7, 11], "transpar": 5, "handl": [5, 11], "compress": 5, "structur": 5, "simpl": 5, "premad": [5, 10], "apach": 5, "kafka": [5, 11], "prerequisit": 5, "systemd": 5, "pattern": [5, 7], "retent": 5, "owa": 5, "ew": 5, "davmail": 5, "understand": [5, 7], "align": [5, 7, 9], "what": 5, "sender": [5, 7, 8], "won": 5, "t": [5, 8, 11], "dkim": [5, 7, 8, 9], "bug": 5, "tabl": [5, 7], "3": [6, 9, 10, 11], "anoth": [6, 11], "solut": 6, "two": 6, "mailto": 6, "uri": 6, "tag": 6, "comma": [6, 11], "behind": 6, "environ": 6, "detail": [6, 7], "http_proxi": 6, "prox": 6, "3128": 6, "https_proxi": 6, "ftp_proxi": 6, "credenti": [6, 11], "wide": [6, 9], "patch": 6, "2010": [6, 9], "rollup": 6, "22": 6, "kb4295699": 6, "2013": 6, "cumul": 6, "21": 6, "kb4099855": 6, "2016": 6, "11": [6, 9], "kb4134118": 6, "static": 6, "copi": [6, 10], "lite": 6, "databas": 6, "ipdb": 6, "distribut": 6, "term": 6, "creativ": 6, "attribut": 6, "intern": 6, "licens": 6, "fallback": 6, "geolite2": 6, "howev": 6, "cannot": 6, "tool": [6, 11], "locat": [6, 7], "overridden": 6, "buster": 6, "compon": 6, "contrib": 6, "repositori": [6, 10], "ppa": 6, "dnf": 6, "build": 6, "maco": 6, "window": 6, "decemb": 6, "30th": 6, "2019": 6, "free": 6, "account": [6, 7], "order": 6, "variou": 6, "regist": 6, "differ": [6, 7, 11], "older": [6, 9], "newer": 6, "Be": 6, "select": 6, "correct": 6, "v": [6, 11], "onc": 6, "pre": 6, "geoip": 6, "conf": 6, "systemdr": 6, "programdata": 6, "citi": 6, "asn": 6, "weekli": 6, "tuesdai": 6, "cron": 6, "schedul": 6, "task": 6, "python3": 6, "pip": 6, "virtualenv": 6, "dev": [6, 11], "libxml2": 6, "libxslt": 6, "python39": 6, "setuptool": 6, "devel": 6, "mkdir": 6, "b": [6, 9], "venv": [6, 11], "those": 6, "explicitli": 6, "9": 6, "insid": 6, "abl": 6, "libemail": 6, "friendli": 7, "incom": [7, 11], "switch": 7, "left": 7, "side": 7, "suggest": 7, "best": 7, "across": 7, "three": 7, "pie": 7, "chart": 7, "percentag": 7, "spf": [7, 9], "segment": 7, "malici": [7, 11], "just": 7, "especi": 7, "collect": [7, 11], "mai": [7, 11], "legitim": [7, 11], "correctli": 7, "while": [7, 11], "remain": 7, "often": 7, "rule": [7, 11], "wherea": 7, "reli": 7, "session": 7, "underneath": 7, "passag": 7, "disposit": [7, 9], "center": 7, "sort": [7, 11], "volum": 7, "By": [7, 11], "hover": 7, "mous": 7, "magnifi": 7, "glass": 7, "icon": 7, "our": 7, "recogn": 7, "market": 7, "plu": 7, "That": 7, "busi": 7, "particular": 7, "With": 7, "contact": 7, "lot": 7, "b2c": 7, "custom": [7, 11], "high": 7, "come": 7, "consum": 7, "googl": [7, 11], "yahoo": 7, "old": 7, "mention": 7, "earlier": 7, "similar": 7, "observ": 7, "who": 7, "addresse": 7, "parent": 7, "subsidiari": 7, "outdat": 7, "further": 7, "down": 7, "were": [7, 11], "call": 7, "been": [7, 11], "consolid": 7, "view": [7, 11], "own": [7, 10], "temporari": 7, "upper": 7, "These": 7, "recipi": 7, "avoid": 7, "leak": 7, "notabl": 7, "chines": 7, "suppli": [7, 11], "few": [7, 11], "wiki": 9, "schema": 9, "7480": 9, "appendix": 9, "c": [9, 11], "produc": 9, "normal": [9, 11], "regardless": 9, "xml_schema": 9, "report_metadata": 9, "org_nam": 9, "acm": 9, "org_email": 9, "org_extra_contact_info": 9, "report_id": 9, "9391651994964116463": 9, "begin_d": 9, "2012": 9, "04": 9, "27": 9, "20": 9, "00": 9, "end_dat": 9, "28": 9, "19": 9, "59": 9, "policy_publish": 9, "adkim": 9, "aspf": 9, "pct": 9, "100": [9, 11], "fo": 9, "72": 9, "150": 9, "241": 9, "94": 9, "adsl": 9, "shv": 9, "bellsouth": 9, "base_domain": 9, "policy_evalu": 9, "policy_override_reason": 9, "identifi": 9, "header_from": 9, "envelope_from": 9, "envelope_to": 9, "null": 9, "auth_result": 9, "selector": 9, "scope": [9, 11], "mfrom": 9, "source_ip_address": 9, "source_countri": 9, "source_reverse_dn": 9, "source_base_domain": 9, "spf_align": 9, "dkim_align": 9, "dmarc_align": 9, "policy_override_com": 9, "dkim_domain": 9, "dkim_selector": 9, "dkim_result": 9, "spf_domain": 9, "spf_scope": 9, "spf_result": 9, "xennn": 9, "anonym": 9, "feedback_typ": 9, "user_ag": 9, "lua": 9, "original_mail_from": 9, "sharepoint": 9, "de": 9, "original_rcpt_to": 9, "peter": 9, "pan": 9, "arrival_d": 9, "mon": 9, "01": 9, "oct": 9, "2018": 9, "0200": 9, "message_id": 9, "38": 9, "e7": 9, "30937": 9, "bd6e1bb5": 9, "mailrelai": 9, "authentication_result": 9, "di": 9, "delivery_result": 9, "auth_failur": 9, "reported_domain": 9, "arrival_date_utc": 9, "09": 9, "authentication_mechan": 9, "original_envelope_id": 9, "sample_headers_onli": 9, "servernameon": 9, "n": [9, 11], "tby": 9, "cest": 9, "ndate": 9, "nmessag": 9, "nto": 9, "nfrom": 9, "utf": 9, "sw50zxjha3rpdmugv2v0dgjld2vyymvylcocymvyc2ljahq": 9, "nsubject": 9, "nmime": 9, "nx": 9, "mailer": 9, "foundat": 9, "ncontent": 9, "charset": 9, "transfer": 9, "quot": 9, "printabl": 9, "head": 9, "href": 9, "3d": 9, "nwettbewerb": 9, "doctyp": 9, "w3c": 9, "dtd": 9, "meta": 9, "08": 9, "0240": 9, "003": 9, "parsed_sampl": 9, "display_nam": 9, "interakt": 9, "wettbewerb": 9, "\u00fcbersicht": 9, "to_domain": 9, "timezon": 9, "mime": 9, "hop": 9, "date_utc": 9, "has_defect": 9, "reply_to": 9, "filename_safe_subject": 9, "organization_nam": 9, "inc": 9, "2024": 9, "09t00": 9, "00z": 9, "09t23": 9, "59z": 9, "00z_exampl": 9, "policy_domain": 9, "policy_typ": 9, "st": 9, "policy_str": 9, "stsv1": 9, "mx": 9, "max_ag": 9, "86400": 9, "successful_session_count": 9, "failed_session_count": 9, "failure_detail": 9, "result_typ": 9, "sending_mta_ip": 9, "209": 9, "85": 9, "222": 9, "201": 9, "receiving_ip": 9, "173": 9, "212": 9, "41": 9, "receiving_mx_hostnam": 9, "208": 9, "176": 9, "collector": [10, 11], "editor": 10, "occurr": 10, "layout": 10, "although": 10, "slightli": 10, "easier": 10, "flexibl": 10, "usag": 11, "h": 11, "config_fil": 11, "verbos": 11, "debug": 11, "log_fil": 11, "file_path": 11, "posit": 11, "argument": 11, "exit": 11, "silent": 11, "impli": 11, "write": 11, "print": 11, "warn": 11, "program": 11, "describ": 11, "comment": 11, "save_aggreg": 11, "save_forens": 11, "dmarcresport": 11, "upersecur": 11, "splunk_hec": 11, "splunkhec": 11, "hectokengoesher": 11, "s3": 11, "bucket": 11, "my": 11, "localhost": 11, "514": 11, "full": 11, "either": 11, "period": 11, "n_proc": 11, "chunk_siz": 11, "larger": 11, "improv": 11, "thousand": 11, "label": 11, "arriv": 11, "993": 11, "escap": 11, "wherev": 11, "section": 11, "recommend": 11, "try": 11, "skip_certificate_verif": 11, "skip": 11, "msgraph": 11, "auth_method": 11, "method": 11, "usernamepassword": 11, "devicecod": 11, "clientsecret": 11, "m365": 11, "client_id": 11, "app": 11, "registr": 11, "client_secret": 11, "secret": 11, "tenant_id": 11, "azur": 11, "tenant": 11, "token_fil": 11, "allow_unencrypted_storag": 11, "fall": 11, "back": 11, "unencrypt": 11, "grant": 11, "readwrit": 11, "deleg": 11, "applic": 11, "restrict": 11, "sinc": 11, "applicationaccesspolici": 11, "powershel": 11, "accessright": 11, "restrictaccess": 11, "appid": 11, "policyscopegroupid": 11, "special": 11, "cert_path": 11, "trust": 11, "appli": 11, "passsword": 11, "aggregate_top": 11, "topic": 11, "forensic_top": 11, "25": 11, "starttl": 11, "upload": 11, "region_nam": 11, "region": 11, "endpoint_url": 11, "endpoint": 11, "access_key_id": 11, "secret_access_kei": 11, "udp": 11, "gmail_api": 11, "credentials_fil": 11, "include_spam_trash": 11, "spam": 11, "trash": 11, "acquir": 11, "googleapi": 11, "oauth2_port": 11, "tcp": 11, "oauth2": 11, "8080": 11, "paginate_messag": 11, "per": 11, "log_analyt": 11, "resid": 11, "dce": 11, "ingest": 11, "dcr_immutable_id": 11, "immut": 11, "dcr": 11, "dcr_aggregate_stream": 11, "stream": 11, "dcr_forensic_stream": 11, "dcr_smtp_tls_stream": 11, "regard": 11, "strongli": 11, "much": 11, "faster": 11, "reliabl": 11, "cisco": 11, "opendn": 11, "outsid": 11, "instanc": 11, "highli": 11, "industri": 11, "sensit": 11, "healthcar": 11, "financ": 11, "possibl": 11, "appear": 11, "sometim": 11, "kind": 11, "approach": 11, "manual": 11, "1000": 11, "analyz": 11, "year": 11, "_cluster": 11, "health": 11, "pretti": 11, "active_primary_shard": 11, "932": 11, "active_shard": 11, "2k": 11, "persist": 11, "max_shards_per_nod": 11, "2000": 11, "watcher": 11, "io": 11}, "objects": {"": [[0, 0, 0, "-", "parsedmarc"]], "parsedmarc": [[0, 1, 1, "", "InvalidAggregateReport"], [0, 1, 1, "", "InvalidDMARCReport"], [0, 1, 1, "", "InvalidForensicReport"], [0, 1, 1, "", "InvalidSMTPTLSReport"], [0, 1, 1, "", "ParserError"], [0, 0, 0, "-", "elastic"], [0, 2, 1, "", "email_results"], [0, 2, 1, "", "extract_report"], [0, 2, 1, "", "get_dmarc_reports_from_mailbox"], [0, 2, 1, "", "get_dmarc_reports_from_mbox"], [0, 2, 1, "", "get_report_zip"], [0, 2, 1, "", "parse_aggregate_report_file"], [0, 2, 1, "", "parse_aggregate_report_xml"], [0, 2, 1, "", "parse_forensic_report"], [0, 2, 1, "", "parse_report_email"], [0, 2, 1, "", "parse_report_file"], [0, 2, 1, "", "parse_smtp_tls_report_json"], [0, 2, 1, "", "parsed_aggregate_reports_to_csv"], [0, 2, 1, "", "parsed_aggregate_reports_to_csv_rows"], [0, 2, 1, "", "parsed_forensic_reports_to_csv"], [0, 2, 1, "", "parsed_forensic_reports_to_csv_rows"], [0, 2, 1, "", "parsed_smtp_tls_reports_to_csv"], [0, 2, 1, "", "parsed_smtp_tls_reports_to_csv_rows"], [0, 2, 1, "", "save_output"], [0, 0, 0, "-", "splunk"], [0, 0, 0, "-", "utils"], [0, 2, 1, "", "watch_inbox"]], "parsedmarc.elastic": [[0, 1, 1, "", "AlreadySaved"], [0, 1, 1, "", "ElasticsearchError"], [0, 2, 1, "", "create_indexes"], [0, 2, 1, "", "migrate_indexes"], [0, 2, 1, "", "save_aggregate_report_to_elasticsearch"], [0, 2, 1, "", "save_forensic_report_to_elasticsearch"], [0, 2, 1, "", "save_smtp_tls_report_to_elasticsearch"], [0, 2, 1, "", "set_hosts"]], "parsedmarc.splunk": [[0, 3, 1, "", "HECClient"], [0, 1, 1, "", "SplunkError"]], "parsedmarc.splunk.HECClient": [[0, 4, 1, "", "save_aggregate_reports_to_splunk"], [0, 4, 1, "", "save_forensic_reports_to_splunk"], [0, 4, 1, "", "save_smtp_tls_reports_to_splunk"]], "parsedmarc.utils": [[0, 1, 1, "", "DownloadError"], [0, 1, 1, "", "EmailParserError"], [0, 2, 1, "", "convert_outlook_msg"], [0, 2, 1, "", "decode_base64"], [0, 2, 1, "", "get_base_domain"], [0, 2, 1, "", "get_filename_safe_string"], [0, 2, 1, "", "get_ip_address_country"], [0, 2, 1, "", "get_ip_address_info"], [0, 2, 1, "", "get_reverse_dns"], [0, 2, 1, "", "human_timestamp_to_datetime"], [0, 2, 1, "", "human_timestamp_to_unix_timestamp"], [0, 2, 1, "", "is_mbox"], [0, 2, 1, "", "is_outlook_msg"], [0, 2, 1, "", "parse_email"], [0, 2, 1, "", "query_dns"], [0, 2, 1, "", "timestamp_to_datetime"], [0, 2, 1, "", "timestamp_to_human"]]}, "objtypes": {"0": "py:module", "1": "py:exception", "2": "py:function", "3": "py:class", "4": "py:method"}, "objnames": {"0": ["py", "module", "Python module"], "1": ["py", "exception", "Python exception"], "2": ["py", "function", "Python function"], "3": ["py", "class", "Python class"], "4": ["py", "method", "Python method"]}, "titleterms": {"api": 0, "refer": 0, "parsedmarc": [0, 1, 2, 5, 6, 11], "elast": 0, "splunk": [0, 10], "util": 0, "indic": 0, "tabl": 0, "contribut": 1, "bug": 1, "report": [1, 5, 6, 9], "access": 2, "an": 2, "inbox": 2, "us": [2, 6, 7, 11], "owa": 2, "ew": 2, "run": [2, 11], "davmail": 2, "systemd": [2, 11], "servic": [2, 11], "configur": [2, 11], "understand": 3, "dmarc": [3, 5, 7], "resourc": 3, "guid": 3, "spf": 3, "record": [3, 4], "valid": 3, "lookalik": 3, "domain": 3, "align": 3, "what": [3, 8], "sender": 3, "won": 3, "t": 3, "support": 3, "dkim": 3, "about": [3, 8], "mail": [3, 8], "list": [3, 8], "best": [3, 8], "practic": [3, 8], "do": [3, 8], "mailman": [3, 8], "2": [3, 8], "3": [3, 8], "listserv": [3, 8], "workaround": [3, 8], "elasticsearch": 4, "kibana": [4, 7], "instal": [4, 6], "upgrad": 4, "index": 4, "pattern": 4, "retent": 4, "document": 5, "open": 5, "sourc": 5, "analyz": [5, 6], "visual": 5, "featur": 5, "content": 5, "prerequisit": 6, "test": 6, "multipl": 6, "web": 6, "proxi": 6, "microsoft": 6, "exchang": 6, "geoipupd": 6, "setup": 6, "option": 6, "depend": 6, "dashboard": 7, "summari": 7, "forens": [7, 9], "sampl": [7, 9], "output": 9, "aggreg": 9, "json": 9, "csv": 9, "smtp": 9, "tl": 9, "cli": 11, "help": 11, "file": 11}, "envversion": {"sphinx.domains.c": 2, "sphinx.domains.changeset": 1, "sphinx.domains.citation": 1, "sphinx.domains.cpp": 8, "sphinx.domains.index": 1, "sphinx.domains.javascript": 2, "sphinx.domains.math": 2, "sphinx.domains.python": 3, "sphinx.domains.rst": 2, "sphinx.domains.std": 2, "sphinx.ext.todo": 2, "sphinx.ext.viewcode": 1, "sphinx": 57}, "alltitles": {"API reference": [[0, "api-reference"]], "parsedmarc": [[0, "module-parsedmarc"]], "parsedmarc.elastic": [[0, "module-parsedmarc.elastic"]], "parsedmarc.splunk": [[0, "module-parsedmarc.splunk"]], "parsedmarc.utils": [[0, "module-parsedmarc.utils"]], "Indices and tables": [[0, "indices-and-tables"]], "Contributing to parsedmarc": [[1, "contributing-to-parsedmarc"]], "Bug reports": [[1, "bug-reports"]], "Accessing an inbox using OWA/EWS": [[2, "accessing-an-inbox-using-owa-ews"]], "Running DavMail as a systemd service": [[2, "running-davmail-as-a-systemd-service"]], "Configuring parsedmarc for DavMail": [[2, "configuring-parsedmarc-for-davmail"]], "Understanding DMARC": [[3, "understanding-dmarc"]], "Resources": [[3, "resources"]], "DMARC guides": [[3, "dmarc-guides"]], "SPF and DMARC record validation": [[3, "spf-and-dmarc-record-validation"]], "Lookalike domains": [[3, "lookalike-domains"]], "DMARC Alignment Guide": [[3, "dmarc-alignment-guide"]], "What if a sender won\u2019t support DKIM/DMARC?": [[3, "what-if-a-sender-wont-support-dkim-dmarc"]], "What about mailing lists?": [[3, "what-about-mailing-lists"], [8, "what-about-mailing-lists"]], "Mailing list best practices": [[3, "mailing-list-best-practices"], [8, "mailing-list-best-practices"]], "Do": [[3, "do"], [8, "do"]], "Do not": [[3, "do-not"], [8, "do-not"]], "Mailman 2": [[3, "mailman-2"], [3, "id1"], [8, "mailman-2"], [8, "id1"]], "Mailman 3": [[3, "mailman-3"], [3, "id2"], [8, "mailman-3"], [8, "id2"]], "LISTSERV": [[3, "listserv"], [8, "listserv"]], "Workarounds": [[3, "workarounds"], [8, "workarounds"]], "Elasticsearch and Kibana": [[4, "elasticsearch-and-kibana"]], "Installation": [[4, "installation"], [6, "installation"]], "Upgrading Kibana index patterns": [[4, "upgrading-kibana-index-patterns"]], "Records retention": [[4, "records-retention"]], "parsedmarc documentation - Open source DMARC report analyzer and visualizer": [[5, "parsedmarc-documentation-open-source-dmarc-report-analyzer-and-visualizer"]], "Features": [[5, "features"]], "Contents": [[5, null]], "Prerequisites": [[6, "prerequisites"]], "Testing multiple report analyzers": [[6, "testing-multiple-report-analyzers"]], "Using a web proxy": [[6, "using-a-web-proxy"]], "Using Microsoft Exchange": [[6, "using-microsoft-exchange"]], "geoipupdate setup": [[6, "geoipupdate-setup"]], "Installing parsedmarc": [[6, "installing-parsedmarc"]], "Optional dependencies": [[6, "optional-dependencies"]], "Using the Kibana dashboards": [[7, "using-the-kibana-dashboards"]], "DMARC Summary": [[7, "dmarc-summary"]], "DMARC Forensic Samples": [[7, "dmarc-forensic-samples"]], "Sample outputs": [[9, "sample-outputs"]], "Sample aggregate report output": [[9, "sample-aggregate-report-output"]], "JSON aggregate report": [[9, "json-aggregate-report"]], "CSV aggregate report": [[9, "csv-aggregate-report"]], "Sample forensic report output": [[9, "sample-forensic-report-output"]], "JSON forensic report": [[9, "json-forensic-report"]], "CSV forensic report": [[9, "csv-forensic-report"]], "JSON SMTP TLS report": [[9, "json-smtp-tls-report"]], "Splunk": [[10, "splunk"]], "Using parsedmarc": [[11, "using-parsedmarc"]], "CLI help": [[11, "cli-help"]], "Configuration file": [[11, "configuration-file"]], "Running parsedmarc as a systemd service": [[11, "running-parsedmarc-as-a-systemd-service"]]}, "indexentries": {"alreadysaved": [[0, "parsedmarc.elastic.AlreadySaved"]], "downloaderror": [[0, "parsedmarc.utils.DownloadError"]], "elasticsearcherror": [[0, "parsedmarc.elastic.ElasticsearchError"]], "emailparsererror": [[0, "parsedmarc.utils.EmailParserError"]], "hecclient (class in parsedmarc.splunk)": [[0, "parsedmarc.splunk.HECClient"]], "invalidaggregatereport": [[0, "parsedmarc.InvalidAggregateReport"]], "invaliddmarcreport": [[0, "parsedmarc.InvalidDMARCReport"]], "invalidforensicreport": [[0, "parsedmarc.InvalidForensicReport"]], "invalidsmtptlsreport": [[0, "parsedmarc.InvalidSMTPTLSReport"]], "parsererror": [[0, "parsedmarc.ParserError"]], "splunkerror": [[0, "parsedmarc.splunk.SplunkError"]], "convert_outlook_msg() (in module parsedmarc.utils)": [[0, "parsedmarc.utils.convert_outlook_msg"]], "create_indexes() (in module parsedmarc.elastic)": [[0, "parsedmarc.elastic.create_indexes"]], "decode_base64() (in module parsedmarc.utils)": [[0, "parsedmarc.utils.decode_base64"]], "email_results() (in module parsedmarc)": [[0, "parsedmarc.email_results"]], "extract_report() (in module parsedmarc)": [[0, "parsedmarc.extract_report"]], "get_base_domain() (in module parsedmarc.utils)": [[0, "parsedmarc.utils.get_base_domain"]], "get_dmarc_reports_from_mailbox() (in module parsedmarc)": [[0, "parsedmarc.get_dmarc_reports_from_mailbox"]], "get_dmarc_reports_from_mbox() (in module parsedmarc)": [[0, "parsedmarc.get_dmarc_reports_from_mbox"]], "get_filename_safe_string() (in module parsedmarc.utils)": [[0, "parsedmarc.utils.get_filename_safe_string"]], "get_ip_address_country() (in module parsedmarc.utils)": [[0, "parsedmarc.utils.get_ip_address_country"]], "get_ip_address_info() (in module parsedmarc.utils)": [[0, "parsedmarc.utils.get_ip_address_info"]], "get_report_zip() (in module parsedmarc)": [[0, "parsedmarc.get_report_zip"]], "get_reverse_dns() (in module parsedmarc.utils)": [[0, "parsedmarc.utils.get_reverse_dns"]], "human_timestamp_to_datetime() (in module parsedmarc.utils)": [[0, "parsedmarc.utils.human_timestamp_to_datetime"]], "human_timestamp_to_unix_timestamp() (in module parsedmarc.utils)": [[0, "parsedmarc.utils.human_timestamp_to_unix_timestamp"]], "is_mbox() (in module parsedmarc.utils)": [[0, "parsedmarc.utils.is_mbox"]], "is_outlook_msg() (in module parsedmarc.utils)": [[0, "parsedmarc.utils.is_outlook_msg"]], "migrate_indexes() (in module parsedmarc.elastic)": [[0, "parsedmarc.elastic.migrate_indexes"]], "module": [[0, "module-parsedmarc"], [0, "module-parsedmarc.elastic"], [0, "module-parsedmarc.splunk"], [0, "module-parsedmarc.utils"]], "parse_aggregate_report_file() (in module parsedmarc)": [[0, "parsedmarc.parse_aggregate_report_file"]], "parse_aggregate_report_xml() (in module parsedmarc)": [[0, "parsedmarc.parse_aggregate_report_xml"]], "parse_email() (in module parsedmarc.utils)": [[0, "parsedmarc.utils.parse_email"]], "parse_forensic_report() (in module parsedmarc)": [[0, "parsedmarc.parse_forensic_report"]], "parse_report_email() (in module parsedmarc)": [[0, "parsedmarc.parse_report_email"]], "parse_report_file() (in module parsedmarc)": [[0, "parsedmarc.parse_report_file"]], "parse_smtp_tls_report_json() (in module parsedmarc)": [[0, "parsedmarc.parse_smtp_tls_report_json"]], "parsed_aggregate_reports_to_csv() (in module parsedmarc)": [[0, "parsedmarc.parsed_aggregate_reports_to_csv"]], "parsed_aggregate_reports_to_csv_rows() (in module parsedmarc)": [[0, "parsedmarc.parsed_aggregate_reports_to_csv_rows"]], "parsed_forensic_reports_to_csv() (in module parsedmarc)": [[0, "parsedmarc.parsed_forensic_reports_to_csv"]], "parsed_forensic_reports_to_csv_rows() (in module parsedmarc)": [[0, "parsedmarc.parsed_forensic_reports_to_csv_rows"]], "parsed_smtp_tls_reports_to_csv() (in module parsedmarc)": [[0, "parsedmarc.parsed_smtp_tls_reports_to_csv"]], "parsed_smtp_tls_reports_to_csv_rows() (in module parsedmarc)": [[0, "parsedmarc.parsed_smtp_tls_reports_to_csv_rows"]], "parsedmarc": [[0, "module-parsedmarc"]], "parsedmarc.elastic": [[0, "module-parsedmarc.elastic"]], "parsedmarc.splunk": [[0, "module-parsedmarc.splunk"]], "parsedmarc.utils": [[0, "module-parsedmarc.utils"]], "query_dns() (in module parsedmarc.utils)": [[0, "parsedmarc.utils.query_dns"]], "save_aggregate_report_to_elasticsearch() (in module parsedmarc.elastic)": [[0, "parsedmarc.elastic.save_aggregate_report_to_elasticsearch"]], "save_aggregate_reports_to_splunk() (parsedmarc.splunk.hecclient method)": [[0, "parsedmarc.splunk.HECClient.save_aggregate_reports_to_splunk"]], "save_forensic_report_to_elasticsearch() (in module parsedmarc.elastic)": [[0, "parsedmarc.elastic.save_forensic_report_to_elasticsearch"]], "save_forensic_reports_to_splunk() (parsedmarc.splunk.hecclient method)": [[0, "parsedmarc.splunk.HECClient.save_forensic_reports_to_splunk"]], "save_output() (in module parsedmarc)": [[0, "parsedmarc.save_output"]], "save_smtp_tls_report_to_elasticsearch() (in module parsedmarc.elastic)": [[0, "parsedmarc.elastic.save_smtp_tls_report_to_elasticsearch"]], "save_smtp_tls_reports_to_splunk() (parsedmarc.splunk.hecclient method)": [[0, "parsedmarc.splunk.HECClient.save_smtp_tls_reports_to_splunk"]], "set_hosts() (in module parsedmarc.elastic)": [[0, "parsedmarc.elastic.set_hosts"]], "timestamp_to_datetime() (in module parsedmarc.utils)": [[0, "parsedmarc.utils.timestamp_to_datetime"]], "timestamp_to_human() (in module parsedmarc.utils)": [[0, "parsedmarc.utils.timestamp_to_human"]], "watch_inbox() (in module parsedmarc)": [[0, "parsedmarc.watch_inbox"]]}}) \ No newline at end of file +Search.setIndex({"docnames": ["api", "contributing", "davmail", "dmarc", "elasticsearch", "index", "installation", "kibana", "mailing-lists", "opensearch", "output", "splunk", "usage"], "filenames": ["api.md", "contributing.md", "davmail.md", "dmarc.md", "elasticsearch.md", "index.md", "installation.md", "kibana.md", "mailing-lists.md", "opensearch.md", "output.md", "splunk.md", "usage.md"], "titles": ["API reference", "Contributing to parsedmarc", "Accessing an inbox using OWA/EWS", "Understanding DMARC", "Elasticsearch and Kibana", "parsedmarc documentation - Open source DMARC report analyzer and visualizer", "Installation", "Using the Kibana dashboards", "What about mailing lists?", "OpenSearch and Grafana", "Sample outputs", "Splunk", "Using parsedmarc"], "terms": {"A": [0, 3, 12], "python": [0, 5, 6], "packag": [0, 4], "pars": [0, 3, 5, 6, 10, 12], "dmarc": [0, 4, 6, 8, 9, 10, 11, 12], "report": [0, 4, 7, 11, 12], "except": [0, 12], "invalidaggregatereport": 0, "sourc": [0, 3, 4, 6, 7, 10], "rais": 0, "when": [0, 3, 5, 7, 8, 12], "an": [0, 3, 5, 7, 8, 10, 12], "invalid": 0, "aggreg": [0, 5, 7, 11, 12], "i": [0, 2, 3, 4, 5, 6, 7, 8, 10, 12], "encount": 0, "invaliddmarcreport": 0, "invalidforensicreport": 0, "forens": [0, 5, 11, 12], "invalidsmtptlsreport": 0, "smtp": [0, 3, 7, 12], "tl": [0, 12], "parsererror": 0, "whenev": [0, 2, 12], "parser": 0, "fail": [0, 3, 7, 8, 10, 12], "some": [0, 2, 3, 4, 7, 8], "reason": [0, 2, 4, 12], "email_result": 0, "result": [0, 5, 7, 10, 12], "host": [0, 2, 3, 4, 5, 8, 12], "mail_from": 0, "mail_to": 0, "mail_cc": 0, "none": [0, 3, 10, 12], "mail_bcc": 0, "port": [0, 2, 12], "0": [0, 2, 3, 4, 5, 6, 8, 9, 10, 11, 12], "require_encrypt": 0, "fals": [0, 2, 6, 10, 12], "verifi": 0, "true": [0, 2, 4, 10, 12], "usernam": [0, 12], "password": [0, 4, 6, 12], "subject": [0, 3, 8, 10, 12], "attachment_filenam": 0, "messag": [0, 2, 3, 4, 6, 7, 8, 10, 12], "email": [0, 3, 5, 6, 7, 8, 10, 11, 12], "zip": [0, 2, 5, 12], "file": [0, 2, 5, 6, 11], "paramet": 0, "ordereddict": 0, "mail": [0, 5, 6, 10, 12], "server": [0, 2, 3, 4, 6, 7, 10, 12], "hostnam": [0, 12], "ip": [0, 3, 4, 6, 7, 12], "address": [0, 2, 3, 4, 7, 8, 10, 12], "The": [0, 3, 6, 7, 11, 12], "valu": [0, 3, 4, 7, 8, 12], "from": [0, 2, 3, 4, 5, 6, 7, 8, 10, 12], "header": [0, 3, 7, 8, 10, 12], "list": [0, 2, 4, 5, 7, 12], "cc": [0, 10], "bcc": [0, 10], "int": [0, 12], "us": [0, 3, 4, 5, 8, 10], "bool": [0, 12], "requir": [0, 2, 3, 4, 6, 8, 12], "secur": [0, 4, 12], "connect": [0, 2, 4, 12], "start": [0, 2, 4, 6, 7, 9, 11, 12], "ssl": [0, 2, 4, 12], "certif": [0, 4, 12], "str": [0, 12], "option": [0, 2, 3, 4, 5, 8, 11, 12], "overrid": 0, "default": [0, 2, 4, 6, 7, 12], "attach": [0, 3, 8, 10, 12], "filenam": [0, 12], "plain": 0, "text": [0, 10], "bodi": [0, 3, 8, 10, 12], "extract_report": 0, "input_": 0, "extract": [0, 2], "gzip": [0, 5], "given": [0, 12], "path": [0, 4, 12], "like": [0, 3, 6, 8], "object": [0, 4], "byte": 0, "input": 0, "return": 0, "type": [0, 10, 12], "get_dmarc_reports_from_mailbox": 0, "mailboxconnect": 0, "reports_fold": [0, 12], "inbox": [0, 3, 5, 8, 12], "archive_fold": [0, 12], "archiv": [0, 12], "delet": [0, 2, 4, 12], "test": [0, 10, 12], "ip_db_path": [0, 6, 12], "offlin": [0, 12], "nameserv": [0, 12], "dns_timeout": [0, 12], "6": [0, 4, 6, 12], "strip_attachment_payload": [0, 12], "batch_siz": [0, 12], "10": [0, 6, 10, 12], "create_fold": 0, "fetch": [0, 12], "mailbox": [0, 7, 12], "folder": [0, 2, 12], "where": [0, 2, 3, 8, 12], "can": [0, 2, 3, 4, 5, 6, 7, 8, 12], "found": [0, 6, 12], "move": [0, 4, 12], "process": [0, 2, 5, 6, 12], "after": [0, 2, 4, 12], "them": [0, 4, 7, 12], "do": [0, 2, 6, 7, 12], "mmdb": [0, 12], "maxmind": [0, 6, 12], "dbip": [0, 12], "queri": [0, 12], "onlin": [0, 2, 12], "geoloc": [0, 12], "dn": [0, 3, 7, 12], "float": [0, 12], "set": [0, 2, 3, 4, 6, 7, 8, 9, 12], "timeout": [0, 2, 12], "remov": [0, 3, 4, 8, 12], "payload": [0, 12], "dict": 0, "previou": [0, 2, 4, 12], "run": [0, 4, 5, 6], "number": [0, 12], "read": [0, 12], "befor": [0, 12], "save": [0, 4, 6, 12], "limit": [0, 2, 12], "whether": 0, "creat": [0, 2, 3, 4, 6, 8, 12], "destin": 0, "watch": [0, 2, 4, 12], "aggregate_report": 0, "forensic_report": 0, "get_dmarc_reports_from_mbox": 0, "2": [0, 4, 10, 12], "parallel": [0, 12], "mbox": [0, 12], "format": [0, 6], "contain": [0, 7, 11, 12], "e": [0, 2, 3, 4, 6, 8, 12], "one": [0, 3, 5, 8, 12], "more": [0, 4, 6, 11, 12], "cloudflar": [0, 12], "": [0, 2, 3, 4, 6, 8, 10, 12], "public": [0, 3, 10, 12], "resolv": [0, 12], "second": [0, 2, 12], "make": [0, 3, 4, 8, 9, 12], "get_report_zip": 0, "output": [0, 5, 12], "parse_aggregate_report_fil": 0, "_input": 0, "keep_al": 0, "callabl": 0, "keep": 0, "aliv": 0, "function": 0, "parse_aggregate_report_xml": 0, "xml": [0, 11], "string": 0, "consist": [0, 5, 10], "parse_forensic_report": 0, "feedback_report": 0, "sampl": [0, 5, 12], "msg_date": 0, "convert": [0, 3, 8], "feedback": 0, "rfc": [0, 3, 8, 10], "822": 0, "date": [0, 3, 8, 10], "parse_report_email": 0, "report_typ": 0, "parse_report_fil": 0, "parse_smtp_tls_report_json": 0, "valid": [0, 7, 10, 12], "parsed_aggregate_reports_to_csv": 0, "flat": 0, "csv": [0, 5, 12], "includ": [0, 3, 6, 7, 8, 12], "data": [0, 4, 5, 7, 9, 11, 12], "parsed_aggregate_reports_to_csv_row": 0, "parsed_forensic_reports_to_csv": 0, "parsed_forensic_reports_to_csv_row": 0, "parsed_smtp_tls_reports_to_csv": 0, "parsed_smtp_tls_reports_to_csv_row": 0, "oor": 0, "singl": 0, "layer": 0, "suitabl": 0, "save_output": 0, "output_directori": 0, "aggregate_json_filenam": [0, 12], "json": [0, 5, 12], "forensic_json_filenam": [0, 12], "smtp_tls_json_filenam": 0, "smtp_tl": 0, "aggregate_csv_filenam": [0, 12], "forensic_csv_filenam": [0, 12], "smtp_tls_csv_filenam": 0, "directori": [0, 12], "watch_inbox": 0, "mailbox_connect": 0, "callback": 0, "check_timeout": [0, 12], "30": [0, 12], "new": [0, 2, 3, 6, 7, 12], "send": [0, 2, 3, 4, 5, 7, 8, 11, 12], "receiv": [0, 10, 12], "imap": [0, 2, 5, 12], "wait": [0, 12], "idl": [0, 2, 12], "respons": [0, 12], "until": [0, 12], "next": [0, 12], "check": [0, 2, 3, 4, 6, 12], "replac": [0, 3, 4, 8], "alreadysav": 0, "match": [0, 4, 11], "exist": [0, 3, 4, 8], "elasticsearcherror": 0, "elasticsearch": [0, 5, 12], "error": [0, 10, 12], "occur": [0, 7], "create_index": 0, "name": [0, 3, 4, 7, 10, 11, 12], "index": [0, 5, 9, 11, 12], "migrate_index": 0, "aggregate_index": 0, "forensic_index": 0, "updat": [0, 4, 6, 12], "map": 0, "save_aggregate_report_to_elasticsearch": 0, "index_suffix": [0, 12], "monthly_index": [0, 12], "number_of_shard": [0, 12], "1": [0, 2, 4, 5, 6, 10, 12], "number_of_replica": [0, 12], "suffix": [0, 12], "monthli": [0, 12], "instead": [0, 3, 6, 8, 12], "daili": [0, 12], "shard": [0, 12], "replica": [0, 12], "save_forensic_report_to_elasticsearch": 0, "save_smtp_tls_report_to_elasticsearch": 0, "set_host": 0, "use_ssl": 0, "ssl_cert_path": 0, "apikei": [0, 12], "60": [0, 12], "url": [0, 2, 12], "http": [0, 1, 2, 3, 4, 6, 8, 9, 10, 11, 12], "chain": 0, "authent": [0, 2, 3, 4, 7, 12], "base64": 0, "encod": [0, 10, 12], "kei": [0, 3, 4, 6, 12], "opensearcherror": 0, "save_aggregate_report_to_opensearch": 0, "save_forensic_report_to_opensearch": 0, "save_smtp_tls_report_to_opensearch": 0, "class": 0, "hecclient": 0, "access_token": 0, "initi": 0, "hec": [0, 11, 12], "access": [0, 4, 5, 6, 12], "token": [0, 4, 12], "give": [0, 4, 12], "up": [0, 2, 4, 6, 7, 9, 12], "save_aggregate_reports_to_splunk": 0, "dictionari": 0, "save_forensic_reports_to_splunk": 0, "save_smtp_tls_reports_to_splunk": 0, "splunkerror": 0, "might": [0, 3, 7, 8], "other": [0, 3, 4, 7, 8], "project": [0, 2, 3, 5, 11], "downloaderror": 0, "download": [0, 2, 4, 6], "emailparsererror": 0, "convert_outlook_msg": 0, "msg_byte": 0, "msgconvert": [0, 6], "perl": [0, 6], "outlook": [0, 2, 6], "m": [0, 6, 10, 12], "standard": [0, 5, 10], "content": [0, 3, 8, 10, 11], "msg": [0, 6], "decode_base64": 0, "decod": 0, "pad": 0, "being": 0, "get_base_domain": 0, "domain": [0, 4, 7, 8, 10], "get": [0, 2, 4, 6, 12], "base": [0, 2, 3, 4, 7, 8, 10], "ar": [0, 2, 3, 4, 6, 7, 8, 10, 12], "publicsuffix": 0, "org": [0, 6, 9, 10], "public_suffix_list": 0, "dat": 0, "subdomain": [0, 3], "get_filename_safe_str": 0, "safe": 0, "get_ip_address_countri": 0, "ip_address": [0, 10], "db_path": 0, "iso": 0, "code": [0, 4, 5], "countri": [0, 6, 7, 10], "associ": 0, "ipv4": 0, "ipv6": 0, "And": 0, "get_ip_address_info": 0, "cach": [0, 12], "revers": [0, 7], "inform": [0, 4, 6, 7, 12], "expiringdict": 0, "storag": [0, 12], "reverse_dn": [0, 10], "get_reverse_dn": 0, "ani": [0, 3, 7, 8, 12], "human_timestamp_to_datetim": 0, "human_timestamp": 0, "to_utc": 0, "human": [0, 7], "readabl": 0, "timestamp": 0, "datetim": 0, "utc": 0, "human_timestamp_to_unix_timestamp": 0, "unix": 0, "yyyi": 0, "mm": 0, "dd": 0, "hh": 0, "ss": 0, "is_mbox": 0, "flag": [0, 2], "is_outlook_msg": 0, "ol": [0, 6], "parse_email": 0, "simplifi": 0, "binari": 0, "query_dn": 0, "record_typ": 0, "about": [0, 5, 6], "record": [0, 5, 6, 10], "answer": [0, 12], "timestamp_to_datetim": 0, "timestamp_to_human": 0, "modul": [0, 5, 12], "pleas": [1, 5, 12], "github": [1, 6, 10, 12], "issu": [1, 5], "tracker": 1, "com": [1, 2, 3, 8, 9, 10, 12], "domainawar": [1, 3, 12], "8": [2, 4, 6, 10, 12], "support": [2, 5, 10, 11], "microsoft": [2, 5, 10, 12], "offic": 2, "365": [2, 4], "via": 2, "graph": [2, 5, 7, 12], "api": [2, 4, 5, 12], "which": [2, 4, 7, 12], "prefer": [2, 6], "over": [2, 5, 7], "organ": [2, 7, 12], "allow": [2, 3, 8, 12], "onli": [2, 3, 6, 7, 8, 12], "exchang": [2, 10, 12], "web": [2, 4], "In": [2, 3, 7, 8, 12], "case": [2, 3, 8], "need": [2, 3, 4, 6, 7, 8, 12], "local": [2, 4, 10, 12], "gatewai": 2, "It": [2, 4, 7, 10, 12], "even": [2, 3, 8, 12], "work": [2, 3, 5, 6, 7, 8], "modern": [2, 3, 8], "auth": [2, 10, 12], "multi": [2, 12], "factor": 2, "To": [2, 4, 6, 7, 9, 10, 12], "thi": [2, 3, 4, 5, 6, 7, 8, 10, 12], "latest": [2, 4, 6, 9], "version": [2, 4, 6, 9, 10, 11, 12], "sourceforg": 2, "net": [2, 10], "unzip": 2, "command": [2, 3, 8, 12], "instal": [2, 5, 12], "java": 2, "sudo": [2, 4, 6, 12], "apt": [2, 4, 6], "jre": 2, "headless": 2, "properti": 2, "see": [2, 3, 4, 5, 7, 12], "document": [2, 12], "basic": [2, 12], "workstat": 2, "mode": [2, 4, 10, 12], "auto": 2, "webdav": 2, "enableew": 2, "office365": 2, "asmx": 2, "listen": [2, 12], "imapport": 2, "1143": 2, "network": [2, 4, 12], "proxi": 2, "enableproxi": 2, "usesystemproxi": 2, "proxyhost": 2, "proxyport": 2, "proxyus": 2, "proxypassword": 2, "exclud": 2, "noproxyfor": 2, "block": [2, 12], "remot": 2, "allowremot": 2, "bind": 2, "socket": 2, "loopback": 2, "bindaddress": 2, "127": [2, 4, 12], "disabl": [2, 12], "specifi": [2, 3], "nosecureimap": 2, "keepal": 2, "charact": [2, 12], "dure": 2, "larg": 2, "enablekeepal": 2, "count": [2, 10], "retriev": 2, "foldersizelimit": 2, "immedi": 2, "store": [2, 4, 9], "imapautoexpung": 2, "enabl": [2, 4, 12], "poll": [2, 12], "delai": [2, 10], "minut": [2, 12], "imapidledelai": 2, "alwai": [2, 4, 12], "repli": [2, 3, 8], "rfc822": 2, "size": [2, 4], "request": [2, 4, 12], "approxim": 2, "perform": [2, 12], "imapalwaysapproxmsgs": 2, "client": [2, 3, 4, 8, 12], "300": 2, "clientsotimeout": 2, "system": [2, 3, 4, 6, 8, 12], "user": [2, 3, 4, 5, 6, 8, 10, 12], "useradd": [2, 6], "r": [2, 6, 10, 12], "bin": [2, 4, 6, 12], "protect": [2, 3, 5, 8, 12], "pry": [2, 12], "ey": [2, 12], "chown": [2, 12], "root": [2, 12], "opt": [2, 6, 12], "chmod": [2, 4, 12], "u": [2, 6, 10, 12], "rw": [2, 12], "g": [2, 3, 4, 8, 12], "o": [2, 4, 12], "nano": [2, 12], "etc": [2, 3, 4, 6, 8, 12], "unit": [2, 12], "descript": [2, 6, 12], "want": [2, 5, 12], "target": [2, 12], "syslog": [2, 12], "execstart": [2, 12], "group": [2, 7, 12], "restart": [2, 3, 4, 8, 12], "restartsec": [2, 12], "5m": [2, 12], "wantedbi": [2, 12], "Then": [2, 3, 4, 6, 8, 12], "systemctl": [2, 4, 12], "daemon": [2, 4, 12], "reload": [2, 4, 12], "you": [2, 3, 4, 5, 6, 7, 8, 12], "must": [2, 3, 8, 12], "also": [2, 3, 7, 8, 12], "abov": [2, 12], "edit": [2, 6, 12], "everi": [2, 6, 12], "time": [2, 4, 6, 7, 12], "upgrad": [2, 5, 6, 12], "statu": [2, 12], "event": [2, 11, 12], "crash": [2, 4, 12], "5": [2, 4, 9], "show": [2, 7, 12], "log": [2, 12], "current": [2, 4, 12], "vew": 2, "well": [2, 12], "newest": [2, 12], "oldest": [2, 12], "journalctl": [2, 12], "becaus": [2, 3, 7, 8, 12], "interact": [2, 4], "add": [2, 3, 4, 6, 7, 8, 12], "follow": [2, 4], "ini": [2, 12], "config": [2, 6, 12], "demystifi": 3, "complet": [3, 4], "If": [3, 4, 6, 7, 8, 12], "look": [3, 7], "out": [3, 4, 7], "sister": 3, "checkdmarc": 3, "against": [3, 8], "spoof": [3, 8], "open": 3, "monitor": [3, 12], "ensur": [3, 6, 8], "dkm": 3, "mechan": 3, "actual": [3, 10], "same": [3, 4, 6, 7, 11], "end": [3, 4], "pass": [3, 7, 10], "long": 3, "relat": 3, "indic": [3, 5], "signatur": [3, 7, 8], "publish": 3, "envelop": 3, "sign": [3, 4, 6], "vendor": 3, "don": 3, "know": 3, "yet": 3, "ask": 3, "thei": [3, 6, 7, 8, 12], "through": 3, "your": [3, 4, 6, 7, 8, 11, 12], "relai": [3, 8], "theirs": 3, "realli": 3, "why": [3, 7], "displai": [3, 7, 11], "worst": 3, "have": [3, 4, 6, 7, 8, 11, 12], "specif": [3, 12], "norepli": [3, 10], "exampl": [3, 4, 6, 8, 10, 12], "separ": [3, 4, 6, 7, 9, 11, 12], "p": [3, 6, 10], "alter": [3, 8], "sp": [3, 10], "top": [3, 7], "level": [3, 4], "tld": 3, "would": [3, 5, 6, 8], "leav": 3, "vulner": 3, "deploi": [3, 8], "find": [3, 7, 8], "most": [3, 4, 7, 8, 12], "modifi": [3, 8, 12], "footer": [3, 8], "part": [3, 4, 7, 8], "therebi": [3, 8], "break": [3, 4, 8], "ideal": [3, 8], "should": [3, 6, 7, 8, 12], "forward": [3, 7, 8], "without": [3, 4, 7, 8], "all": [3, 5, 7, 8, 11, 12], "joe": [3, 8], "nelson": [3, 8], "doe": [3, 8], "fantast": [3, 8], "job": [3, 6, 8], "explain": [3, 8], "exactli": [3, 8], "shouldn": [3, 8], "fulli": [3, 8], "compliant": [3, 8], "rather": [3, 8], "than": [3, 4, 8, 12], "repeat": [3, 8], "hi": [3, 8], "fine": [3, 8], "here": [3, 8, 10, 12], "summari": [3, 5, 8], "retain": [3, 8], "origin": [3, 8, 12], "2369": [3, 8], "unsubscrib": [3, 8], "outgo": [3, 8, 12], "ad": [3, 6, 8, 12], "link": [3, 4, 7, 8], "2919": [3, 8], "id": [3, 8, 10, 12], "webmail": [3, 7, 8], "servic": [3, 4, 5, 7, 8], "gener": [3, 4, 6, 8, 10, 12], "button": [3, 8], "tradit": [3, 8], "disclaim": [3, 8], "addit": [3, 8], "compli": [3, 4, 6, 8, 9], "configur": [3, 4, 5, 6, 7, 8, 9], "action": [3, 8], "prefix": [3, 8], "still": [3, 6, 8, 10, 12], "tell": [3, 6, 7, 8], "came": [3, 8], "wa": [3, 4, 6, 8], "sent": [3, 8, 12], "post": [3, 8], "step": [3, 4, 8], "common": [3, 4, 6, 8], "platform": [3, 8], "below": [3, 8, 12], "navig": [3, 6, 8], "subject_prefix": [3, 8], "from_is_list": [3, 8], "No": [3, 8], "first_strip_reply_to": [3, 8], "reply_goes_to_list": [3, 8], "poster": [3, 8], "include_rfc2369_head": [3, 8], "ye": [3, 8], "include_list_post_head": [3, 8], "include_sender_head": [3, 8], "non": [3, 8, 12], "digest": [3, 8], "msg_header": [3, 8], "msg_footer": [3, 8], "scrub_nondigest": [3, 8], "privaci": [3, 6, 7, 8, 12], "filter": [3, 7, 8, 11], "dmarc_moderation_act": [3, 8], "accept": [3, 4, 8], "dmarc_quarantine_moderation_act": [3, 8], "dmarc_none_moderation_act": [3, 8], "ident": [3, 8, 12], "blank": [3, 8], "html": [3, 4, 8, 10], "plaintext": [3, 8], "rfc2369": [3, 8], "explicit": [3, 8], "first": [3, 6, 8, 12], "strip": [3, 8, 12], "replyto": [3, 8], "goe": [3, 8], "mung": [3, 8], "mitig": [3, 8], "uncondition": [3, 8], "templat": [3, 8], "unfortun": [3, 8], "postoriu": [3, 8], "admin": [3, 8, 12], "ui": [3, 8], "empti": [3, 8], "so": [3, 6, 7, 8, 12], "ll": [3, 8], "line": [3, 8], "touch": [3, 8], "var": [3, 8], "en": [3, 4, 8, 10], "member": [3, 8], "regular": [3, 8], "languag": [3, 8], "core": [3, 8], "16": [3, 8], "2017a": [3, 8], "higher": [3, 8], "rewrit": [3, 8], "enforc": [3, 8], "quarantin": [3, 8], "reject": [3, 8], "polici": [3, 8, 10, 12], "linux": [3, 6, 8], "go": [3, 8], "legal": [3, 8], "administr": [3, 8], "known": [3, 7, 8, 12], "longer": [3, 8], "wrap": [3, 8], "could": [3, 4, 8, 12], "interfer": [3, 8], "search": [3, 8, 12], "mobil": [3, 8], "On": [3, 4, 6, 7, 8], "hand": [3, 8], "caus": [3, 4, 7, 8], "accident": [3, 8], "entir": [3, 7, 8], "intend": [3, 8], "choos": [3, 8], "fit": [3, 8], "commun": [3, 8], "tab": [3, 4, 8], "page": [3, 4, 6, 7, 8], "visual": [4, 9], "dashboard": [4, 5, 9, 11], "later": [4, 6, 12], "debian": [4, 6], "ubuntu": [4, 6], "y": [4, 6], "transport": 4, "wget": 4, "qo": 4, "artifact": 4, "elast": [4, 5], "co": 4, "gpg": 4, "dearmor": 4, "usr": 4, "share": [4, 12], "keyr": 4, "echo": 4, "deb": 4, "x": [4, 10], "stabl": 4, "main": 4, "tee": 4, "d": 4, "For": [4, 12], "cento": [4, 6], "rhel": [4, 6], "rpm": 4, "guid": [4, 5], "previous": [4, 7], "jvm": 4, "heap": 4, "veri": [4, 7, 12], "small": 4, "1g": 4, "under": [4, 6, 7], "heavi": 4, "load": 4, "fix": 4, "increas": [4, 12], "minimum": 4, "maximum": 4, "depend": [4, 5, 12], "resourc": [4, 5, 12], "sure": [4, 6], "ha": [4, 7, 12], "least": [4, 6, 12], "gb": 4, "ram": 4, "assign": 4, "4": [4, 6, 11], "xms4g": 4, "xmx4g": 4, "www": [4, 6, 12], "refer": [4, 5], "import": [4, 7], "As": [4, 7], "7": [4, 6], "activ": [4, 6], "xpack": 4, "vim": 4, "yml": 4, "featur": 4, "enrol": 4, "encrypt": [4, 12], "logstash": 4, "agent": 4, "keystor": 4, "cert": 4, "p12": 4, "mutual": 4, "between": [4, 7], "cluster": [4, 12], "node": 4, "verification_mod": 4, "truststor": 4, "self": [4, 5], "openssl": 4, "req": 4, "x509": 4, "dai": [4, 9, 12], "newkei": 4, "rsa": 4, "4096": 4, "keyout": 4, "crt": 4, "Or": [4, 6], "csr": 4, "ca": 4, "fill": [4, 6], "prompt": 4, "fqdn": 4, "field": 4, "rm": 4, "f": 4, "place": [4, 7, 12], "mv": 4, "660": 4, "server_ip": 4, "publicbaseurl": 4, "connexion": 4, "9200": [4, 12], "5601": 4, "past": [4, 11], "verif": [4, 12], "put": [4, 12], "browser": 4, "setup": [4, 9, 12], "encryptedsavedobject": 4, "encryptionkei": 4, "xxxx": 4, "now": [4, 7], "parsedmarc": [4, 9, 10, 11], "right": [4, 7], "click": [4, 7], "export": 4, "ndjson": 4, "provid": [4, 7], "consol": [4, 12], "stack": 4, "manag": [4, 12], "hamburg": 4, "menu": [4, 7], "overwrit": 4, "restor": 4, "someon": 4, "els": 4, "permiss": [4, 12], "control": 4, "commerci": [4, 5], "pack": 4, "chang": [4, 7, 11, 12], "wai": [4, 7], "releas": [4, 6], "login": 4, "checkbox": 4, "dmarc_aggreg": 4, "dmarc_forens": 4, "conform": 4, "each": [4, 6, 9, 11, 12], "easi": [4, 9], "regul": [4, 6, 9, 12], "gdpr": [4, 9], "effici": 4, "help": 5, "maintain": 5, "develop": 5, "consid": [5, 7], "review": [5, 7], "how": 5, "contribut": 5, "assist": 5, "pin": 5, "particularli": [5, 12], "thank": [5, 10], "contributor": 5, "cli": 5, "util": 5, "kibana": [5, 11], "splunk": [5, 12], "opensearch": [5, 12], "grafana": 5, "altern": [5, 12], "agari": 5, "brand": [5, 7], "dmarcian": 5, "ondmarc": 5, "proofpoint": 5, "fraud": 5, "defens": 5, "valimail": 5, "draft": [5, 10], "rua": [5, 6], "failur": [5, 7, 10, 12], "ruf": [5, 6, 7, 12], "gmail": [5, 7, 12], "transpar": 5, "handl": [5, 12], "compress": 5, "structur": 5, "simpl": 5, "premad": [5, 11], "apach": 5, "kafka": [5, 12], "prerequisit": 5, "systemd": 5, "pattern": [5, 7], "retent": 5, "owa": 5, "ew": 5, "davmail": 5, "understand": [5, 7], "align": [5, 7, 10], "what": 5, "sender": [5, 7, 8], "won": 5, "t": [5, 8, 12], "dkim": [5, 7, 8, 10], "bug": 5, "tabl": [5, 7], "3": [6, 10, 11, 12], "anoth": [6, 12], "solut": 6, "two": 6, "mailto": 6, "uri": 6, "tag": 6, "comma": [6, 12], "behind": 6, "environ": 6, "detail": [6, 7], "http_proxi": 6, "prox": 6, "3128": 6, "https_proxi": 6, "ftp_proxi": 6, "credenti": [6, 12], "wide": [6, 10], "patch": 6, "2010": [6, 10], "rollup": 6, "22": 6, "kb4295699": 6, "2013": 6, "cumul": 6, "21": 6, "kb4099855": 6, "2016": 6, "11": [6, 10], "kb4134118": 6, "static": 6, "copi": [6, 11], "lite": 6, "databas": 6, "ipdb": 6, "distribut": 6, "term": 6, "creativ": 6, "attribut": 6, "intern": 6, "licens": 6, "fallback": 6, "geolite2": 6, "howev": 6, "cannot": 6, "tool": [6, 12], "locat": [6, 7], "overridden": 6, "buster": 6, "compon": 6, "contrib": 6, "repositori": [6, 11], "ppa": 6, "dnf": 6, "build": 6, "maco": 6, "window": 6, "decemb": 6, "30th": 6, "2019": 6, "free": 6, "account": [6, 7], "order": 6, "variou": 6, "regist": 6, "differ": [6, 7, 12], "older": [6, 10], "newer": 6, "Be": 6, "select": 6, "correct": 6, "v": [6, 12], "onc": 6, "pre": 6, "geoip": 6, "conf": 6, "systemdr": 6, "programdata": 6, "citi": 6, "asn": 6, "weekli": 6, "tuesdai": 6, "cron": 6, "schedul": 6, "task": 6, "python3": 6, "pip": 6, "virtualenv": 6, "dev": [6, 12], "libxml2": 6, "libxslt": 6, "python39": 6, "setuptool": 6, "devel": 6, "mkdir": 6, "b": [6, 10], "venv": [6, 12], "those": 6, "explicitli": 6, "9": 6, "insid": 6, "abl": 6, "libemail": 6, "friendli": 7, "incom": [7, 12], "switch": 7, "left": 7, "side": 7, "suggest": 7, "best": 7, "across": 7, "three": 7, "pie": 7, "chart": 7, "percentag": 7, "spf": [7, 10], "segment": 7, "malici": [7, 12], "just": 7, "especi": 7, "collect": [7, 12], "mai": [7, 12], "legitim": [7, 12], "correctli": 7, "while": [7, 12], "remain": 7, "often": 7, "rule": [7, 12], "wherea": 7, "reli": 7, "session": 7, "underneath": 7, "passag": 7, "disposit": [7, 10], "center": 7, "sort": [7, 12], "volum": 7, "By": [7, 12], "hover": 7, "mous": 7, "magnifi": 7, "glass": 7, "icon": 7, "our": 7, "recogn": 7, "market": 7, "plu": 7, "That": 7, "busi": 7, "particular": 7, "With": 7, "contact": 7, "lot": 7, "b2c": 7, "custom": [7, 12], "high": 7, "come": 7, "consum": 7, "googl": [7, 12], "yahoo": 7, "old": 7, "mention": 7, "earlier": 7, "similar": 7, "observ": 7, "who": 7, "addresse": 7, "parent": 7, "subsidiari": 7, "outdat": 7, "further": 7, "down": 7, "were": [7, 12], "call": 7, "been": [7, 12], "consolid": 7, "view": [7, 12], "own": [7, 11], "temporari": 7, "upper": 7, "These": 7, "recipi": 7, "avoid": 7, "leak": 7, "notabl": 7, "chines": 7, "suppli": [7, 12], "few": [7, 12], "doc": 9, "wiki": 10, "schema": 10, "7480": 10, "appendix": 10, "c": [10, 12], "produc": 10, "normal": [10, 12], "regardless": 10, "xml_schema": 10, "report_metadata": 10, "org_nam": 10, "acm": 10, "org_email": 10, "org_extra_contact_info": 10, "report_id": 10, "9391651994964116463": 10, "begin_d": 10, "2012": 10, "04": 10, "27": 10, "20": 10, "00": 10, "end_dat": 10, "28": 10, "19": 10, "59": 10, "policy_publish": 10, "adkim": 10, "aspf": 10, "pct": 10, "100": [10, 12], "fo": 10, "72": 10, "150": 10, "241": 10, "94": 10, "adsl": 10, "shv": 10, "bellsouth": 10, "base_domain": 10, "policy_evalu": 10, "policy_override_reason": 10, "identifi": 10, "header_from": 10, "envelope_from": 10, "envelope_to": 10, "null": 10, "auth_result": 10, "selector": 10, "scope": [10, 12], "mfrom": 10, "source_ip_address": 10, "source_countri": 10, "source_reverse_dn": 10, "source_base_domain": 10, "spf_align": 10, "dkim_align": 10, "dmarc_align": 10, "policy_override_com": 10, "dkim_domain": 10, "dkim_selector": 10, "dkim_result": 10, "spf_domain": 10, "spf_scope": 10, "spf_result": 10, "xennn": 10, "anonym": 10, "feedback_typ": 10, "user_ag": 10, "lua": 10, "original_mail_from": 10, "sharepoint": 10, "de": 10, "original_rcpt_to": 10, "peter": 10, "pan": 10, "arrival_d": 10, "mon": 10, "01": 10, "oct": 10, "2018": 10, "0200": 10, "message_id": 10, "38": 10, "e7": 10, "30937": 10, "bd6e1bb5": 10, "mailrelai": 10, "authentication_result": 10, "di": 10, "delivery_result": 10, "auth_failur": 10, "reported_domain": 10, "arrival_date_utc": 10, "09": 10, "authentication_mechan": 10, "original_envelope_id": 10, "sample_headers_onli": 10, "servernameon": 10, "n": [10, 12], "tby": 10, "cest": 10, "ndate": 10, "nmessag": 10, "nto": 10, "nfrom": 10, "utf": 10, "sw50zxjha3rpdmugv2v0dgjld2vyymvylcocymvyc2ljahq": 10, "nsubject": 10, "nmime": 10, "nx": 10, "mailer": 10, "foundat": 10, "ncontent": 10, "charset": 10, "transfer": 10, "quot": 10, "printabl": 10, "head": 10, "href": 10, "3d": 10, "nwettbewerb": 10, "doctyp": 10, "w3c": 10, "dtd": 10, "meta": 10, "08": 10, "0240": 10, "003": 10, "parsed_sampl": 10, "display_nam": 10, "interakt": 10, "wettbewerb": 10, "\u00fcbersicht": 10, "to_domain": 10, "timezon": 10, "mime": 10, "hop": 10, "date_utc": 10, "has_defect": 10, "reply_to": 10, "filename_safe_subject": 10, "organization_nam": 10, "inc": 10, "2024": 10, "09t00": 10, "00z": 10, "09t23": 10, "59z": 10, "00z_exampl": 10, "policy_domain": 10, "policy_typ": 10, "st": 10, "policy_str": 10, "stsv1": 10, "mx": 10, "max_ag": 10, "86400": 10, "successful_session_count": 10, "failed_session_count": 10, "failure_detail": 10, "result_typ": 10, "sending_mta_ip": 10, "209": 10, "85": 10, "222": 10, "201": 10, "receiving_ip": 10, "173": 10, "212": 10, "41": 10, "receiving_mx_hostnam": 10, "208": 10, "176": 10, "collector": [11, 12], "editor": 11, "occurr": 11, "layout": 11, "although": 11, "slightli": 11, "easier": 11, "flexibl": 11, "usag": 12, "h": 12, "config_fil": 12, "verbos": 12, "debug": 12, "log_fil": 12, "file_path": 12, "posit": 12, "argument": 12, "exit": 12, "silent": 12, "impli": 12, "write": 12, "print": 12, "warn": 12, "program": 12, "describ": 12, "comment": 12, "save_aggreg": 12, "save_forens": 12, "dmarcresport": 12, "upersecur": 12, "splunk_hec": 12, "splunkhec": 12, "hectokengoesher": 12, "s3": 12, "bucket": 12, "my": 12, "localhost": 12, "514": 12, "full": 12, "either": 12, "period": 12, "n_proc": 12, "chunk_siz": 12, "larger": 12, "improv": 12, "thousand": 12, "label": 12, "arriv": 12, "993": 12, "escap": 12, "wherev": 12, "section": 12, "recommend": 12, "try": 12, "skip_certificate_verif": 12, "skip": 12, "msgraph": 12, "auth_method": 12, "method": 12, "usernamepassword": 12, "devicecod": 12, "clientsecret": 12, "m365": 12, "client_id": 12, "app": 12, "registr": 12, "client_secret": 12, "secret": 12, "tenant_id": 12, "azur": 12, "tenant": 12, "token_fil": 12, "allow_unencrypted_storag": 12, "fall": 12, "back": 12, "unencrypt": 12, "grant": 12, "readwrit": 12, "deleg": 12, "applic": 12, "restrict": 12, "sinc": 12, "applicationaccesspolici": 12, "powershel": 12, "accessright": 12, "restrictaccess": 12, "appid": 12, "policyscopegroupid": 12, "special": 12, "cert_path": 12, "trust": 12, "appli": 12, "passsword": 12, "aggregate_top": 12, "topic": 12, "forensic_top": 12, "25": 12, "starttl": 12, "upload": 12, "region_nam": 12, "region": 12, "endpoint_url": 12, "endpoint": 12, "access_key_id": 12, "secret_access_kei": 12, "udp": 12, "gmail_api": 12, "credentials_fil": 12, "include_spam_trash": 12, "spam": 12, "trash": 12, "acquir": 12, "googleapi": 12, "oauth2_port": 12, "tcp": 12, "oauth2": 12, "8080": 12, "paginate_messag": 12, "per": 12, "log_analyt": 12, "resid": 12, "dce": 12, "ingest": 12, "dcr_immutable_id": 12, "immut": 12, "dcr": 12, "dcr_aggregate_stream": 12, "stream": 12, "dcr_forensic_stream": 12, "dcr_smtp_tls_stream": 12, "regard": 12, "strongli": 12, "much": 12, "faster": 12, "reliabl": 12, "cisco": 12, "opendn": 12, "outsid": 12, "instanc": 12, "highli": 12, "industri": 12, "sensit": 12, "healthcar": 12, "financ": 12, "possibl": 12, "appear": 12, "sometim": 12, "kind": 12, "approach": 12, "manual": 12, "1000": 12, "analyz": 12, "year": 12, "_cluster": 12, "health": 12, "pretti": 12, "active_primary_shard": 12, "932": 12, "active_shard": 12, "2k": 12, "persist": 12, "max_shards_per_nod": 12, "2000": 12, "watcher": 12, "io": 12}, "objects": {"": [[0, 0, 0, "-", "parsedmarc"]], "parsedmarc": [[0, 1, 1, "", "InvalidAggregateReport"], [0, 1, 1, "", "InvalidDMARCReport"], [0, 1, 1, "", "InvalidForensicReport"], [0, 1, 1, "", "InvalidSMTPTLSReport"], [0, 1, 1, "", "ParserError"], [0, 0, 0, "-", "elastic"], [0, 2, 1, "", "email_results"], [0, 2, 1, "", "extract_report"], [0, 2, 1, "", "get_dmarc_reports_from_mailbox"], [0, 2, 1, "", "get_dmarc_reports_from_mbox"], [0, 2, 1, "", "get_report_zip"], [0, 0, 0, "-", "opensearch"], [0, 2, 1, "", "parse_aggregate_report_file"], [0, 2, 1, "", "parse_aggregate_report_xml"], [0, 2, 1, "", "parse_forensic_report"], [0, 2, 1, "", "parse_report_email"], [0, 2, 1, "", "parse_report_file"], [0, 2, 1, "", "parse_smtp_tls_report_json"], [0, 2, 1, "", "parsed_aggregate_reports_to_csv"], [0, 2, 1, "", "parsed_aggregate_reports_to_csv_rows"], [0, 2, 1, "", "parsed_forensic_reports_to_csv"], [0, 2, 1, "", "parsed_forensic_reports_to_csv_rows"], [0, 2, 1, "", "parsed_smtp_tls_reports_to_csv"], [0, 2, 1, "", "parsed_smtp_tls_reports_to_csv_rows"], [0, 2, 1, "", "save_output"], [0, 0, 0, "-", "splunk"], [0, 0, 0, "-", "utils"], [0, 2, 1, "", "watch_inbox"]], "parsedmarc.elastic": [[0, 1, 1, "", "AlreadySaved"], [0, 1, 1, "", "ElasticsearchError"], [0, 2, 1, "", "create_indexes"], [0, 2, 1, "", "migrate_indexes"], [0, 2, 1, "", "save_aggregate_report_to_elasticsearch"], [0, 2, 1, "", "save_forensic_report_to_elasticsearch"], [0, 2, 1, "", "save_smtp_tls_report_to_elasticsearch"], [0, 2, 1, "", "set_hosts"]], "parsedmarc.opensearch": [[0, 1, 1, "", "AlreadySaved"], [0, 1, 1, "", "OpenSearchError"], [0, 2, 1, "", "create_indexes"], [0, 2, 1, "", "migrate_indexes"], [0, 2, 1, "", "save_aggregate_report_to_opensearch"], [0, 2, 1, "", "save_forensic_report_to_opensearch"], [0, 2, 1, "", "save_smtp_tls_report_to_opensearch"], [0, 2, 1, "", "set_hosts"]], "parsedmarc.splunk": [[0, 3, 1, "", "HECClient"], [0, 1, 1, "", "SplunkError"]], "parsedmarc.splunk.HECClient": [[0, 4, 1, "", "save_aggregate_reports_to_splunk"], [0, 4, 1, "", "save_forensic_reports_to_splunk"], [0, 4, 1, "", "save_smtp_tls_reports_to_splunk"]], "parsedmarc.utils": [[0, 1, 1, "", "DownloadError"], [0, 1, 1, "", "EmailParserError"], [0, 2, 1, "", "convert_outlook_msg"], [0, 2, 1, "", "decode_base64"], [0, 2, 1, "", "get_base_domain"], [0, 2, 1, "", "get_filename_safe_string"], [0, 2, 1, "", "get_ip_address_country"], [0, 2, 1, "", "get_ip_address_info"], [0, 2, 1, "", "get_reverse_dns"], [0, 2, 1, "", "human_timestamp_to_datetime"], [0, 2, 1, "", "human_timestamp_to_unix_timestamp"], [0, 2, 1, "", "is_mbox"], [0, 2, 1, "", "is_outlook_msg"], [0, 2, 1, "", "parse_email"], [0, 2, 1, "", "query_dns"], [0, 2, 1, "", "timestamp_to_datetime"], [0, 2, 1, "", "timestamp_to_human"]]}, "objtypes": {"0": "py:module", "1": "py:exception", "2": "py:function", "3": "py:class", "4": "py:method"}, "objnames": {"0": ["py", "module", "Python module"], "1": ["py", "exception", "Python exception"], "2": ["py", "function", "Python function"], "3": ["py", "class", "Python class"], "4": ["py", "method", "Python method"]}, "titleterms": {"api": 0, "refer": 0, "parsedmarc": [0, 1, 2, 5, 6, 12], "elast": 0, "opensearch": [0, 9], "splunk": [0, 11], "util": 0, "indic": 0, "tabl": 0, "contribut": 1, "bug": 1, "report": [1, 5, 6, 10], "access": 2, "an": 2, "inbox": 2, "us": [2, 6, 7, 12], "owa": 2, "ew": 2, "run": [2, 12], "davmail": 2, "systemd": [2, 12], "servic": [2, 12], "configur": [2, 12], "understand": 3, "dmarc": [3, 5, 7], "resourc": 3, "guid": 3, "spf": 3, "record": [3, 4, 9], "valid": 3, "lookalik": 3, "domain": 3, "align": 3, "what": [3, 8], "sender": 3, "won": 3, "t": 3, "support": 3, "dkim": 3, "about": [3, 8], "mail": [3, 8], "list": [3, 8], "best": [3, 8], "practic": [3, 8], "do": [3, 8], "mailman": [3, 8], "2": [3, 8], "3": [3, 8], "listserv": [3, 8], "workaround": [3, 8], "elasticsearch": 4, "kibana": [4, 7], "instal": [4, 6, 9], "upgrad": 4, "index": 4, "pattern": 4, "retent": [4, 9], "document": 5, "open": 5, "sourc": 5, "analyz": [5, 6], "visual": 5, "featur": 5, "content": 5, "prerequisit": 6, "test": 6, "multipl": 6, "web": 6, "proxi": 6, "microsoft": 6, "exchang": 6, "geoipupd": 6, "setup": 6, "option": 6, "depend": 6, "dashboard": 7, "summari": 7, "forens": [7, 10], "sampl": [7, 10], "grafana": 9, "output": 10, "aggreg": 10, "json": 10, "csv": 10, "smtp": 10, "tl": 10, "cli": 12, "help": 12, "file": 12}, "envversion": {"sphinx.domains.c": 2, "sphinx.domains.changeset": 1, "sphinx.domains.citation": 1, "sphinx.domains.cpp": 8, "sphinx.domains.index": 1, "sphinx.domains.javascript": 2, "sphinx.domains.math": 2, "sphinx.domains.python": 3, "sphinx.domains.rst": 2, "sphinx.domains.std": 2, "sphinx.ext.todo": 2, "sphinx.ext.viewcode": 1, "sphinx": 57}, "alltitles": {"API reference": [[0, "api-reference"]], "parsedmarc": [[0, "module-parsedmarc"]], "parsedmarc.elastic": [[0, "module-parsedmarc.elastic"]], "parsedmarc.opensearch": [[0, "module-parsedmarc.opensearch"]], "parsedmarc.splunk": [[0, "module-parsedmarc.splunk"]], "parsedmarc.utils": [[0, "module-parsedmarc.utils"]], "Indices and tables": [[0, "indices-and-tables"]], "Contributing to parsedmarc": [[1, "contributing-to-parsedmarc"]], "Bug reports": [[1, "bug-reports"]], "Accessing an inbox using OWA/EWS": [[2, "accessing-an-inbox-using-owa-ews"]], "Running DavMail as a systemd service": [[2, "running-davmail-as-a-systemd-service"]], "Configuring parsedmarc for DavMail": [[2, "configuring-parsedmarc-for-davmail"]], "Understanding DMARC": [[3, "understanding-dmarc"]], "Resources": [[3, "resources"]], "DMARC guides": [[3, "dmarc-guides"]], "SPF and DMARC record validation": [[3, "spf-and-dmarc-record-validation"]], "Lookalike domains": [[3, "lookalike-domains"]], "DMARC Alignment Guide": [[3, "dmarc-alignment-guide"]], "What if a sender won\u2019t support DKIM/DMARC?": [[3, "what-if-a-sender-wont-support-dkim-dmarc"]], "What about mailing lists?": [[3, "what-about-mailing-lists"], [8, "what-about-mailing-lists"]], "Mailing list best practices": [[3, "mailing-list-best-practices"], [8, "mailing-list-best-practices"]], "Do": [[3, "do"], [8, "do"]], "Do not": [[3, "do-not"], [8, "do-not"]], "Mailman 2": [[3, "mailman-2"], [3, "id1"], [8, "mailman-2"], [8, "id1"]], "Mailman 3": [[3, "mailman-3"], [3, "id2"], [8, "mailman-3"], [8, "id2"]], "LISTSERV": [[3, "listserv"], [8, "listserv"]], "Workarounds": [[3, "workarounds"], [8, "workarounds"]], "Elasticsearch and Kibana": [[4, "elasticsearch-and-kibana"]], "Installation": [[4, "installation"], [6, "installation"], [9, "installation"]], "Upgrading Kibana index patterns": [[4, "upgrading-kibana-index-patterns"]], "Records retention": [[4, "records-retention"], [9, "records-retention"]], "parsedmarc documentation - Open source DMARC report analyzer and visualizer": [[5, "parsedmarc-documentation-open-source-dmarc-report-analyzer-and-visualizer"]], "Features": [[5, "features"]], "Contents": [[5, null]], "Prerequisites": [[6, "prerequisites"]], "Testing multiple report analyzers": [[6, "testing-multiple-report-analyzers"]], "Using a web proxy": [[6, "using-a-web-proxy"]], "Using Microsoft Exchange": [[6, "using-microsoft-exchange"]], "geoipupdate setup": [[6, "geoipupdate-setup"]], "Installing parsedmarc": [[6, "installing-parsedmarc"]], "Optional dependencies": [[6, "optional-dependencies"]], "Using the Kibana dashboards": [[7, "using-the-kibana-dashboards"]], "DMARC Summary": [[7, "dmarc-summary"]], "DMARC Forensic Samples": [[7, "dmarc-forensic-samples"]], "OpenSearch and Grafana": [[9, "opensearch-and-grafana"]], "Sample outputs": [[10, "sample-outputs"]], "Sample aggregate report output": [[10, "sample-aggregate-report-output"]], "JSON aggregate report": [[10, "json-aggregate-report"]], "CSV aggregate report": [[10, "csv-aggregate-report"]], "Sample forensic report output": [[10, "sample-forensic-report-output"]], "JSON forensic report": [[10, "json-forensic-report"]], "CSV forensic report": [[10, "csv-forensic-report"]], "JSON SMTP TLS report": [[10, "json-smtp-tls-report"]], "Splunk": [[11, "splunk"]], "Using parsedmarc": [[12, "using-parsedmarc"]], "CLI help": [[12, "cli-help"]], "Configuration file": [[12, "configuration-file"]], "Running parsedmarc as a systemd service": [[12, "running-parsedmarc-as-a-systemd-service"]]}, "indexentries": {"alreadysaved": [[0, "parsedmarc.elastic.AlreadySaved"], [0, "parsedmarc.opensearch.AlreadySaved"]], "downloaderror": [[0, "parsedmarc.utils.DownloadError"]], "elasticsearcherror": [[0, "parsedmarc.elastic.ElasticsearchError"]], "emailparsererror": [[0, "parsedmarc.utils.EmailParserError"]], "hecclient (class in parsedmarc.splunk)": [[0, "parsedmarc.splunk.HECClient"]], "invalidaggregatereport": [[0, "parsedmarc.InvalidAggregateReport"]], "invaliddmarcreport": [[0, "parsedmarc.InvalidDMARCReport"]], "invalidforensicreport": [[0, "parsedmarc.InvalidForensicReport"]], "invalidsmtptlsreport": [[0, "parsedmarc.InvalidSMTPTLSReport"]], "opensearcherror": [[0, "parsedmarc.opensearch.OpenSearchError"]], "parsererror": [[0, "parsedmarc.ParserError"]], "splunkerror": [[0, "parsedmarc.splunk.SplunkError"]], "convert_outlook_msg() (in module parsedmarc.utils)": [[0, "parsedmarc.utils.convert_outlook_msg"]], "create_indexes() (in module parsedmarc.elastic)": [[0, "parsedmarc.elastic.create_indexes"]], "create_indexes() (in module parsedmarc.opensearch)": [[0, "parsedmarc.opensearch.create_indexes"]], "decode_base64() (in module parsedmarc.utils)": [[0, "parsedmarc.utils.decode_base64"]], "email_results() (in module parsedmarc)": [[0, "parsedmarc.email_results"]], "extract_report() (in module parsedmarc)": [[0, "parsedmarc.extract_report"]], "get_base_domain() (in module parsedmarc.utils)": [[0, "parsedmarc.utils.get_base_domain"]], "get_dmarc_reports_from_mailbox() (in module parsedmarc)": [[0, "parsedmarc.get_dmarc_reports_from_mailbox"]], "get_dmarc_reports_from_mbox() (in module parsedmarc)": [[0, "parsedmarc.get_dmarc_reports_from_mbox"]], "get_filename_safe_string() (in module parsedmarc.utils)": [[0, "parsedmarc.utils.get_filename_safe_string"]], "get_ip_address_country() (in module parsedmarc.utils)": [[0, "parsedmarc.utils.get_ip_address_country"]], "get_ip_address_info() (in module parsedmarc.utils)": [[0, "parsedmarc.utils.get_ip_address_info"]], "get_report_zip() (in module parsedmarc)": [[0, "parsedmarc.get_report_zip"]], "get_reverse_dns() (in module parsedmarc.utils)": [[0, "parsedmarc.utils.get_reverse_dns"]], "human_timestamp_to_datetime() (in module parsedmarc.utils)": [[0, "parsedmarc.utils.human_timestamp_to_datetime"]], "human_timestamp_to_unix_timestamp() (in module parsedmarc.utils)": [[0, "parsedmarc.utils.human_timestamp_to_unix_timestamp"]], "is_mbox() (in module parsedmarc.utils)": [[0, "parsedmarc.utils.is_mbox"]], "is_outlook_msg() (in module parsedmarc.utils)": [[0, "parsedmarc.utils.is_outlook_msg"]], "migrate_indexes() (in module parsedmarc.elastic)": [[0, "parsedmarc.elastic.migrate_indexes"]], "migrate_indexes() (in module parsedmarc.opensearch)": [[0, "parsedmarc.opensearch.migrate_indexes"]], "module": [[0, "module-parsedmarc"], [0, "module-parsedmarc.elastic"], [0, "module-parsedmarc.opensearch"], [0, "module-parsedmarc.splunk"], [0, "module-parsedmarc.utils"]], "parse_aggregate_report_file() (in module parsedmarc)": [[0, "parsedmarc.parse_aggregate_report_file"]], "parse_aggregate_report_xml() (in module parsedmarc)": [[0, "parsedmarc.parse_aggregate_report_xml"]], "parse_email() (in module parsedmarc.utils)": [[0, "parsedmarc.utils.parse_email"]], "parse_forensic_report() (in module parsedmarc)": [[0, "parsedmarc.parse_forensic_report"]], "parse_report_email() (in module parsedmarc)": [[0, "parsedmarc.parse_report_email"]], "parse_report_file() (in module parsedmarc)": [[0, "parsedmarc.parse_report_file"]], "parse_smtp_tls_report_json() (in module parsedmarc)": [[0, "parsedmarc.parse_smtp_tls_report_json"]], "parsed_aggregate_reports_to_csv() (in module parsedmarc)": [[0, "parsedmarc.parsed_aggregate_reports_to_csv"]], "parsed_aggregate_reports_to_csv_rows() (in module parsedmarc)": [[0, "parsedmarc.parsed_aggregate_reports_to_csv_rows"]], "parsed_forensic_reports_to_csv() (in module parsedmarc)": [[0, "parsedmarc.parsed_forensic_reports_to_csv"]], "parsed_forensic_reports_to_csv_rows() (in module parsedmarc)": [[0, "parsedmarc.parsed_forensic_reports_to_csv_rows"]], "parsed_smtp_tls_reports_to_csv() (in module parsedmarc)": [[0, "parsedmarc.parsed_smtp_tls_reports_to_csv"]], "parsed_smtp_tls_reports_to_csv_rows() (in module parsedmarc)": [[0, "parsedmarc.parsed_smtp_tls_reports_to_csv_rows"]], "parsedmarc": [[0, "module-parsedmarc"]], "parsedmarc.elastic": [[0, "module-parsedmarc.elastic"]], "parsedmarc.opensearch": [[0, "module-parsedmarc.opensearch"]], "parsedmarc.splunk": [[0, "module-parsedmarc.splunk"]], "parsedmarc.utils": [[0, "module-parsedmarc.utils"]], "query_dns() (in module parsedmarc.utils)": [[0, "parsedmarc.utils.query_dns"]], "save_aggregate_report_to_elasticsearch() (in module parsedmarc.elastic)": [[0, "parsedmarc.elastic.save_aggregate_report_to_elasticsearch"]], "save_aggregate_report_to_opensearch() (in module parsedmarc.opensearch)": [[0, "parsedmarc.opensearch.save_aggregate_report_to_opensearch"]], "save_aggregate_reports_to_splunk() (parsedmarc.splunk.hecclient method)": [[0, "parsedmarc.splunk.HECClient.save_aggregate_reports_to_splunk"]], "save_forensic_report_to_elasticsearch() (in module parsedmarc.elastic)": [[0, "parsedmarc.elastic.save_forensic_report_to_elasticsearch"]], "save_forensic_report_to_opensearch() (in module parsedmarc.opensearch)": [[0, "parsedmarc.opensearch.save_forensic_report_to_opensearch"]], "save_forensic_reports_to_splunk() (parsedmarc.splunk.hecclient method)": [[0, "parsedmarc.splunk.HECClient.save_forensic_reports_to_splunk"]], "save_output() (in module parsedmarc)": [[0, "parsedmarc.save_output"]], "save_smtp_tls_report_to_elasticsearch() (in module parsedmarc.elastic)": [[0, "parsedmarc.elastic.save_smtp_tls_report_to_elasticsearch"]], "save_smtp_tls_report_to_opensearch() (in module parsedmarc.opensearch)": [[0, "parsedmarc.opensearch.save_smtp_tls_report_to_opensearch"]], "save_smtp_tls_reports_to_splunk() (parsedmarc.splunk.hecclient method)": [[0, "parsedmarc.splunk.HECClient.save_smtp_tls_reports_to_splunk"]], "set_hosts() (in module parsedmarc.elastic)": [[0, "parsedmarc.elastic.set_hosts"]], "set_hosts() (in module parsedmarc.opensearch)": [[0, "parsedmarc.opensearch.set_hosts"]], "timestamp_to_datetime() (in module parsedmarc.utils)": [[0, "parsedmarc.utils.timestamp_to_datetime"]], "timestamp_to_human() (in module parsedmarc.utils)": [[0, "parsedmarc.utils.timestamp_to_human"]], "watch_inbox() (in module parsedmarc)": [[0, "parsedmarc.watch_inbox"]]}}) \ No newline at end of file diff --git a/splunk.html b/splunk.html index d9c1af87..f9073a9a 100644 --- a/splunk.html +++ b/splunk.html @@ -4,7 +4,7 @@ - Splunk — parsedmarc 8.7.0 documentation + Splunk — parsedmarc 8.8.0 documentation @@ -38,7 +38,7 @@ parsedmarc
              - 8.7.0 + 8.8.0
              @@ -54,6 +54,7 @@
            • Using parsedmarc
            • Sample outputs
            • Elasticsearch and Kibana
            • +
            • OpenSearch and Grafana
            • Using the Kibana dashboards
            • Splunk
            • Accessing an inbox using OWA/EWS
            • diff --git a/usage.html b/usage.html index c3f29dd8..561f6e4a 100644 --- a/usage.html +++ b/usage.html @@ -4,7 +4,7 @@ - Using parsedmarc — parsedmarc 8.7.0 documentation + Using parsedmarc — parsedmarc 8.8.0 documentation @@ -38,7 +38,7 @@ parsedmarc
              - 8.7.0 + 8.8.0
              @@ -59,6 +59,7 @@
            • Sample outputs
            • Elasticsearch and Kibana
            • +
            • OpenSearch and Grafana
            • Using the Kibana dashboards
            • Splunk
            • Accessing an inbox using OWA/EWS
            • @@ -171,6 +172,10 @@

              Configuration filehosts = 127.0.0.1:9200 ssl = False +[opensearch] +hosts = https://admin:admin@127.0.0.1:9200 +ssl = True + [splunk_hec] url = https://splunkhec.example.com token = HECTokenGoesHere @@ -342,6 +347,32 @@

              Configuration file0)

              +
            • opensearch

              +
              +
            • splunk_hec

              • url - str: The URL of the Splunk HTTP Events Collector (HEC)