{"id":8959,"library":"dkimpy","title":"DKIMpy: DKIM, ARC, and TLSRPT email signing and verification","description":"DKIMpy is a Python library for creating and verifying DKIM (DomainKeys Identified Mail), ARC (Authenticated Receive Chain), and TLSRPT (TLS Report) signatures on email messages. It provides a robust implementation for email authentication, relying on cryptographic operations and DNS lookups. The current version is 1.1.8, and it maintains a stable release cadence with updates addressing security and compatibility.","status":"active","version":"1.1.8","language":"python","source_language":"en","source_url":"https://github.com/sdgathman/dkimpy","tags":["email","dkim","arc","tlsrpt","security","cryptography","authentication"],"install":[{"cmd":"pip install dkimpy","lang":"bash","label":"Install stable version"}],"dependencies":[{"reason":"Core cryptographic operations for signing and verification.","package":"cryptography","optional":false},{"reason":"Required for performing DNS lookups to retrieve public keys during verification.","package":"dnspython","optional":false},{"reason":"Provides additional cryptographic primitives.","package":"pycryptodomex","optional":false},{"reason":"Often used alongside DKIM for generating Authentication-Results headers.","package":"authres","optional":true}],"imports":[{"wrong":"from dkimpy.dkim import DKIM","symbol":"DKIM","correct":"from dkim import DKIM"}],"quickstart":{"code":"import os\nfrom dkimpy.dkim import DKIM, verify, DKIMException\n\n# In a real application, load your actual private key and use your domain/selector.\n# Example key generation (using openssl):\n#   openssl genrsa -out dkim.private 1024\n#   openssl rsa -in dkim.private -pubout -out dkim.public\n# Then load: `with open('dkim.private', 'rb') as f: private_key = f.read()`\nprivate_key = os.environ.get('DKIM_PRIVATE_KEY', b\"\") # Should be bytes\ndomain = os.environ.get('DKIM_DOMAIN', 'example.com')\nselector = os.environ.get('DKIM_SELECTOR', 's1')\n\n# Sample email content (bytes) - DKIMpy works with byte strings\nemail_message_bytes = b\"\"\"From: sender@example.com\\r\\nTo: recipient@example.com\\r\\nSubject: Test DKIM Signature\\r\\n\\r\\nThis is the body of the email.\\r\\n\"\"\"\n\n# --- 1. Sign an email ---\nprint(\"--- Signing an Email ---\")\nif not private_key:\n    print(\"Warning: DKIM_PRIVATE_KEY environment variable not set. Signing will likely fail.\")\n    print(\"Please provide a valid private key for real signing.\")\n\ntry:\n    # Initialize the DKIM signer\n    signer = DKIM(\n        message=email_message_bytes,\n        selector=selector.encode(), # Selector must be bytes\n        domain=domain.encode(),     # Domain must be bytes\n        privkey=private_key\n    )\n    \n    # Sign the message\n    signed_email_bytes = signer.sign()\n    print(\"Email signed successfully. First 500 bytes of signed email:\")\n    print(signed_email_bytes[:500].decode(errors='ignore'))\n    print(\"...\")\n\nexcept DKIMException as e:\n    print(f\"Error signing email: {e}\")\nexcept Exception as e:\n    print(f\"An unexpected error occurred during signing: {e}\")\n\n\n# --- 2. Verify a received email ---\n# For actual verification, the signed email needs to be received, and\n# dkimpy will perform DNS lookups for the public key (TXT record).\nprint(\"\\n--- Verification Example (requires real signed email and DNS) ---\")\nreceived_signed_email_bytes = signed_email_bytes # Use the just-signed email for demonstration\n\ntry:\n    # The `verify` function is a module-level function\n    # It returns a list of (dkim_domain, dkim_selector, ...) tuples for each valid signature.\n    result = verify(received_signed_email_bytes)\n    \n    if result:\n        print(f\"Verification successful. Found {len(result)} valid DKIM signatures.\")\n        # print(f\"Result details: {result}\") # Uncomment for verbose output\n    else:\n        print(\"Verification failed or no valid DKIM-Signature found.\")\n\nexcept DKIMException as e:\n    print(f\"Verification encountered an error: {e}\")\nexcept Exception as e:\n    print(f\"An unexpected error occurred during verification: {e}\")","lang":"python","description":"This quickstart demonstrates how to sign an email using `dkimpy.dkim.DKIM` and how to initiate verification using `dkimpy.dkim.verify`. For actual signing, a private key (bytes) and a domain/selector (bytes) are required. Full verification relies on accurate DNS TXT records for the public key, which `dkimpy` will query automatically."},"warnings":[{"fix":"Migrate your code to Python 3 and update call signatures and data types (e.g., using byte strings for email content and keys instead of unicode).","message":"Version 1.0.0 introduced a major rewrite, making it incompatible with Python 2. Code written for `dkimpy` prior to 1.0.0 will likely break when upgrading to Python 3 with `dkimpy>=1.0.0`.","severity":"breaking","affected_versions":"<1.0.0"},{"fix":"Ensure all string-like inputs are explicitly encoded to bytes using `.encode('utf-8')` or similar, e.g., `b'example.com'`, `b's1'`.","message":"All email content, keys, domain, and selector parameters must be byte strings (`bytes`), not unicode strings (`str`). Passing `str` will lead to `TypeError` or unexpected encoding issues.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Ensure your environment has working DNS resolution. For verification failures, check the domain's DKIM DNS TXT records (`selector._domainkey.example.com`) and confirm they contain a valid public key (p= tag).","message":"DKIM verification heavily relies on successful DNS lookups to retrieve the public key. Network issues, misconfigured DNS records (TXT records), or DNSSEC failures can cause verification to fail.","severity":"gotcha","affected_versions":"All"},{"fix":"Ensure your private key is in PEM format. You can often convert keys using `openssl` if needed.","message":"The private key must be in PEM format. Other formats (e.g., DER) are not directly supported and will result in `cryptography.exceptions.InvalidKey` or other decryption errors.","severity":"gotcha","affected_versions":"All"}],"env_vars":null,"search_vec":"'1.1.8':54 'address':64 'arc':3,23,70 'authent':24,42,74 'cadenc':61 'chain':26 'compat':67 'creat':16 'cryptograph':45 'cryptographi':73 'current':51 'dkim':2,19,69 'dkimpi':1,10 'dns':48 'domainkey':20 'email':6,33,41,68 'identifi':21 'implement':39 'librari':14 'lookup':49 'mail':22 'maintain':57 'messag':34 'oper':46 'provid':36 'python':13 'receiv':25 'releas':60 'reli':43 'report':30 'robust':38 'secur':65,72 'sign':7 'signatur':31 'stabl':59 'tls':29 'tlsrpt':5,28,71 'updat':63 'verif':9 'verifi':18 'version':52","created_at":"2026-04-16T18:47:44.607193+00:00","updated_at":"2026-04-16T18:47:44.607193+00:00","problems":null,"ecosystem":"pypi","meta_description":null,"install_score":null,"quickstart_score":null,"quickstart_tag":null,"pypi_latest":"1.1.8","cli_name":"dkimpy","cli_version":"sh: 1: dkimpy: not found","type":"library","homepage":"https://launchpad.net/dkimpy","github":null,"docs":null,"changelog":null,"pypi":"https://pypi.org/project/dkimpy/","npm":null,"openapi_spec":null,"status_page":null,"smithery":null,"categories":["auth-security","communication"],"base_url":null,"auth_type":null,"provenance":{"verified_status":"passing","verified_at":"2026-06-30","last_verified":"2026-06-30","next_check":"2026-07-30","install_tag":null}}