144 lines
5.0 KiB
Python
144 lines
5.0 KiB
Python
import smtplib
|
|
from email.mime.text import MIMEText
|
|
from email.mime.multipart import MIMEMultipart
|
|
from typing import List, Dict, Optional
|
|
import os
|
|
from datetime import datetime
|
|
|
|
class EmailNotifier:
|
|
"""Email notification system"""
|
|
|
|
def __init__(self, config: Dict):
|
|
self.smtp_server = config.get('smtp_server', 'localhost')
|
|
self.smtp_port = int(config.get('smtp_port', 587))
|
|
self.username = config.get('username', '')
|
|
self.password = config.get('password', '')
|
|
self.from_email = config.get('from_email', self.username)
|
|
self.security = config.get('security', 'starttls')
|
|
|
|
# Handle to_emails - can be string or list
|
|
to_emails = config.get('to_emails', [])
|
|
if isinstance(to_emails, str):
|
|
self.to_emails = [to_emails]
|
|
else:
|
|
self.to_emails = to_emails
|
|
|
|
def send_notification(self, scraper_name: str, new_results: List[Dict]) -> bool:
|
|
"""Send email notification for new results"""
|
|
if not new_results:
|
|
return True
|
|
|
|
if not self.to_emails:
|
|
print("Keine Empfänger-Emails konfiguriert")
|
|
return False
|
|
|
|
try:
|
|
# Create message
|
|
msg = MIMEMultipart()
|
|
msg['From'] = self.from_email
|
|
msg['To'] = ', '.join(self.to_emails)
|
|
msg['Subject'] = f"Neue Wohnungen gefunden: {len(new_results)} neue Ergebnisse für {scraper_name}"
|
|
|
|
# Create email body
|
|
body = self._create_email_body(scraper_name, new_results)
|
|
msg.attach(MIMEText(body, 'html'))
|
|
|
|
# Send email with security settings
|
|
if self.security in ['ssl', 'ssl/tls']:
|
|
server = smtplib.SMTP_SSL(self.smtp_server, self.smtp_port)
|
|
else:
|
|
server = smtplib.SMTP(self.smtp_server, self.smtp_port)
|
|
|
|
# Apply security settings for non-SSL
|
|
if self.security in ['tls', 'starttls']:
|
|
server.starttls()
|
|
|
|
# Login if credentials provided
|
|
if self.username and self.password:
|
|
server.login(self.username, self.password)
|
|
|
|
server.send_message(msg)
|
|
server.quit()
|
|
|
|
print(f"Email-Benachrichtigung gesendet an {len(self.to_emails)} Empfänger")
|
|
return True
|
|
|
|
except Exception as e:
|
|
print(f"Fehler beim Senden der Email: {e}")
|
|
return False
|
|
|
|
def _create_email_body(self, scraper_name: str, new_results: List[Dict]) -> str:
|
|
"""Create HTML email body"""
|
|
html = f"""
|
|
<html>
|
|
<body>
|
|
<h2>🏠 Neue Wohnungen gefunden - {scraper_name}</h2>
|
|
<p><strong>Zeitpunkt:</strong> {datetime.now().strftime('%d.%m.%Y %H:%M')}</p>
|
|
<p><strong>Anzahl neuer Ergebnisse:</strong> {len(new_results)}</p>
|
|
|
|
<h3>Neue Wohnungen:</h3>
|
|
<table border="1" cellpadding="5" cellspacing="0" style="border-collapse: collapse;">
|
|
<tr style="background-color: #f0f0f0;">
|
|
<th>PLZ</th>
|
|
<th>Adresse</th>
|
|
<th>Link</th>
|
|
</tr>
|
|
"""
|
|
|
|
for result in new_results:
|
|
plz = result.get('plz', 'N/A')
|
|
address = result.get('address', 'N/A')
|
|
link = result.get('link', '#')
|
|
|
|
# Handle empty or None links
|
|
if not link or link == '#' or link == 'None':
|
|
link_display = 'Kein Link'
|
|
link_href = '#'
|
|
else:
|
|
link_display = 'Details'
|
|
link_href = link
|
|
|
|
html += f"""
|
|
<tr>
|
|
<td>{plz}</td>
|
|
<td>{address}</td>
|
|
<td><a href="{link_href}" target="_blank">{link_display}</a></td>
|
|
</tr>
|
|
"""
|
|
|
|
html += """
|
|
</table>
|
|
<br>
|
|
<p><small>Diese Nachricht wurde automatisch vom Flat Scraper gesendet.</small></p>
|
|
</body>
|
|
</html>
|
|
"""
|
|
|
|
return html
|
|
|
|
class ConsoleNotifier:
|
|
"""Console notification for testing"""
|
|
|
|
def send_notification(self, scraper_name: str, new_results: List[Dict]) -> bool:
|
|
"""Print notification to console"""
|
|
if not new_results:
|
|
return True
|
|
|
|
print(f"\n{'='*50}")
|
|
print(f"🏠 NEUE WOHNUNGEN GEFUNDEN: {scraper_name}")
|
|
print(f"Zeitpunkt: {datetime.now().strftime('%d.%m.%Y %H:%M')}")
|
|
print(f"Anzahl: {len(new_results)}")
|
|
print(f"{'='*50}")
|
|
|
|
for result in new_results:
|
|
plz = result.get('plz', 'N/A')
|
|
address = result.get('address', 'N/A')
|
|
link = result.get('link', '#')
|
|
|
|
print(f"📍 PLZ {plz}: {address}")
|
|
if link != '#':
|
|
print(f" 🔗 {link}")
|
|
print()
|
|
|
|
return True
|