#!/usr/bin/env python3 # Copyright (C) 2020 Agilent Technologies, Inc. # Author: Chris Laplante # This sendemail-validate hook injects 'From: ' header lines into outgoing # emails sent via 'git send-email', to ensure that accurate commit authorship # information is present. It was created because some email servers # (notably Microsoft Exchange / Office 360) seem to butcher outgoing patches, # resulting in incorrect authorship. # Current limitations: # 1. Assumes one per patch per email # 2. Minimal error checking # # Installation: # 1. Copy to .git/hooks/sendemail-validate # 2. chmod +x .git/hooks/sendemail-validate import enum import re import subprocess import sys class Subject(enum.IntEnum): NOT_SEEN = 0 CONSUMING = 1 SEEN = 2 def make_from_line(): cmd = ["git", "var", "GIT_COMMITTER_IDENT"] proc = subprocess.run(cmd, check=True, stdout=subprocess.PIPE, universal_newlines=True) regex = re.compile(r"^(.*>).*$") match = regex.match(proc.stdout) assert match is not None return "From: {0}".format(match.group(1)) def main(): email = sys.argv[1] with open(email, "r") as f: email_lines = f.read().split("\n") subject_seen = Subject.NOT_SEEN first_body_line = None for i, line in enumerate(email_lines): if (subject_seen == Subject.NOT_SEEN) and line.startswith("Subject: "): subject_seen = Subject.CONSUMING continue if subject_seen == Subject.CONSUMING: if not line.strip(): subject_seen = Subject.SEEN continue if subject_seen == Subject.SEEN: first_body_line = i break assert subject_seen == Subject.SEEN assert first_body_line is not None from_line = make_from_line() # Only add FROM line if it is not already there if email_lines[first_body_line] != from_line: email_lines.insert(first_body_line, from_line) email_lines.insert(first_body_line + 1, "") with open(email, "w") as f: f.write("\n".join(email_lines)) return 0 if __name__ == "__main__": sys.exit(main())