如何用Python在邮件中嵌入含多媒体的完整推文?
解决邮件中嵌入完整推文(含图片/视频)的问题
邮件客户端会默认阻止外部JavaScript执行,你之前使用的Twitter widgets.js脚本根本不会运行,因此只能显示blockquote里的纯文本,无法渲染推文样式和媒体内容。以下是两种可行的解决方案:
方案一:基于Twitter oEmbed静态渲染 + 内嵌媒体
通过Tweepy获取不带JS的推文HTML,手动添加样式并将媒体资源内嵌到邮件中,确保邮件客户端能直接加载内容。
步骤及代码
- 安装依赖库:
pip install tweepy requests beautifulsoup4
- 完整代码:
import smtplib from email.mime.text import MIMEText from email.mime.multipart import MIMEMultipart from email.mime.image import MIMEImage import tweepy import requests from bs4 import BeautifulSoup # Twitter API 配置(需提前申请开发者账号) TWITTER_API_KEY = "你的API_KEY" TWITTER_API_SECRET = "你的API_SECRET" TWITTER_BEARER_TOKEN = "你的BEARER_TOKEN" # 邮件配置 sender_email = "你的发件邮箱" receiver_email = "收件邮箱" password = "邮箱密码/应用专用密码" # 初始化Tweepy客户端 client = tweepy.Client(bearer_token=TWITTER_BEARER_TOKEN) # 目标推文ID tweet_id = "1509206476874784769" # 获取不带JS的oEmbed数据 oembed = client.get_oembed(tweet_id, omit_script=True, theme="light") tweet_html = oembed.data["html"] # 解析推文HTML,提取图片媒体 soup = BeautifulSoup(tweet_html, "html.parser") media_elements = soup.find_all("img", class_="twitter-tweet-media") media_attachments = [] # 下载图片并转为邮件内嵌附件 for idx, img in enumerate(media_elements): media_url = img["src"] img_data = requests.get(media_url).content # 创建内嵌图片对象,设置唯一Content-ID img_part = MIMEImage(img_data) img_cid = f"tweet_media_{idx}" img_part.add_header("Content-ID", f"<{img_cid}>") img_part.add_header("Content-Disposition", "inline", filename=f"{img_cid}.jpg") media_attachments.append(img_part) # 替换HTML中的图片链接为内嵌引用 img["src"] = f"cid:{img_cid}" # 添加Twitter推文的基础样式,还原排版 tweet_css = """ <style> .twitter-tweet { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; border: 1px solid #e1e8ed; border-radius: 16px; padding: 16px; max-width: 550px; } .twitter-tweet p { font-size: 15px; line-height: 20px; color: #14171a; margin: 0 0 12px; } .twitter-tweet a { color: #1da1f2; text-decoration: none; } .twitter-tweet img { border-radius: 12px; max-width: 100%; height: auto; } </style> """ # 组装最终HTML内容 final_html = f""" <html> <body> {tweet_css} {str(soup)} </body> </html> """ # 创建邮件容器(使用related类型支持内嵌资源) message = MIMEMultipart("related") message["Subject"] = "嵌入完整推文测试" message["From"] = sender_email message["To"] = receiver_email # 添加纯文本 fallback message.attach(MIMEText("请使用支持HTML的邮件客户端查看完整推文", "plain")) # 添加HTML内容 message.attach(MIMEText(final_html, "html")) # 附加内嵌媒体 for attachment in media_attachments: message.attach(attachment) # 发送邮件 with smtplib.SMTP('smtp.office365.com', 587) as server: server.ehlo() server.starttls() server.ehlo() server.login(sender_email, password) server.send_message(message)
关键说明
- 使用
MIMEMultipart("related")替代alternative,支持内嵌资源引用 omit_script=True获取无需JS渲染的基础HTML- 通过Content-ID(cid)将图片内嵌到邮件,避免外部链接被拦截
- 自定义CSS还原Twitter推文的排版样式
方案二:无头浏览器截图嵌入(简单高效)
用无头浏览器渲染完整推文并截图,将图片嵌入邮件,完全还原推文样式,适合静态展示需求。
步骤及代码
- 安装依赖库:
pip install playwright playwright install chromium
- 完整代码:
import smtplib from email.mime.text import MIMEText from email.mime.multipart import MIMEMultipart from email.mime.image import MIMEImage from playwright.sync_api import sync_playwright # 邮件配置 sender_email = "你的发件邮箱" receiver_email = "收件邮箱" password = "邮箱密码/应用专用密码" # 目标推文链接 tweet_url = "https://twitter.com/Twitter/status/1509206476874784769" # 无头浏览器截取推文截图 with sync_playwright() as p: browser = p.chromium.launch(headless=True) page = browser.new_page() page.goto(tweet_url) # 等待推文元素加载完成 page.wait_for_selector("article[data-testid='tweet']") # 截取推文区域的截图 tweet_element = page.query_selector("article[data-testid='tweet']") tweet_screenshot = tweet_element.screenshot() browser.close() # 创建邮件容器 message = MIMEMultipart("related") message["Subject"] = "推文截图嵌入测试" message["From"] = sender_email message["To"] = receiver_email # 添加纯文本 fallback message.attach(MIMEText("请使用支持HTML的邮件客户端查看推文截图", "plain")) # 嵌入截图到HTML img_part = MIMEImage(tweet_screenshot) img_part.add_header("Content-ID", "<tweet_screenshot>") message.attach(img_part) final_html = f""" <html> <body> <img src="cid:tweet_screenshot" alt="完整推文" style="max-width: 100%;"> </body> </html> """ message.attach(MIMEText(final_html, "html")) # 发送邮件 with smtplib.SMTP('smtp.office365.com', 587) as server: server.ehlo() server.starttls() server.ehlo() server.login(sender_email, password) server.send_message(message)
优缺点
- 优点:无需处理API和媒体解析,完全还原推文样式(包括表情、排版)
- 缺点:视频仅能显示第一帧,需额外安装浏览器组件
内容的提问来源于stack exchange,提问作者Santi
相关产品推荐
相关产品推荐

