Small Python script to quick test DMARCDKIM and SPF records

Table of contents

  1. DMARC, DKIM and SPF
    1. Script banner
    2. DMARC test
    3. DKIM Test
    4. SPF test
  2. Test in Windows Subsystem for Linux
  3. Source code on Github

DMARC, DKIM and SPF

For a given occasion I wrote Small Python script to test a domain for DMARC, DKIM and SPF records. Those records are managed in a DNS zone and are typically used in Anti-SPAM techniques.

DKIM requires a so-called DKIM Selector, which can be extracted from the header of an email sent to yourself (or of any other email).

It’s possible to use dig and query those records manually, but for repeating tests I prefer one simple command line tool which do those three test in one go.

For Python, the nice toolkit dnspython exists to do all the DNS query work. I’m importing this toolkit and argparse in my script. The script gets a nice ASCII banner because ASCII banners are cool ;)


    #!/usr/bin/python3
    import argparse
    import dns.resolver

    print ("______ ___  ___  ___  ______  _____   ______  _   __ _____ ___  ___   _____ ______ ______ ")
    print ("|  _  \|  \/  | / _ \ | ___ \/  __ \  |  _  \| | / /|_   _||  \/  |  /  ___|| ___ \|  ___|")
    print ("| | | || .  . |/ /_\ \| |_/ /| /  \/  | | | || |/ /   | |  | .  . |  \ `--. | |_/ /| |_   ")
    print ("| | | || |\/| ||  _  ||    / | |      | | | ||    \   | |  | |\/| |   `--. \|  __/ |  _|  ")
    print ("| |/ / | |  | || | | || |\ \ | \__/\  | |/ / | |\  \ _| |_ | |  | |  /\__/ /| |    | |    ")
    print ("|___/  \_|  |_/\_| |_/\_| \_| \____/  |___/  \_| \_/ \___/ \_|  |_/  \____/ \_|    \_|    ")
    print ("                                               |  _        '   _  |     |_   _   ,_  |_ ")
    print ("            Copyright (C) 2021 Stefan Thierolf | (_|  (_)  |  (_  |<    |_  (/_  _\  |_ ")
    print ("                                 License GPLv3 |   |                                    ")
    print ()

    parser = argparse.ArgumentParser(description='Simple DMARC DKIM SPF quick test.')
    parser.add_argument('domain', help='Domain name to test')
    parser.add_argument('selector', help='DKIM Selector, can be extracted from email')
    args = parser.parse_args()
    domain = args.domain
    selector = args.selector

DMARC test

This is the first test case which tests for the DMARC record. The test tries to resolve the _dmarc.domain.tldTXT record in DNS. In the returned DNS data the script looks for the string DMARC1. If the string exists, the test is PASSED, if not the test if FAILED.


    #
    # Testing DMARC
    #
    print()
    print ("Testing domain", domain, "for DMARC record...")
    try:
      test_dmarc = dns.resolver.resolve('_dmarc.' + domain , 'TXT')
      for dns_data in test_dmarc:
        if 'DMARC1' in str(dns_data):
          print ("  [PASS] DMARC record found :",dns_data)
    except:
      print ("  [FAIL] DMARC record not found.")
      pass

DKIM Test

Similar like for DMARC the script tests for DKIM. The so-called DKIM Selector must be extracted from the email headers. This test tries to resolve [selector]._domainkey.domain.tld. The returned DNS data is then checked for the string DKIM1.


    #
    # Testing DKIM
    #
    print()
    print ("Testing domain", domain, "for DKIM record with selector", selector, "...")
    try:
      test_dkim = dns.resolver.resolve(selector + '._domainkey.' + domain , 'TXT')
      for dns_data in test_dkim:
        if 'DKIM1' in str(dns_data):
          print ("  [PASS] DKIM record found  :",dns_data)
    except:
      print ("  [FAIL] DKIM record not found.")
      pass

SPF test

The test for SPF record is performed in the same way. In the returned DNS data the script looks for the string spf1. If the string was found, the test is PASSED, if not the test is FAILED.


    #
    # Testing SPF
    #
    print()
    print ("Testing domain", domain, "for SPF record...")
    try:
      test_spf = dns.resolver.resolve(domain , 'TXT')
      for dns_data in test_spf:
        if 'spf1' in str(dns_data):
          print ("  [PASS] SPF record found   :",dns_data)
    except:
      print ("  [FAIL] SPF record not found.")
      pass

Test in Windows Subsystem for Linux

As test I checked if the script is running in Windows Subsystem for Linux. As domain I tested microsoft.com with their DKIM selector selector2. The result showed that all three testes are passed and the records are shown. A test against another domain showed failed for DKIM and DMARC, but passed for SPF.

dds-quick-test.py running in WSL2 to check microsoft.com

Source code on Github

You will find the script on my GitHub repo published at dds-quick-test.py