diff options
Diffstat (limited to 'dmarc_analyzer/main.py')
| -rw-r--r-- | dmarc_analyzer/main.py | 108 |
1 files changed, 108 insertions, 0 deletions
diff --git a/dmarc_analyzer/main.py b/dmarc_analyzer/main.py new file mode 100644 index 0000000..18431d0 --- /dev/null +++ b/dmarc_analyzer/main.py @@ -0,0 +1,108 @@ +#!/usr/bin/env python3 +"""Main CLI entry point for DMARC analyzer""" + +import click +import os +from pathlib import Path + +from .extractor import extract_files +from .parser import parse_dmarc_report +from .database import Database +from .reporter import generate_report + + +@click.command() +@click.argument('paths', nargs=-1, type=click.Path(exists=True)) +@click.option('--db', default='dmarc_reports.db', help='Database file path') +@click.option('--output-format', type=click.Choice(['summary', 'detailed', 'failures']), default='summary', help='Report output format') +@click.option('--show-failures-only', is_flag=True, help='Show only records with authentication failures') +@click.option('--report-only', is_flag=True, help='Generate report from existing data without processing files') +@click.option('--date-from', type=click.DateTime(['%Y-%m-%d']), help='Filter reports from this date (YYYY-MM-DD)') +@click.option('--date-to', type=click.DateTime(['%Y-%m-%d']), help='Filter reports to this date (YYYY-MM-DD)') +@click.option('--show-timeline', is_flag=True, help='Show daily breakdown in reports') +def cli(paths, db, output_format, show_failures_only, report_only, date_from, date_to, show_timeline): + """Analyze DMARC reports from gzip/zip files or directories""" + database = Database(db) + database.init_db() + + # Report-only mode: skip file processing + if report_only: + if paths: + click.echo("Warning: Paths provided but --report-only specified. Ignoring paths.", err=True) + + click.echo("Generating report from existing database...") + click.echo("\n" + "="*50) + click.echo("DMARC REPORT SUMMARY") + click.echo("="*50) + + # Create date filter + date_filter = {} + if date_from: + date_filter['date_from'] = date_from + if date_to: + date_filter['date_to'] = date_to + + report = generate_report(database, output_format, show_failures_only, date_filter, show_timeline) + click.echo(report) + return + + # Validate paths are provided for processing mode + if not paths: + click.echo("Error: Paths are required unless using --report-only", err=True) + return + + processed_count = 0 + + for path in paths: + path = Path(path) + + if path.is_file(): + files = [path] + else: + # Find all gzip and zip files in directory + files = list(path.glob('*.gz')) + list(path.glob('*.zip')) + + for file_path in files: + try: + click.echo(f"Processing: {file_path}") + + # Extract and parse + xml_content = extract_files(file_path) + if xml_content: + report_data = parse_dmarc_report(xml_content) + if report_data: + was_stored = database.store_report(report_data) + if was_stored: + processed_count += 1 + click.echo(f" ✓ Processed successfully") + else: + click.echo(f" ⊝ Skipped (duplicate)") + else: + click.echo(f" ⚠ Failed to parse DMARC report", err=True) + else: + click.echo(f" ⚠ Failed to extract file", err=True) + + except Exception as e: + click.echo(f" ✗ Error processing {file_path}: {e}", err=True) + + click.echo(f"\nProcessed {processed_count} reports") + + # Generate summary report + if processed_count > 0: + click.echo("\n" + "="*50) + click.echo("DMARC REPORT SUMMARY") + click.echo("="*50) + + # Create date filter for processing mode too + date_filter = {} + if date_from: + date_filter['date_from'] = date_from + if date_to: + date_filter['date_to'] = date_to + + report = generate_report(database, output_format, show_failures_only, date_filter, show_timeline) + click.echo(report) + + +if __name__ == '__main__': + cli()
\ No newline at end of file |