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:
+
+ - Aby korzystać z działu download, gdzie znajdziesz schematy, instrukcje serwisowe i inne cenne materiały, wymagany jest minimalny staż w serwisie
+ - Twoje obecne konto ma już historię, którą stracisz jeśli zostanie usunięte
+ - Długoletnie konta mają pierwszeństwo dostępu do specjalnych zasobów
+
+
+
Jeśli nadal chcesz korzystać z serwisu, wystarczy się zalogować – to wszystko!
@@ -71,4 +110,4 @@
-