python - 使用python 3.7,如何确保正确修改正文内容后正确重新生成已解析的电子邮件而不丢失任何内容?

标签 python email

我想解析(序列化)多部分电子邮件(或具有内嵌图像、附件等的多个电子邮件附件的任何和所有类型),使用一些额外信息设置其正文内容类型,并在发送之前重新生成电子邮件出来。如何用最简单的Python代码来实现这一点呢?使用Python 3.6版本。 现在我正在使用 email.walk() 并获取第一个可用的 text/plain、text/html 并假设它是覆盖邮件的正文,通过 walk() 进一步递归地解析邮件的不同部分...这看起来很麻烦。有什么简单的方法吗? 添加我正在尝试的代码片段: #!/usr/bin/python3 ”“” 用法: 从命令行:cat mail | python warning_mail_stdout.py

此脚本从标准输入读取邮件并在邮件正文中附加“警告” 并将附加邮件打印到标准输出 “”“

import imaplib
import email
import logging
import smtplib
import re

from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
# from subprocess import Popen, PIPE
import sys
import email, os

title = ''
logger = logging.getLogger()
handler = logging.StreamHandler()
formatter = logging.Formatter(
    '%(asctime)s %(name)-12s %(levelname)-8s %(message)s')
handler.setFormatter(formatter)
logger.addHandler(handler)
logger.setLevel(logging.INFO)

from email.policy import default

from email import policy
from email.parser import BytesParser
from email.mime.message import MIMEMessage
parser = email.parser.Parser()

def login():
    # Read message from Std Input
    mail = BytesParser(policy=policy.default).parse(open('1email_sample.eml','rb'))
    if mail is None:
        print("No mail in stdin ...")
    else:
        #mail is not None:
        mbody = ''
        mhtml = ''
        text_body = ''
        mail_charset = None
        html_body = ''
        mail_from = email.utils.parseaddr(mail['From'])[1]
        mwarn = ''
        new_message = ''
        attached_bool = False
        mail_attached_bool = False
        h=p=related_body=None
        h_body=plain_body = None
        new_message1 = email.message.EmailMessage()#policy=default)
        warning_txt = "[Caution: This message came from an external domain.]" 
        new_message = email.message.EmailMessage()
        
        # copying header values
        for header_val in mail:
            parser.parsestr(header_val)
            new_message[header_val] = mail[header_val]
            print(new_message[header_val])

        mailbody = mail.get_body(preferencelist=('related', 'html', 'plain'))

        new_message1.attach(mailbody)
        
        new_message.set_type('multipart/related')
        new_message.attach(new_message1)

        for p  in mail.iter_attachments():
            if p.is_attachment(): 
                new_message.attach(p)

        recipients = [
                      "<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="25564d441216655c444d4a4a0b464a48" rel="noreferrer noopener nofollow">[email protected]</a>",
        ]

         # s  ---is the smtp server to send out mail
        #'''
        try:
            print(new_message.get_content_type(), 'vvvvv sent')
            s.sendmail(mail_from, recipients,bytes(new_message))
        except UnicodeEncodeError:
            s.sendmail(mail_from, recipients,
                       new_message.as_string().encode("utf-8"))
        #'''
        s.close()

if __name__ == "__main__":
    login()

最佳答案

如果您只想更改 body 部位的某些内容,您甚至不需要 walk 方法。 get_body 可以为您完成这项工作,尽管它可能会对某些不合规的消息产生意外的结果,但它可能比您或我能想到的任何东西都要可靠得多。 所以你的程序流程应该是

  • 使用解析器对象构建树
  • 可能会检查defects属性以确保该消息适合您
  • 在树上调用 get_body
  • get_body 返回的 mime 部分执行您需要的操作
  • 使用生成器对象序列化树

我在这里添加一些示例。不幸的是,文档还很不清楚,所以也许这会有所帮助:

>>> from email.message import EmailMessage
>>> import email.policy
>>> from email import message_from_binary_file

>>> msgin = open('1email_sample.eml', 'rb')      
>>> msg = message_from_binary_file(msgin, policy=email.policy.default)
>>> for part in msg.walk():
        print(part.get_content_type())       
multipart/related
multipart/alternative
text/plain
text/html
image/png
image/png
image/png
image/png
image/png
image/png
image/png

>>> body = msg.get_body('plain') ##get the plain text, not 'related'
>>> btext = body.get_payload()
>>> type(btext)
<class 'str'>
>>> len(btext)
6926
>>> body.set_payload('this is my message' + btext)
>>> len(body.get_payload())
6944

>>> body2=msg.get_body('html') ##same with html
>>> bhtml=body2.get_payload()
>>> type(bhtml)
<class 'str'>

关于python - 使用python 3.7,如何确保正确修改正文内容后正确重新生成已解析的电子邮件而不丢失任何内容?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67919536/

相关文章:

python - Scrapy response.replace编码错误

python - Tensorflow:tf.gfile.Exist 和 Env::FileExists 返回 True,文件名为空

email - 553 5.1.3 收件人地址不是有效的 RFC-5321 地址

java - java 中的 gmail imap 错误的未知命令

c# - SMTP 发送邮件已取消

python - 如何解决 Python fork 进程中 OpenSSL 的 PRNG 限制?

python - SQLAlchemy 一对一关系

python - 如何模拟异步协程?

java - 如何知道邮件是否真的发送?

java - 检测文本中的电子邮件并用 <a> 标记将其包围