From eeadd80347f5aa533a91cf9952216a85727ea878 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Gruszczy=C5=84ski?= Date: Sun, 18 May 2025 23:09:38 +0200 Subject: [PATCH] nowy mail i funkcja --- app.py | 63 +++++++++++++++++++++++++++++++++++++--------- mail_template.html | 47 +++++++++++++++++++++++++++++++--- 2 files changed, 94 insertions(+), 16 deletions(-) diff --git a/app.py b/app.py index e0f551a..7cc6e1c 100644 --- a/app.py +++ b/app.py @@ -21,6 +21,7 @@ import smtplib from email.mime.multipart import MIMEMultipart from email.mime.text import MIMEText import time +from datetime import datetime, timedelta # Redis - baza 5 @@ -79,7 +80,6 @@ def is_temp_email(email): except Exception: return False - def export_to_csv(users): now = datetime.datetime.now().strftime("%Y-%m-%d_%H%M") filename = f"user_cleanup_results_{now}.csv" @@ -167,7 +167,7 @@ def get_smtp_config(): return config -def send_email_batch(users, smtp_config, mails_per_pack=100, time_per_pack=60, dry_run=False): +def send_email_batch(users, smtp_config, mails_per_pack=100, time_per_pack=60, dry_run=False, inactive_range=None): import os template_path = "mail_template.html" @@ -182,6 +182,19 @@ 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}") return + # Filtrowanie użytkowników według zakresu nieaktywności + if inactive_range: + min_days, max_days = inactive_range + now_ts = int(datetime.datetime.now().timestamp()) + filtered_users = [] + for user in users: + last_access = user['access'] or 0 + days_inactive = (now_ts - last_access) / 86400 + if min_days <= days_inactive <= max_days: + filtered_users.append(user) + users = filtered_users + print(f"📨 Wysyłka maili tylko dla użytkowników nieaktywnych od {min_days} do {max_days} dni ({len(users)} osób)") + try: smtp = smtplib.SMTP(smtp_config["host"], int(smtp_config["port"])) smtp.ehlo() @@ -213,8 +226,11 @@ def send_email_batch(users, smtp_config, mails_per_pack=100, time_per_pack=60, d msg['To'] = user['mail'] msg['Subject'] = "Twoje konto w unitraklub.pl" - body = template.replace("@user", user['name']).replace( - "@rejestracja", datetime.datetime.fromtimestamp(user['created']).strftime('%Y-%m-%d')) + # Generowanie treści maila z uwzględnieniem ostatniego logowania + body = template.replace("@user", user['name']) \ + .replace("@rejestracja", datetime.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') + msg.attach(MIMEText(body, 'html')) smtp.send_message(msg) @@ -263,6 +279,9 @@ def main(): # Czyszczenie cache DNS w Redisie /root/user_manager/venv/bin/python3 app.py --flush-cache + + # Wyślij maile tylko do użytkowników nieaktywnych od 1 do 5 lat + /root/user_manager/venv/bin/python3 app.py --send-mails --inactive-since 365-1825 """, formatter_class=argparse.RawDescriptionHelpFormatter ) @@ -318,11 +337,27 @@ def main(): help='Ile sekund czekać między paczkami maili (domyślnie: 60 sek.)') 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( + "--inactive-since", + type=str, + help="Zakres dni nieaktywności w formacie min-max, np. 360-1825 (tylko dla wysyłki maili)" + ) args = parser.parse_args() + # NEW: przetwarzanie parametru --inactive-since + inactive_range = None + if args.inactive_since: + try: + min_days, max_days = map(int, args.inactive_since.split('-')) + inactive_range = (min_days, max_days) + except Exception as e: + print(f"Błąd parsowania zakresu dni w --inactive-since: {e}") + exit(1) + if args.send_test: test_user = { 'name': 'Testowy Użytkownik', @@ -334,7 +369,6 @@ def main(): send_email_batch([test_user], smtp_config, mails_per_pack=1, time_per_pack=0, dry_run=False) return - if not args.drupal_path: args.drupal_path = os.getenv("DRUPAL_PATH") @@ -406,7 +440,6 @@ def main(): # Redundant safety filter to exclude any with points final_candidates = [u for u in final_candidates if (u.get('points') or 0) == 0] - if args.report_domains: domain_report(final_candidates) @@ -424,19 +457,26 @@ def main(): export_to_csv(final_candidates) - if args.export_excel: export_to_excel(final_candidates) if args.send_mails: - send_email_batch(final_candidates, smtp_config, args.mails_per_pack, args.time_per_pack) - + send_email_batch( + final_candidates, + smtp_config, + args.mails_per_pack, + args.time_per_pack, + inactive_range=inactive_range # NEW: przekazanie zakresu nieaktywności + ) print("\n📋 Parametry filtrowania:") if args.days_inactive: 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"- 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 + 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("\n📊 Podsumowanie:") print(f"- Całkowita liczba użytkowników w bazie: {len(users)}") @@ -459,6 +499,5 @@ def main(): delete_user_via_php(u['uid'], args.drupal_path) print(f"✅ Usunięto {len(final_candidates)} użytkowników przez delete_user.php") - if __name__ == '__main__': - main() + main() \ No newline at end of file diff --git a/mail_template.html b/mail_template.html index 5010683..b1859c0 100644 --- a/mail_template.html +++ b/mail_template.html @@ -25,6 +25,11 @@ font-size: 22px; color: #222222; } + h2 { + font-size: 18px; + color: #222222; + margin-top: 25px; + } p { font-size: 16px; line-height: 1.6; @@ -42,6 +47,28 @@ margin: 20px 0; font-weight: bold; } + .details { + background-color: #f8f9fa; + padding: 12px; + border-left: 4px solid #3498db; + margin: 20px 0; + } + .details-item { + margin-bottom: 8px; + } + .benefits { + background-color: #e8f4fd; + padding: 12px; + border-left: 4px solid #2980b9; + margin: 20px 0; + } + .benefits ul { + padding-left: 20px; + margin: 10px 0; + } + .benefits li { + margin-bottom: 8px; + } @@ -52,14 +79,26 @@ Kontaktujemy się z Tobą w sprawie Twojego konta w serwisie unitraklub.pl.

-

- Zarejestrowałeś/aś konto dnia @rejestracja. Niestety, od momentu rejestracji nie wykazało ono żadnej aktywności. -

+
+
Data rejestracji: @rejestracja
+
Ostatnie logowanie: @ostatnie_logowanie
+
Jeśli nie zalogujesz się w najbliższym czasie, konto zostanie zablokowane i następnie usunięte.
+

Dlaczego warto zachować obecne konto?

+ +
+

Od pewnego czasu wprowadziliśmy nowe zasady dostępu do cennych zasobów:

+ +
+

Jeśli nadal chcesz korzystać z serwisu, wystarczy się zalogować – to wszystko!

@@ -71,4 +110,4 @@ - + \ No newline at end of file