578 Zeilen
25 KiB
Python
578 Zeilen
25 KiB
Python
# social_networks/facebook/facebook_automation.py
|
|
|
|
"""
|
|
Facebook-Automatisierung - Hauptklasse für Facebook-Automatisierungsfunktionalität
|
|
Mit Anti-Bot Features wie bei Instagram.
|
|
"""
|
|
|
|
import logging
|
|
import time
|
|
import random
|
|
from datetime import datetime
|
|
from typing import Dict, List, Any, Optional, Tuple
|
|
|
|
from browser.playwright_manager import PlaywrightManager
|
|
from browser.playwright_extensions import PlaywrightExtensions
|
|
from social_networks.base_automation import BaseAutomation
|
|
from infrastructure.services.advanced_fingerprint_service import AdvancedFingerprintService
|
|
from infrastructure.repositories.fingerprint_repository import FingerprintRepository
|
|
from utils.password_generator import PasswordGenerator
|
|
from utils.username_generator import UsernameGenerator
|
|
from utils.birthday_generator import BirthdayGenerator
|
|
from utils.human_behavior import HumanBehavior
|
|
from utils.email_handler import EmailHandler
|
|
|
|
# Importiere Helferklassen
|
|
from .facebook_registration import FacebookRegistration
|
|
from .facebook_login import FacebookLogin
|
|
from .facebook_verification import FacebookVerification
|
|
from .facebook_ui_helper import FacebookUIHelper
|
|
from .facebook_utils import FacebookUtils
|
|
from utils.logger import setup_logger
|
|
|
|
# Konfiguriere Logger
|
|
logger = setup_logger("facebook_automation")
|
|
|
|
class FacebookAutomation(BaseAutomation):
|
|
"""
|
|
Hauptklasse für die Facebook-Automatisierung.
|
|
Implementiert die Registrierung und Anmeldung bei Facebook mit Anti-Bot Features.
|
|
"""
|
|
|
|
def __init__(self,
|
|
headless: bool = False,
|
|
use_proxy: bool = False,
|
|
proxy_type: str = None,
|
|
save_screenshots: bool = True,
|
|
screenshots_dir: str = None,
|
|
slowmo: int = 0,
|
|
debug: bool = False,
|
|
email_domain: str = "z5m7q9dk3ah2v1plx6ju.com",
|
|
enhanced_stealth: bool = True,
|
|
fingerprint_noise: float = 0.5,
|
|
window_position = None,
|
|
fingerprint = None,
|
|
language: str = "de"):
|
|
"""
|
|
Initialisiert die Facebook-Automatisierung.
|
|
|
|
Args:
|
|
headless: Ob der Browser im Headless-Modus ausgeführt werden soll
|
|
use_proxy: Ob ein Proxy verwendet werden soll
|
|
proxy_type: Proxy-Typ ("ipv4", "ipv6", "mobile") oder None für zufälligen Typ
|
|
save_screenshots: Ob Screenshots gespeichert werden sollen
|
|
screenshots_dir: Verzeichnis für Screenshots
|
|
slowmo: Verzögerung zwischen Aktionen in Millisekunden
|
|
debug: Ob Debug-Informationen angezeigt werden sollen
|
|
email_domain: Domain für generierte E-Mail-Adressen
|
|
enhanced_stealth: Ob erweiterter Stealth-Modus aktiviert werden soll
|
|
fingerprint_noise: Menge an Rauschen für Fingerprint-Verschleierung (0.0-1.0)
|
|
window_position: Position des Browser-Fensters
|
|
fingerprint: Vordefinierter Fingerprint
|
|
language: Sprache für Facebook ("de" oder "en")
|
|
"""
|
|
# Initialisiere die Basisklasse
|
|
super().__init__(
|
|
headless=headless,
|
|
use_proxy=use_proxy,
|
|
proxy_type=proxy_type,
|
|
save_screenshots=save_screenshots,
|
|
screenshots_dir=screenshots_dir,
|
|
slowmo=slowmo,
|
|
debug=debug,
|
|
email_domain=email_domain,
|
|
window_position=window_position
|
|
)
|
|
|
|
# Zusätzliche Initialisierungen für Facebook
|
|
self.window_position = window_position
|
|
|
|
# Facebook-spezifische Einstellungen
|
|
self.language = language
|
|
self.base_url = f"https://www.facebook.com/?locale={language}_DE" if language == "de" else "https://www.facebook.com"
|
|
|
|
# Stealth-Modus-Einstellungen (wie bei Instagram)
|
|
self.enhanced_stealth = enhanced_stealth
|
|
self.fingerprint_noise = max(0.0, min(1.0, fingerprint_noise))
|
|
|
|
# Initialisiere Helferklassen
|
|
self.registration = FacebookRegistration(self)
|
|
self.login = FacebookLogin(self)
|
|
self.verification = FacebookVerification(self)
|
|
self.ui_helper = FacebookUIHelper(self)
|
|
self.utils = FacebookUtils(self)
|
|
|
|
# Zusätzliche Hilfsklassen
|
|
self.password_generator = PasswordGenerator()
|
|
self.username_generator = UsernameGenerator()
|
|
self.birthday_generator = BirthdayGenerator()
|
|
self.human_behavior = HumanBehavior(speed_factor=0.8, randomness=0.6)
|
|
self.email_handler = EmailHandler() # Fuer E-Mail-Verifikation wie bei Instagram
|
|
|
|
# Fingerprint Service für Account-gebundene Fingerprints (wie bei Instagram)
|
|
self.fingerprint_service = AdvancedFingerprintService(FingerprintRepository())
|
|
self.account_fingerprint = None
|
|
|
|
# Nutze übergebenen Fingerprint wenn vorhanden
|
|
self.provided_fingerprint = fingerprint
|
|
|
|
logger.info(f"Facebook-Automatisierung initialisiert (Sprache: {language})")
|
|
|
|
def _initialize_browser(self) -> bool:
|
|
"""
|
|
Initialisiert den Browser mit Facebook-spezifischen Einstellungen.
|
|
Folgt dem Instagram-Pattern für saubere Implementierung.
|
|
|
|
Returns:
|
|
bool: True bei Erfolg, False bei Fehler
|
|
"""
|
|
try:
|
|
self._emit_customer_log("🔄 Sichere Verbindung wird aufgebaut...")
|
|
|
|
# Proxy-Konfiguration, falls aktiviert
|
|
proxy_config = None
|
|
if self.use_proxy:
|
|
self._emit_customer_log("🌐 Optimale Verbindung wird ausgewählt...")
|
|
proxy_config = self.proxy_rotator.get_proxy(self.proxy_type)
|
|
if not proxy_config:
|
|
logger.warning(f"Kein Proxy vom Typ '{self.proxy_type}' verfügbar, verwende direkten Zugriff")
|
|
|
|
# Browser initialisieren (wie Instagram - direkt, ohne super())
|
|
self.browser = PlaywrightManager(
|
|
headless=self.headless,
|
|
proxy=proxy_config,
|
|
browser_type="chromium",
|
|
screenshots_dir=self.screenshots_dir,
|
|
slowmo=self.slowmo,
|
|
window_position=self.window_position
|
|
)
|
|
|
|
# Browser starten
|
|
self.browser.start()
|
|
|
|
# Erweiterten Fingerprint-Schutz aktivieren, wenn gewünscht
|
|
if self.enhanced_stealth:
|
|
# Erstelle Extensions-Objekt
|
|
extensions = PlaywrightExtensions(self.browser)
|
|
|
|
# Methoden anhängen
|
|
extensions.hook_into_playwright_manager()
|
|
|
|
# Fingerprint-Schutz aktivieren mit angepasster Konfiguration
|
|
if self.provided_fingerprint:
|
|
# Nutze den bereitgestellten Fingerprint
|
|
logger.info("Verwende bereitgestellten Fingerprint für Account-Erstellung")
|
|
# Konvertiere Dict zu BrowserFingerprint wenn nötig
|
|
if isinstance(self.provided_fingerprint, dict):
|
|
from domain.entities.browser_fingerprint import BrowserFingerprint
|
|
fingerprint_obj = BrowserFingerprint.from_dict(self.provided_fingerprint)
|
|
else:
|
|
fingerprint_obj = self.provided_fingerprint
|
|
|
|
# Wende Fingerprint über FingerprintProtection an
|
|
from browser.fingerprint_protection import FingerprintProtection
|
|
protection = FingerprintProtection(
|
|
context=self.browser.context,
|
|
fingerprint_config=fingerprint_obj
|
|
)
|
|
protection.apply_to_context(self.browser.context)
|
|
logger.info(f"Fingerprint {fingerprint_obj.fingerprint_id} angewendet")
|
|
self.account_fingerprint = fingerprint_obj
|
|
else:
|
|
# Fallback: Zufällige Fingerprint-Konfiguration
|
|
fingerprint_config = {
|
|
"noise_level": self.fingerprint_noise,
|
|
"canvas_noise": True,
|
|
"audio_noise": True,
|
|
"webgl_noise": True,
|
|
"hardware_concurrency": random.choice([4, 6, 8]),
|
|
"device_memory": random.choice([4, 8]),
|
|
"language": self.language,
|
|
"timezone_id": "Europe/Berlin"
|
|
}
|
|
|
|
success = self.browser.enable_enhanced_fingerprint_protection(fingerprint_config)
|
|
if success:
|
|
logger.info("Erweiterter Fingerprint-Schutz erfolgreich aktiviert")
|
|
else:
|
|
logger.warning("Erweiterter Fingerprint-Schutz konnte nicht aktiviert werden")
|
|
|
|
# Facebook-spezifische Browser-Einstellungen
|
|
self._apply_facebook_specific_settings()
|
|
|
|
self._emit_customer_log("✅ Verbindung erfolgreich hergestellt")
|
|
logger.info("Browser erfolgreich initialisiert")
|
|
return True
|
|
|
|
except Exception as e:
|
|
logger.error(f"Fehler bei der Browser-Initialisierung: {e}")
|
|
self.status["error"] = f"Browser-Initialisierungsfehler: {str(e)}"
|
|
return False
|
|
|
|
def _apply_facebook_specific_settings(self):
|
|
"""
|
|
Wendet Facebook-spezifische Browser-Einstellungen an.
|
|
"""
|
|
try:
|
|
# Setze Facebook-spezifische Headers
|
|
extra_headers = {
|
|
'Accept-Language': 'de-DE,de;q=0.9,en;q=0.8' if self.language == 'de' else 'en-US,en;q=0.9',
|
|
'sec-ch-ua': '"Not_A Brand";v="8", "Chromium";v="120", "Google Chrome";v="120"',
|
|
'sec-ch-ua-mobile': '?0',
|
|
'sec-ch-ua-platform': '"Windows"',
|
|
}
|
|
|
|
self.browser.page.set_extra_http_headers(extra_headers)
|
|
|
|
# Viewport für Desktop
|
|
self.browser.page.set_viewport_size({
|
|
'width': random.randint(1366, 1920),
|
|
'height': random.randint(768, 1080)
|
|
})
|
|
|
|
logger.debug("Facebook-spezifische Browser-Einstellungen angewendet")
|
|
|
|
except Exception as e:
|
|
logger.warning(f"Fehler beim Anwenden Facebook-spezifischer Einstellungen: {e}")
|
|
|
|
def register_account(self,
|
|
full_name: str = None,
|
|
age: int = None,
|
|
first_name: str = None,
|
|
last_name: str = None,
|
|
birth_date: Dict[str, int] = None,
|
|
gender: str = None,
|
|
registration_method: str = "email",
|
|
email: str = None,
|
|
phone_number: str = None,
|
|
password: str = None,
|
|
**kwargs) -> Dict[str, Any]:
|
|
"""
|
|
Registriert einen neuen Facebook-Account.
|
|
Unterstützt beide Aufrufmuster: Base-Pattern (full_name, age) und Legacy (first_name, last_name, birth_date).
|
|
|
|
Args:
|
|
full_name: Vollständiger Name (für Base-Pattern)
|
|
age: Alter (für Base-Pattern)
|
|
first_name: Vorname (Legacy, wird aus full_name extrahiert wenn nicht gegeben)
|
|
last_name: Nachname (Legacy, wird aus full_name extrahiert wenn nicht gegeben)
|
|
birth_date: Geburtsdatum als Dict (Legacy, wird aus age generiert wenn nicht gegeben)
|
|
gender: Geschlecht ('male', 'female', 'custom')
|
|
registration_method: Registrierungsmethode (für Kompatibilität, immer 'email' bei Facebook)
|
|
email: E-Mail-Adresse (optional, wird generiert wenn nicht angegeben)
|
|
phone_number: Telefonnummer (optional, alternativ zu E-Mail)
|
|
password: Passwort (optional, wird generiert wenn nicht angegeben)
|
|
**kwargs: Weitere optionale Parameter
|
|
|
|
Returns:
|
|
Dict[str, Any]: Ergebnis der Registrierung
|
|
"""
|
|
# Parameter-Konvertierung: Base-Pattern → Facebook-Format
|
|
if full_name and not (first_name and last_name):
|
|
name_parts = full_name.split(" ", 1)
|
|
first_name = name_parts[0] if name_parts else "Test"
|
|
last_name = name_parts[1] if len(name_parts) > 1 else "User"
|
|
logger.debug(f"Namen aus full_name extrahiert: {first_name} {last_name}")
|
|
|
|
if age and not birth_date:
|
|
birth_date = self.birthday_generator.generate_birthday_components("facebook", age)
|
|
logger.debug(f"Geburtsdatum aus Alter generiert: {birth_date}")
|
|
|
|
if not gender:
|
|
gender = random.choice(["male", "female"])
|
|
logger.debug(f"Zufälliges Geschlecht gewählt: {gender}")
|
|
|
|
logger.info(f"Starte Facebook-Registrierung für {first_name} {last_name}")
|
|
|
|
try:
|
|
# Browser initialisieren
|
|
if not self._initialize_browser():
|
|
return {"success": False, "error": "Browser konnte nicht initialisiert werden"}
|
|
|
|
# Fingerprint rotieren für neue Registrierung
|
|
if self.enhanced_stealth and hasattr(self.browser, 'rotate_fingerprint'):
|
|
self.browser.rotate_fingerprint()
|
|
logger.info("Browser-Fingerprint für Registrierung rotiert")
|
|
|
|
# E-Mail generieren wenn nicht vorhanden
|
|
if not email and not phone_number:
|
|
email = self._generate_email(first_name, last_name)
|
|
logger.info(f"Generierte E-Mail: {email}")
|
|
|
|
# Passwort generieren wenn nicht vorhanden
|
|
if not password:
|
|
# Facebook-spezifische Passwort-Policy
|
|
password = self.password_generator.generate_password(
|
|
platform="facebook", # Plattform-spezifische Regeln
|
|
length=random.randint(12, 16) # Überschreibt default-Länge
|
|
)
|
|
logger.info("Passwort generiert")
|
|
|
|
# Account-Daten vorbereiten
|
|
account_data = {
|
|
"first_name": first_name,
|
|
"last_name": last_name,
|
|
"birth_date": birth_date,
|
|
"gender": gender,
|
|
"email": email,
|
|
"phone_number": phone_number,
|
|
"password": password,
|
|
"language": self.language,
|
|
**kwargs
|
|
}
|
|
|
|
# Delegiere an Registration-Klasse
|
|
result = self.registration.register_account(account_data)
|
|
|
|
# Screenshot am Ende
|
|
self._take_screenshot(f"registration_finished_{int(time.time())}")
|
|
|
|
# Fingerprint-Statistiken aktualisieren bei Erfolg
|
|
if result.get("success") and self.account_fingerprint:
|
|
try:
|
|
account_id = result.get("account_data", {}).get("account_id", f"fb_{int(time.time())}")
|
|
self.fingerprint_service.update_fingerprint_stats(
|
|
self.account_fingerprint.fingerprint_id,
|
|
account_id,
|
|
success=True
|
|
)
|
|
logger.info("Fingerprint-Statistiken für erfolgreiche Registrierung aktualisiert")
|
|
except Exception as e:
|
|
logger.warning(f"Fehler beim Aktualisieren der Fingerprint-Statistiken: {e}")
|
|
|
|
# Status aktualisieren
|
|
self.status.update(result)
|
|
|
|
return result
|
|
|
|
except Exception as e:
|
|
error_msg = f"Unerwarteter Fehler bei der Registrierung: {str(e)}"
|
|
logger.error(error_msg, exc_info=True)
|
|
|
|
# Fehler-Screenshot
|
|
self._take_screenshot(f"registration_error_{int(time.time())}")
|
|
|
|
self.status.update({
|
|
"success": False,
|
|
"error": error_msg,
|
|
"stage": "error"
|
|
})
|
|
|
|
return self.status
|
|
finally:
|
|
# Browser offen lassen für Debugging
|
|
logger.info("Registrierung abgeschlossen - Browser bleibt offen")
|
|
|
|
def login_account(self, email_or_phone: str, password: str, account_id: Optional[str] = None, **kwargs) -> Dict[str, Any]:
|
|
"""
|
|
Meldet sich bei einem bestehenden Facebook-Account an.
|
|
|
|
Args:
|
|
email_or_phone: E-Mail-Adresse oder Telefonnummer
|
|
password: Passwort
|
|
account_id: Optional account ID für gespeicherten Fingerprint
|
|
**kwargs: Weitere optionale Parameter
|
|
|
|
Returns:
|
|
Dict[str, Any]: Ergebnis der Anmeldung
|
|
"""
|
|
logger.info(f"Starte Facebook-Login für '{email_or_phone}'")
|
|
|
|
try:
|
|
# Browser initialisieren mit Account-Fingerprint wenn vorhanden
|
|
if not self.browser or not hasattr(self.browser, 'page') or not self.browser.page:
|
|
if account_id:
|
|
# Verwende Account-spezifischen Fingerprint
|
|
if not self._initialize_browser_with_fingerprint(account_id):
|
|
return {"success": False, "error": "Browser konnte nicht mit Account-Fingerprint initialisiert werden"}
|
|
else:
|
|
# Verwende zufälligen Fingerprint
|
|
if not self._initialize_browser():
|
|
return {"success": False, "error": "Browser konnte nicht initialisiert werden"}
|
|
else:
|
|
logger.info("Verwende bereits geöffneten Browser für Login")
|
|
|
|
# Delegiere an Login-Klasse
|
|
result = self.login.login_account(email_or_phone, password, **kwargs)
|
|
|
|
# Screenshot am Ende
|
|
self._take_screenshot(f"login_finished_{int(time.time())}")
|
|
|
|
# Fingerprint-Statistiken aktualisieren
|
|
if account_id and self.account_fingerprint and result.get("success"):
|
|
try:
|
|
self.fingerprint_service.update_fingerprint_stats(
|
|
self.account_fingerprint.fingerprint_id,
|
|
account_id,
|
|
success=True
|
|
)
|
|
logger.info("Fingerprint-Statistiken für erfolgreichen Login aktualisiert")
|
|
except Exception as e:
|
|
logger.warning(f"Fehler beim Aktualisieren der Fingerprint-Statistiken: {e}")
|
|
|
|
# Status aktualisieren
|
|
self.status.update(result)
|
|
|
|
return result
|
|
|
|
except Exception as e:
|
|
error_msg = f"Unerwarteter Fehler beim Login: {str(e)}"
|
|
logger.error(error_msg, exc_info=True)
|
|
|
|
# Fehler-Screenshot
|
|
self._take_screenshot(f"login_error_{int(time.time())}")
|
|
|
|
self.status.update({
|
|
"success": False,
|
|
"error": error_msg,
|
|
"stage": "error"
|
|
})
|
|
|
|
return self.status
|
|
finally:
|
|
# Browser offen lassen für User-Kontrolle
|
|
logger.info("Login abgeschlossen - Browser bleibt offen")
|
|
|
|
def verify_account(self, verification_code: str, **kwargs) -> Dict[str, Any]:
|
|
"""
|
|
Verifiziert einen Facebook-Account mit einem Bestätigungscode.
|
|
Implementiert die abstrakte Methode aus BaseAutomation.
|
|
|
|
Args:
|
|
verification_code: Der Bestätigungscode (5-stellig für Facebook)
|
|
**kwargs: Weitere optionale Parameter
|
|
|
|
Returns:
|
|
Dict[str, Any]: Ergebnis der Verifizierung mit Status
|
|
"""
|
|
logger.info(f"Starte Facebook-Account-Verifizierung mit Code: {verification_code}")
|
|
|
|
try:
|
|
# Browser initialisieren falls noch nicht geschehen
|
|
if not self.browser or not hasattr(self.browser, 'page'):
|
|
if not self._initialize_browser():
|
|
return {"success": False, "error": "Browser konnte nicht initialisiert werden"}
|
|
|
|
# Delegiere an Verification-Klasse
|
|
# Die eigentliche Verifizierung wird bereits in registration.py gehandhabt
|
|
# Diese Methode ist für standalone Verifizierung
|
|
|
|
# Prüfe ob wir auf der Verifizierungsseite sind
|
|
current_url = self.browser.page.url if self.browser else ""
|
|
if "confirmemail" not in current_url:
|
|
logger.warning("Nicht auf der Verifizierungsseite - navigiere dorthin")
|
|
# Könnte hier zur Verifizierungsseite navigieren wenn nötig
|
|
|
|
# Nutze die _enter_verification_code Methode aus registration
|
|
from .facebook_registration import FacebookRegistration
|
|
temp_registration = FacebookRegistration(self)
|
|
success = temp_registration._enter_verification_code(verification_code)
|
|
|
|
if success:
|
|
logger.info("Verifizierung erfolgreich abgeschlossen")
|
|
result = {
|
|
"success": True,
|
|
"stage": "verified",
|
|
"message": "Account erfolgreich verifiziert"
|
|
}
|
|
else:
|
|
logger.error("Verifizierung fehlgeschlagen")
|
|
result = {
|
|
"success": False,
|
|
"error": "Verifizierungscode konnte nicht bestätigt werden",
|
|
"stage": "verification_failed"
|
|
}
|
|
|
|
# Screenshot
|
|
self._take_screenshot(f"verification_result_{int(time.time())}")
|
|
|
|
# Status aktualisieren
|
|
self.status.update(result)
|
|
|
|
return result
|
|
|
|
except Exception as e:
|
|
error_msg = f"Unerwarteter Fehler bei der Verifizierung: {str(e)}"
|
|
logger.error(error_msg, exc_info=True)
|
|
|
|
# Fehler-Screenshot
|
|
self._take_screenshot(f"verification_error_{int(time.time())}")
|
|
|
|
self.status.update({
|
|
"success": False,
|
|
"error": error_msg,
|
|
"stage": "error"
|
|
})
|
|
|
|
return self.status
|
|
finally:
|
|
# Browser offen lassen für weitere Aktionen
|
|
logger.info("Verifizierung abgeschlossen - Browser bleibt offen")
|
|
|
|
def _initialize_browser_with_fingerprint(self, account_id: str) -> bool:
|
|
"""
|
|
Initialisiert den Browser mit einem Account-spezifischen Fingerprint.
|
|
|
|
Args:
|
|
account_id: Account-ID für den Fingerprint
|
|
|
|
Returns:
|
|
bool: True bei Erfolg, False bei Fehler
|
|
"""
|
|
try:
|
|
fingerprint = self.fingerprint_service.get_account_fingerprint(account_id)
|
|
|
|
if fingerprint:
|
|
logger.info(f"Verwende gespeicherten Fingerprint für Account {account_id}")
|
|
else:
|
|
logger.info(f"Kein gespeicherter Fingerprint für Account {account_id}, generiere neuen")
|
|
fingerprint = self.fingerprint_service.create_account_fingerprint(
|
|
account_id=account_id,
|
|
profile_type="desktop",
|
|
platform="facebook"
|
|
)
|
|
|
|
self.provided_fingerprint = fingerprint.to_dict() if hasattr(fingerprint, 'to_dict') else fingerprint
|
|
self.account_fingerprint = fingerprint
|
|
|
|
# Browser mit Fingerprint initialisieren
|
|
return self._initialize_browser()
|
|
|
|
except Exception as e:
|
|
logger.error(f"Fehler bei Browser-Initialisierung mit Fingerprint: {e}")
|
|
return False
|
|
|
|
def _generate_email(self, first_name: str, last_name: str) -> str:
|
|
"""
|
|
Generiert eine E-Mail-Adresse basierend auf dem Namen.
|
|
|
|
Args:
|
|
first_name: Vorname
|
|
last_name: Nachname
|
|
|
|
Returns:
|
|
str: Generierte E-Mail-Adresse
|
|
"""
|
|
# Entferne Umlaute und Sonderzeichen
|
|
first_clean = first_name.lower().replace('ä', 'ae').replace('ö', 'oe').replace('ü', 'ue').replace('ß', 'ss')
|
|
last_clean = last_name.lower().replace('ä', 'ae').replace('ö', 'oe').replace('ü', 'ue').replace('ß', 'ss')
|
|
|
|
# Verschiedene E-Mail-Formate
|
|
formats = [
|
|
f"{first_clean}.{last_clean}",
|
|
f"{first_clean}{last_clean}",
|
|
f"{first_clean[0]}{last_clean}",
|
|
f"{first_clean}_{last_clean}",
|
|
f"{last_clean}.{first_clean}",
|
|
]
|
|
|
|
# Wähle zufälliges Format
|
|
base_email = random.choice(formats)
|
|
|
|
# Füge optional Zahlen hinzu
|
|
if random.random() > 0.5:
|
|
base_email += str(random.randint(1, 999))
|
|
|
|
# Füge Domain hinzu
|
|
return f"{base_email}@{self.email_domain}"
|