nowy mail i funkcja

This commit is contained in:
Mateusz Gruszczyński
2025-05-18 23:19:58 +02:00
parent d5a2a19776
commit f7c39c9585

45
app.py
View File

@ -3,7 +3,7 @@
import argparse import argparse
import mysql.connector import mysql.connector
import dns.resolver import dns.resolver
import datetime from datetime import datetime, timedelta
import csv import csv
import socket import socket
from dotenv import load_dotenv from dotenv import load_dotenv
@ -21,8 +21,6 @@ import smtplib
from email.mime.multipart import MIMEMultipart from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText from email.mime.text import MIMEText
import time import time
from datetime import datetime, timedelta
# Redis - baza 5 # Redis - baza 5
redis_client = redis.Redis(host='localhost', port=6379, db=5, decode_responses=True) redis_client = redis.Redis(host='localhost', port=6379, db=5, decode_responses=True)
@ -81,7 +79,7 @@ def is_temp_email(email):
return False return False
def export_to_csv(users): def export_to_csv(users):
now = datetime.datetime.now().strftime("%Y-%m-%d_%H%M") now = datetime.now().strftime("%Y-%m-%d_%H%M")
filename = f"user_cleanup_results_{now}.csv" filename = f"user_cleanup_results_{now}.csv"
with open(filename, mode='w', newline='', encoding='utf-8') as f: with open(filename, mode='w', newline='', encoding='utf-8') as f:
writer = csv.writer(f) writer = csv.writer(f)
@ -89,8 +87,8 @@ def export_to_csv(users):
for u in users: for u in users:
writer.writerow([ writer.writerow([
u['uid'], u['name'], u['mail'], u['uid'], u['name'], u['mail'],
datetime.datetime.fromtimestamp(u['access']).strftime('%Y-%m-%d') if u['access'] else 'nigdy', datetime.fromtimestamp(u['access']).strftime('%Y-%m-%d') if u['access'] else 'nigdy',
datetime.datetime.fromtimestamp(u['created']).strftime('%Y-%m-%d') if u.get('created') else 'brak', datetime.fromtimestamp(u['created']).strftime('%Y-%m-%d') if u.get('created') else 'brak',
u.get('points', 0), u.get('points', 0),
'TAK' if u['inactive'] else 'NIE', 'TAK' if u['inactive'] else 'NIE',
'TAK' if u['email_valid'] else 'NIE', 'TAK' if u['email_valid'] else 'NIE',
@ -99,7 +97,7 @@ def export_to_csv(users):
print(f"📁 CSV zapisany: {filename}") print(f"📁 CSV zapisany: {filename}")
def export_to_excel(users): def export_to_excel(users):
now = datetime.datetime.now().strftime("%Y-%m-%d_%H%M") now = datetime.now().strftime("%Y-%m-%d_%H%M")
filename = f"user_cleanup_results_{now}.xlsx" filename = f"user_cleanup_results_{now}.xlsx"
workbook = xlsxwriter.Workbook(filename) workbook = xlsxwriter.Workbook(filename)
sheet = workbook.add_worksheet("Wyniki") sheet = workbook.add_worksheet("Wyniki")
@ -110,8 +108,8 @@ def export_to_excel(users):
sheet.write(row_idx, 0, u['uid']) sheet.write(row_idx, 0, u['uid'])
sheet.write(row_idx, 1, u['name']) sheet.write(row_idx, 1, u['name'])
sheet.write(row_idx, 2, u['mail']) sheet.write(row_idx, 2, u['mail'])
sheet.write(row_idx, 3, datetime.datetime.fromtimestamp(u['access']).strftime('%Y-%m-%d') if u['access'] else 'nigdy') sheet.write(row_idx, 3, datetime.fromtimestamp(u['access']).strftime('%Y-%m-%d') if u['access'] else 'nigdy')
sheet.write(row_idx, 4, datetime.datetime.fromtimestamp(u['created']).strftime('%Y-%m-%d') if u.get('created') else 'brak') sheet.write(row_idx, 4, datetime.fromtimestamp(u['created']).strftime('%Y-%m-%d') if u.get('created') else 'brak')
sheet.write(row_idx, 5, u.get('points', 0)) sheet.write(row_idx, 5, u.get('points', 0))
sheet.write(row_idx, 6, 'TAK' if u['inactive'] else 'NIE') sheet.write(row_idx, 6, 'TAK' if u['inactive'] else 'NIE')
sheet.write(row_idx, 7, 'TAK' if u['email_valid'] else 'NIE') sheet.write(row_idx, 7, 'TAK' if u['email_valid'] else 'NIE')
@ -182,10 +180,9 @@ def send_email_batch(users, smtp_config, mails_per_pack=100, time_per_pack=60, d
print(f"❌ Błąd podczas odczytu szablonu HTML: {e}") print(f"❌ Błąd podczas odczytu szablonu HTML: {e}")
return return
# Filtrowanie użytkowników według zakresu nieaktywności
if inactive_range: if inactive_range:
min_days, max_days = inactive_range min_days, max_days = inactive_range
now_ts = int(datetime.datetime.now().timestamp()) now_ts = int(datetime.now().timestamp())
filtered_users = [] filtered_users = []
for user in users: for user in users:
last_access = user['access'] or 0 last_access = user['access'] or 0
@ -226,15 +223,14 @@ def send_email_batch(users, smtp_config, mails_per_pack=100, time_per_pack=60, d
msg['To'] = user['mail'] msg['To'] = user['mail']
msg['Subject'] = "Twoje konto w unitraklub.pl" msg['Subject'] = "Twoje konto w unitraklub.pl"
# Generowanie treści maila z uwzględnieniem ostatniego logowania
body = template.replace("@user", user['name']) \ body = template.replace("@user", user['name']) \
.replace("@rejestracja", datetime.datetime.fromtimestamp(user['created']).strftime('%Y-%m-%d')) \ .replace("@rejestracja", datetime.fromtimestamp(user['created']).strftime('%Y-%m-%d')) \
.replace("@ostatnie_logowanie", datetime.datetime.fromtimestamp(user['access']).strftime('%Y-%m-%d') if user['access'] else 'nigdy') .replace("@ostatnie_logowanie", datetime.fromtimestamp(user['access']).strftime('%Y-%m-%d') if user['access'] else 'nigdy')
msg.attach(MIMEText(body, 'html')) msg.attach(MIMEText(body, 'html'))
smtp.send_message(msg) smtp.send_message(msg)
time.sleep(0.5) # opcjonalne mikroopóźnienie między mailami time.sleep(0.5)
except Exception as e: except Exception as e:
print(f"⚠️ Błąd wysyłki do {user['mail']}: {e}") print(f"⚠️ Błąd wysyłki do {user['mail']}: {e}")
@ -339,7 +335,6 @@ def main():
parser.add_argument('--only-invalid-emails', action='store_true', parser.add_argument('--only-invalid-emails', action='store_true',
help='Usuń tylko użytkowników z nieprawidłowymi lub tymczasowymi adresami e-mail (bez sprawdzania aktywności)') help='Usuń tylko użytkowników z nieprawidłowymi lub tymczasowymi adresami e-mail (bez sprawdzania aktywności)')
# NEW: dodano argument --inactive-since
parser.add_argument( parser.add_argument(
"--inactive-since", "--inactive-since",
type=str, type=str,
@ -348,7 +343,6 @@ def main():
args = parser.parse_args() args = parser.parse_args()
# NEW: przetwarzanie parametru --inactive-since
inactive_range = None inactive_range = None
if args.inactive_since: if args.inactive_since:
try: try:
@ -362,7 +356,7 @@ def main():
test_user = { test_user = {
'name': 'Testowy Użytkownik', 'name': 'Testowy Użytkownik',
'mail': args.send_test, 'mail': args.send_test,
'created': int(datetime.datetime.now().timestamp()) - (86400 * 365 * 2) # 2 lata temu 'created': int(datetime.now().timestamp()) - (86400 * 365 * 2) # 2 lata temu
} }
print(f"📬 Wysyłka testowego maila na: {test_user['mail']}") print(f"📬 Wysyłka testowego maila na: {test_user['mail']}")
@ -387,7 +381,7 @@ def main():
} }
users = get_users(db_config) users = get_users(db_config)
now_ts = int(dt.now().timestamp()) now_ts = int(datetime.now().timestamp())
final_candidates = [] final_candidates = []
inactive_count = 0 inactive_count = 0
invalid_email_count = 0 invalid_email_count = 0
@ -401,7 +395,6 @@ def main():
continue continue
if (user.get('post_count') or 0) > 0: if (user.get('post_count') or 0) > 0:
# Pomijamy użytkownika, który dodał treści
continue continue
user['temp_email'] = is_temp_email(user['mail']) user['temp_email'] = is_temp_email(user['mail'])
@ -413,8 +406,7 @@ def main():
final_candidates.append(user) final_candidates.append(user)
continue continue
# Pomijanie aktywnych "weteranów" created_year = datetime.fromtimestamp(user['created']).year if user.get('created') else None
created_year = datetime.datetime.fromtimestamp(user['created']).year if user.get('created') else None
recent_login_threshold = now_ts - (args.recent_login_days * 86400) recent_login_threshold = now_ts - (args.recent_login_days * 86400)
if created_year and created_year <= args.veteran_year: if created_year and created_year <= args.veteran_year:
@ -437,7 +429,6 @@ def main():
if args.validate or user['inactive'] or not user['email_valid']: if args.validate or user['inactive'] or not user['email_valid']:
final_candidates.append(user) final_candidates.append(user)
# Redundant safety filter to exclude any with points
final_candidates = [u for u in final_candidates if (u.get('points') or 0) == 0] final_candidates = [u for u in final_candidates if (u.get('points') or 0) == 0]
if args.report_domains: if args.report_domains:
@ -446,8 +437,8 @@ def main():
if args.show_table: if args.show_table:
print(tabulate([ print(tabulate([
[u['uid'], u['name'], u['mail'], [u['uid'], u['name'], u['mail'],
datetime.datetime.fromtimestamp(u['access']).strftime('%Y-%m-%d') if u['access'] else 'nigdy', datetime.fromtimestamp(u['access']).strftime('%Y-%m-%d') if u['access'] else 'nigdy',
datetime.datetime.fromtimestamp(u['created']).strftime('%Y-%m-%d') if u.get('created') else 'brak', datetime.fromtimestamp(u['created']).strftime('%Y-%m-%d') if u.get('created') else 'brak',
u.get('points', 0), u.get('points', 0),
'TAK' if u['inactive'] else 'NIE', 'TAK' if u['inactive'] else 'NIE',
'TAK' if u['email_valid'] else 'NIE', 'TAK' if u['email_valid'] else 'NIE',
@ -466,7 +457,7 @@ def main():
smtp_config, smtp_config,
args.mails_per_pack, args.mails_per_pack,
args.time_per_pack, args.time_per_pack,
inactive_range=inactive_range # NEW: przekazanie zakresu nieaktywności inactive_range=inactive_range
) )
print("\n📋 Parametry filtrowania:") print("\n📋 Parametry filtrowania:")
@ -474,7 +465,7 @@ def main():
print(f"- Nieaktywni: brak logowania przez ≥ {args.days_inactive} dni (~{days_to_years(args.days_inactive)} lat)") print(f"- Nieaktywni: brak logowania przez ≥ {args.days_inactive} dni (~{days_to_years(args.days_inactive)} lat)")
print(f"- Weterani: konta zarejestrowane w roku ≤ {args.veteran_year}") print(f"- Weterani: konta zarejestrowane w roku ≤ {args.veteran_year}")
print(f"- Pominięci weterani: logowanie w ciągu ostatnich ≤ {args.recent_login_days} dni (~{days_to_years(args.recent_login_days)} lat)") print(f"- Pominięci weterani: logowanie w ciągu ostatnich ≤ {args.recent_login_days} dni (~{days_to_years(args.recent_login_days)} lat)")
if args.inactive_since: # NEW: wyświetlanie zakresu nieaktywności if args.inactive_since:
min_days, max_days = map(int, args.inactive_since.split('-')) min_days, max_days = map(int, args.inactive_since.split('-'))
print(f"- Wysyłka maili tylko dla nieaktywnych od {min_days} do {max_days} dni (~{days_to_years(min_days)}-{days_to_years(max_days)} lat)") print(f"- Wysyłka maili tylko dla nieaktywnych od {min_days} do {max_days} dni (~{days_to_years(min_days)}-{days_to_years(max_days)} lat)")