import argparse import subprocess from pathlib import Path import pandas as pd from jinja2 import Template def construct_mails( data_file: Path, template_file: Path, sheet_name: str, full_area_name: str, from_addr: str, subject: str, name_idx: int, mail_idx: int, dry_run: bool = False, ) -> None: df = pd.read_excel(data_file, sheet_name=sheet_name) today = pd.to_datetime("today").normalize() for idx, row in df.iterrows(): name = row[name_idx] mail = row[mail_idx] if pd.isna(mail): continue with template_file.open() as f: template = Template(f.read()) msg = template.render( name=name, full_area_name=full_area_name, ) payload = [ "thunderbird", "-compose", f"to='{mail}',subject='{subject}',from='{from_addr}',body='{msg}'", ] if dry_run: print(payload) else: subprocess.run(payload) def main(): parser = argparse.ArgumentParser("TVStud Bonn Mail") parser.add_argument( "--data-file", type=Path, default=Path("Strukturaufbau.xlsx"), help="Path of the ods/Excel file containing the mapping data." "Defaults to 'Strukturaufbau.xlsx'", ) parser.add_argument( "--template-file", type=Path, default=Path("template.txt"), help="Path of the text file containing the template for the mail body. " "Defaults to 'template.txt'.", ) parser.add_argument( "--from-name", type=str, default="TVStud Bonn", help="Sender name to use. Defaults to 'TVStud Bonn'", ) parser.add_argument( "--from-address", type=str, default="bonn@tvstud.de", help="Sender address to use. Defaults to 'bonn@tvstud.de'", ) parser.add_argument( "--subject", type=str, default="TVStud Bonn TODO", help="Mail subject to use" ) parser.add_argument( "--sheet", type=str, default=None, help="The name of the sheet to run on", ) parser.add_argument( "--full-area-name", type=str, default=None, help="The name of the area to use in the mail (e.g. 'Psychologie' for the sheet 'Psycho'). " "If None, the sheet name is used instead. Defaults to None.", ) parser.add_argument( "--print-sheets", action="store_true", help="Print available sheets and exit", ) parser.add_argument( "--dry-run", action="store_true", help="Do a dry run and only print the generated emails to stdout", ) parser.add_argument( "--name-idx", type=int, default=0, help="Index of the column containing the names (0-based). Defaults to 0.", ) parser.add_argument( "--mail-idx", type=int, default=6, help="Index of the column containing the mail addresses (0-based). Defaults to 6.", ) args = parser.parse_args() if args.print_sheets or args.sheet is None: xl = pd.ExcelFile(args.data_file) print("Available sheets (specify via '--sheet'):") print(xl.sheet_names) return if args.full_area_name is None: args.full_area_name = args.sheet construct_mails( data_file=args.data_file, template_file=args.template_file, sheet_name=args.sheet, full_area_name=args.full_area_name, subject=args.subject, from_addr=args.from_address, name_idx=args.name_idx, mail_idx=args.mail_idx, dry_run=args.dry_run, ) if __name__ == "__main__": main()