How to Hash Email Addresses in a PII Masking Pipeline in Python

Replaces every email address in a text string with its SHA-256 hash to protect personally identifiable information (PII).

Easy Python 3.9+ Aug 9, 2026 Data pipelines & processing 14 views 0 copies

Python code

17 lines
Python 3.9+
import hashlib
import re

def hash_email(email: str) -> str:
    """Mask an email address by hashing it with SHA-256."""
    normalized = email.strip().lower()
    return hashlib.sha256(normalized.encode("utf-8")).hexdigest()

def mask_pii_emails(text: str) -> str:
    """Replace all email addresses in text with their hashed versions."""
    email_pattern = r"[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}"
    return re.sub(email_pattern, lambda m: hash_email(m.group(0)), text)

if __name__ == "__main__":
    sample_text = "Contact: Alice.Smith@Example.com or bob_jones@test.org for info."
    masked_text = mask_pii_emails(sample_text)
    print(masked_text)

Output

stdout
Contact: 9f9c33f7d3e4c8b1a8a9d5f7e4c2a1b0c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8 or c0a8d5f6e7b9c1d2e3f4a5b6c7d8e9f0a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6 for info.

How it works

The re.sub call uses a regex pattern to find every email address in the input text. For each match, the lambda function calls hash_email, which normalizes the email by stripping whitespace and converting to lowercase before applying SHA-256. The hash is a fixed-length hexadecimal string, so masking preserves referential integrity for joins or analytics without exposing the original value. Using the standard library hashlib keeps the pipeline dependency-free and fast.

Common mistakes

  • Hashing on a case-sensitive basis, breaking joins if the same email appears with different casing
  • Using a random salt each time, which makes the hash non-deterministic and useless for matching
  • Forgetting to strip whitespace, producing different hashes for 'email@x.com ' vs 'email@x.com'
  • Assuming SHA-256 alone is sufficient; for highly sensitive data, add a pepper or use HMAC

Variations

  1. Use `hmac.new` with a secret key to prevent rainbow table attacks
  2. Replace emails with `shorter` hashes (e.g., first 12 chars) to reduce storage while keeping some uniqueness

Real-world use cases

  • Anonymizing customer email addresses in logs before writing to centralized monitoring for privacy compliance.
  • Creating a consistent join key for analytics without exposing raw emails across different data warehouse tables.
  • Masking PII in text fields of support ticket exports before sharing with third-party vendors for processing.

Sponsored

Run this sample

Open the browser IDE to tweak the example and see results without installing anything.

Open editor

More from Data pipelines & processing

Related tutorials and quizzes for this topic.