Spaces:
Runtime error
Runtime error
Upload 18 files
Browse files- emailer.py +43 -2
emailer.py
CHANGED
|
@@ -60,6 +60,47 @@ def _sender_address(sender: str) -> str:
|
|
| 60 |
return formataddr((str(Header("Chan Compass", "utf-8")), sender))
|
| 61 |
|
| 62 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 63 |
def _inline_md(s: str) -> str:
|
| 64 |
s = html.escape(s)
|
| 65 |
s = re.sub(r"\*\*(.+?)\*\*", r"<strong>\1</strong>", s)
|
|
@@ -159,7 +200,7 @@ def _send_via_resend(recipients: list, subject: str, content: str) -> str:
|
|
| 159 |
"from": RESEND_FROM,
|
| 160 |
"to": recipients,
|
| 161 |
"subject": subject,
|
| 162 |
-
"text": content,
|
| 163 |
"html": _md_to_html(content),
|
| 164 |
}).encode("utf-8")
|
| 165 |
req = urllib.request.Request(
|
|
@@ -190,7 +231,7 @@ def _send_via_smtp(recipients: list, subject: str, content: str) -> str:
|
|
| 190 |
msg["Subject"] = Header(subject, "utf-8")
|
| 191 |
msg["From"] = _sender_address(EMAIL_SENDER)
|
| 192 |
msg["To"] = ", ".join(recipients)
|
| 193 |
-
msg.attach(MIMEText(content, "plain", "utf-8"))
|
| 194 |
msg.attach(MIMEText(_md_to_html(content), "html", "utf-8"))
|
| 195 |
domain = EMAIL_SENDER.split("@")[-1].lower()
|
| 196 |
sc = SMTP_CONFIGS.get(domain, {"server": f"smtp.{domain}", "port": 465, "ssl": True})
|
|
|
|
| 60 |
return formataddr((str(Header("Chan Compass", "utf-8")), sender))
|
| 61 |
|
| 62 |
|
| 63 |
+
def _md_to_plain(text: str) -> str:
|
| 64 |
+
"""Markdown -> readable plain text (for the text/plain MIME part and the
|
| 65 |
+
Resend `text` field). Strips #/**/| noise so text-only clients look clean."""
|
| 66 |
+
lines, out = text.split("\n"), []
|
| 67 |
+
i, n = 0, len(lines)
|
| 68 |
+
while i < n:
|
| 69 |
+
line = lines[i]
|
| 70 |
+
if "|" in line and i + 1 < n and re.match(r"^\s*\|?[\s:\-|]+\|?\s*$", lines[i + 1]):
|
| 71 |
+
header = [c.strip() for c in line.strip().strip("|").split("|")]
|
| 72 |
+
i += 2
|
| 73 |
+
while i < n and "|" in lines[i]:
|
| 74 |
+
cells = [c.strip() for c in lines[i].strip().strip("|").split("|")]
|
| 75 |
+
if len(header) == 2 and len(cells) == 2:
|
| 76 |
+
out.append(f" {cells[0]}: {cells[1]}")
|
| 77 |
+
else:
|
| 78 |
+
out.append(" " + " | ".join(cells))
|
| 79 |
+
i += 1
|
| 80 |
+
out.append("")
|
| 81 |
+
continue
|
| 82 |
+
m = re.match(r"^(#{1,4})\s+(.*)$", line)
|
| 83 |
+
if m:
|
| 84 |
+
title = m.group(2).strip()
|
| 85 |
+
out.append("")
|
| 86 |
+
out.append(title.upper() if len(m.group(1)) <= 2 else title)
|
| 87 |
+
out.append("-" * min(len(title), 60))
|
| 88 |
+
i += 1
|
| 89 |
+
continue
|
| 90 |
+
if line.strip() in ("---", "***", "___"):
|
| 91 |
+
out.append("-" * 40)
|
| 92 |
+
i += 1
|
| 93 |
+
continue
|
| 94 |
+
s = re.sub(r"\*\*(.+?)\*\*", r"\1", line)
|
| 95 |
+
s = re.sub(r"`(.+?)`", r"\1", s)
|
| 96 |
+
s = re.sub(r"\[(.+?)\]\((https?://[^\s)]+)\)", r"\1 (\2)", s)
|
| 97 |
+
s = re.sub(r"^_(.+)_$", r"\1", s.strip())
|
| 98 |
+
out.append(s)
|
| 99 |
+
i += 1
|
| 100 |
+
txt = "\n".join(out)
|
| 101 |
+
return re.sub(r"\n{3,}", "\n\n", txt).strip()
|
| 102 |
+
|
| 103 |
+
|
| 104 |
def _inline_md(s: str) -> str:
|
| 105 |
s = html.escape(s)
|
| 106 |
s = re.sub(r"\*\*(.+?)\*\*", r"<strong>\1</strong>", s)
|
|
|
|
| 200 |
"from": RESEND_FROM,
|
| 201 |
"to": recipients,
|
| 202 |
"subject": subject,
|
| 203 |
+
"text": _md_to_plain(content),
|
| 204 |
"html": _md_to_html(content),
|
| 205 |
}).encode("utf-8")
|
| 206 |
req = urllib.request.Request(
|
|
|
|
| 231 |
msg["Subject"] = Header(subject, "utf-8")
|
| 232 |
msg["From"] = _sender_address(EMAIL_SENDER)
|
| 233 |
msg["To"] = ", ".join(recipients)
|
| 234 |
+
msg.attach(MIMEText(_md_to_plain(content), "plain", "utf-8"))
|
| 235 |
msg.attach(MIMEText(_md_to_html(content), "html", "utf-8"))
|
| 236 |
domain = EMAIL_SENDER.split("@")[-1].lower()
|
| 237 |
sc = SMTP_CONFIGS.get(domain, {"server": f"smtp.{domain}", "port": 465, "ssl": True})
|