如何使用 python gmail API(有效)将超链接插入现有电子邮件(通过插入/删除 API 函数)而不被破坏?

问题描述 投票:0回答:1

我正在尝试编写一个能够有效地将超链接添加到现有电子邮件的脚本。我已经有了一个类似的脚本,可以有效地调整现有电子邮件中大图像的大小以节省空间。

我通过检索电子邮件,编辑检索到的副本,用相同的

threadId
将其写回(尽管gmail分配了一个新的id),并删除带有原始id的电子邮件来实现对电子邮件的编辑,所以就这样了左边是修改后的副本,与原始副本位于同一位置。

但是当我尝试添加超链接并在gmail web界面中查看最终结果时,它是不可点击的,我在gmail的显示原始功能中看到的是这样的:

<a href"http://testurl.com">testurl text</a>

即href 后面的等号缺失,其他一切都很好。

按照 GMail python 快速入门文档 设置服务并在名为 query 的变量中设置查询参数后,执行的代码如下所示:

# get content of first email matching query criteria
results = service.users().messages().list(userId='me', q=query, maxResults = 500).execute()
fullmsg = service.users().messages().get(userId='me', id=results['messages'][0]['id'], format='raw').execute()
unencoded = base64.urlsafe_b64decode(fullmsg['raw']).decode('utf-8')
mmsg = email.message_from_string(unencoded)

# find text/html part, and add link to start of html body using BeautifulSoup
for part in mmsg.walk():
    if part.get_content_type() == 'text/html':
        soup = BeautifulSoup(part.get_payload(), features='lxml')
        linkTag = soup.new_tag('a', href='http://testurl.com')
        linkTag.append("testurl text")
        soup.body.insert(0,linkTag)
        part.set_payload(str(soup))
encmsg = base64.urlsafe_b64encode(mmsg.as_string().encode('utf-8'))

# Add a label to indicate this email has been processed already (so query will exclude it from future searches) and write altered copy back to the server, deleting the original email
newLabels = fullmsg['labelIds'] + [doneLabelID]
fixedMsg = { 'raw' : encmsg.decode(), 'labelIds' : newLabels, 'threadId' : fullmsg['threadId'] }
response = service.users().messages().insert(userId='me', body=fixedMsg, internalDateSource='dateHeader').execute()
service.users().messages().delete(userId='me', id=results['messages'][0]['id']).execute()          

pdb 在检查不同点的更改后的主体时给出了令人鼓舞的结果,就像在执行上述命令后运行以下命令一样:

fromg = service.users().messages().get(userId='me', id=response['id'], format='raw').execute()
unenc = base64.urlsafe_b64decode(fromg['raw']).decode('utf-8')
gmmsg = email.message_from_string(unenc)
for part in gmmsg.walk(): 
    if part.get_content_type() == 'text/html':
        print(part)

此时,将副本写回服务器并通过 API 检索该电子邮件后,打印文本中的锚标记包含内容 href='http://testurl.com'。但是,当在 Gmail 网络界面中查看电子邮件时,如上所述,链接文本(“testurl 文本”)仅显示为普通文本。通过显示原始href查看源缺少等号,并转发电子邮件,查看thunderbird中的消息源并b64解码编码的文本/html段仅显示锚标记包含的文本(“testurl文本”) - 锚标记本身完全丢失(可能是由于 href 属性格式不正确而被 gmail 删除?)。

我也尝试过不涉及 BeautifulSoup(手动插入锚标签),以防它引入一些奇怪的东西,但这没有什么区别。

如果有人知道是什么原因导致 gmail 在 Gmail Web 界面中查看或转发这些邮件时损坏这些邮件(但在通过 API 访问邮件时不这样做),我们将不胜感激。


编辑:对于在 gmail Web 界面中编写的简单 html 电子邮件,问题并不明显 - 该电子邮件可以通过上述代码添加链接,而无需进行修改。不过,从我们的合作伙伴业务(我最初正在测试)收到的更复杂的 html 电子邮件确实表现出了这个问题。

有效的简单电子邮件有

Content-Type: text/html; charset="UTF-8"
,来自合作伙伴业务的不起作用的电子邮件有
Content-Type: text/html; charset=UTF-8\nContent-Transfer-Encoding: quoted-printable
,并且看起来很奇怪,您希望在 html 内容中看到等号,即
<meta charset"utf-8" content'3D"text/html;' http-equiv'3D"Content-Type"= '/>
。不确定这是否是问题的一部分。尝试将我的链接写为
<a href'3D"http://testurl.com"'>Test text</a>
来模仿它,但是虽然它显示为显示原始内容中所写的内容,但它仍然没有产生可点击的链接。

python gmail
1个回答
0
投票

事实证明内容传输编码是关键,我需要将锚标记编写为

<a href=3D"http://testurl.com">test text</a>
。据推测,我们的合作伙伴企业发送的电子邮件未按预期显示,因为他们尝试正确编码等号,结果为“3D”而不是“=3D”。

© www.soinside.com 2019 - 2024. All rights reserved.