Fix feedback attachments: proper MIME mixed/alternative structure
Rewrite feedback.py with correct MIMEMultipart(mixed) containing alternative text part + base64-encoded image attachments. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Dieser Commit ist enthalten in:
@@ -39,7 +39,6 @@ _user_timestamps: dict[int, list[float]] = defaultdict(list)
|
|||||||
_MAX_PER_HOUR = 3
|
_MAX_PER_HOUR = 3
|
||||||
_WINDOW = 3600
|
_WINDOW = 3600
|
||||||
|
|
||||||
|
|
||||||
_ALLOWED_TYPES = {"image/jpeg", "image/png"}
|
_ALLOWED_TYPES = {"image/jpeg", "image/png"}
|
||||||
_MAX_FILE_SIZE = 5 * 1024 * 1024 # 5 MB
|
_MAX_FILE_SIZE = 5 * 1024 * 1024 # 5 MB
|
||||||
_MAX_FILES = 3
|
_MAX_FILES = 3
|
||||||
@@ -105,16 +104,32 @@ async def send_feedback(
|
|||||||
</div>
|
</div>
|
||||||
</div>"""
|
</div>"""
|
||||||
|
|
||||||
msg = MIMEMultipart("alternative")
|
msg = MIMEMultipart("mixed")
|
||||||
msg["From"] = f"{SMTP_FROM_NAME} <{SMTP_FROM_EMAIL}>"
|
msg["From"] = f"{SMTP_FROM_NAME} <{SMTP_FROM_EMAIL}>"
|
||||||
msg["To"] = FEEDBACK_EMAIL
|
msg["To"] = FEEDBACK_EMAIL
|
||||||
msg["Subject"] = subject
|
msg["Subject"] = subject
|
||||||
if email:
|
if email:
|
||||||
msg["Reply-To"] = email
|
msg["Reply-To"] = email
|
||||||
|
|
||||||
|
# Text-Teil (alternative: plain + html)
|
||||||
|
text_part = MIMEMultipart("alternative")
|
||||||
text_fallback = f"Feedback von {display_name} ({category_label}):\n\n{message}"
|
text_fallback = f"Feedback von {display_name} ({category_label}):\n\n{message}"
|
||||||
msg.attach(MIMEText(text_fallback, "plain", "utf-8"))
|
text_part.attach(MIMEText(text_fallback, "plain", "utf-8"))
|
||||||
msg.attach(MIMEText(html_body, "html", "utf-8"))
|
text_part.attach(MIMEText(html_body, "html", "utf-8"))
|
||||||
|
msg.attach(text_part)
|
||||||
|
|
||||||
|
# Bild-Anhaenge
|
||||||
|
for f in files:
|
||||||
|
file_data = await f.read()
|
||||||
|
if len(file_data) > _MAX_FILE_SIZE:
|
||||||
|
raise HTTPException(status_code=422, detail=f"Datei {f.filename} ist groesser als 5 MB.")
|
||||||
|
sub_type = (f.content_type or "image/jpeg").split("/")[1]
|
||||||
|
attachment = MIMEBase("image", sub_type)
|
||||||
|
attachment.set_payload(file_data)
|
||||||
|
encoders.encode_base64(attachment)
|
||||||
|
attachment.add_header("Content-Disposition", "attachment", filename=f.filename or "bild.jpg")
|
||||||
|
msg.attach(attachment)
|
||||||
|
logger.debug(f"Anhang: {f.filename} ({len(file_data)} Bytes, {f.content_type})")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
await aiosmtplib.send(
|
await aiosmtplib.send(
|
||||||
@@ -126,7 +141,7 @@ async def send_feedback(
|
|||||||
start_tls=SMTP_USE_TLS,
|
start_tls=SMTP_USE_TLS,
|
||||||
)
|
)
|
||||||
_user_timestamps[user_id].append(now)
|
_user_timestamps[user_id].append(now)
|
||||||
logger.info(f"Feedback von {display_name} ({category_label}) gesendet")
|
logger.info(f"Feedback von {display_name} ({category_label}) gesendet, {len(files)} Anhaenge")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"Feedback-E-Mail fehlgeschlagen: {e}")
|
logger.error(f"Feedback-E-Mail fehlgeschlagen: {e}")
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
|
|||||||
In neuem Issue referenzieren
Einen Benutzer sperren