Python SMTP/MIME 消息正文

Posted

技术标签:

【中文标题】Python SMTP/MIME 消息正文【英文标题】:Python SMTP/MIME Message body 【发布时间】:2015-09-01 09:28:40 【问题描述】:

我已经为此工作了 2 天,并设法获得了这个带有 pcapng 文件的脚本以发送,但我似乎无法让邮件正文出现在电子邮件中。

import smtplib
import base64
import ConfigParser
#from email.MIMEapplication import MIMEApplication
#from email.MIMEmultipart import MIMEMultipart
#from email.MIMEtext import MIMEText
#from email.utils import COMMASPACE, formatdate

Config = ConfigParser.ConfigParser()
Config.read('mailsend.ini')

filename = "test.pcapng"

fo = open(filename, "rb")
filecontent = fo.read()
encoded_content = base64.b64encode(filecontent)  # base 64

sender = 'notareal@email.com'  # raw_input("Sender: ")
receiver = 'someother@fakeemail.com'  # raw_input("Recipient: ")

marker = raw_input("Please input a unique set of numbers that will not be found elsewhere in the message, ie- roll face: ")

body ="""
This is a test email to send an attachment.
"""

# Define the main headers
header = """ From: From Person <notareal@email.com>
To: To Person <someother@fakeemail.com>
Subject: Sending Attachment
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary=%s
--%s
""" % (marker, marker)

# Define message action
message_action = """Content-Type: text/plain
Content-Transfer-Encoding:8bit

%s
--%s
""" % (body, marker)

# Define the attachment section
message_attachment = """Content-Type: multipart/mixed; name=\"%s\"
Content-Transfer-Encoding:base64
Content-Disposition: attachment; filename=%s

%s
--%s--
""" % (filename, filename, encoded_content, marker)

message = header + message_action + message_attachment

try:
    smtpObj = smtplib.SMTP('smtp.gmail.com')
    smtpObj.sendmail(sender, receiver, message)
    print "Successfully sent email!"
except Exception:
    print "Error: unable to send email"

我的目标是最终让这个脚本在从配置文件中读取参数后发送一封电子邮件,并附上一个 pcapng 文件以及一些描述wireshark事件的其他文本数据。电子邮件在发送时未显示邮件正文。 pcapng 文件现在只是一个充满虚假 ip 和子网的测试文件。邮件正文哪里出错了?

def mail_man():
    if ms == 'Y' or ms == 'y' and ms_maxattach <= int(smtp.esmtp_features['size']):
        fromaddr = [ms_from]
        toaddr = [ms_sendto]
        cc = [ms_cc]
        bcc = [ms_bcc]

        msg = MIMEMultipart()

        body = "\nYou're captured event is attached. \nThis is an automated email generated by Dumpcap.py"

        msg.attach("From: %s\r\n" % fromaddr
        + "To: %s\r\n" % toaddr
        + "CC: %s\r\n" % ",".join(cc)
        + "Subject: %s\r\n" % ms_subject
        + "X-Priority = %s\r\n" % ms_importance
        + "\r\n"
        + "%s\r\n" % body
        + "%s\r\n" % ms_pm)
        toaddrs = [toaddr] + cc + bcc

        msg.attach(MIMEText(body, 'plain'))

        filename = "dcdflts.cong"
        attachment = open(filename, "rb")

        if ms_attach == 'y' or ms_attach == "Y":
            part = MIMEBase('application', 'octet-stream')
            part.set_payload(attachment.read())
            encoders.encode_base64(part)
            part.add_header('Content-Disposition', "attachment; filename= %s" % filename)
            msg.attach(part)

        server = smtplib.SMTP(ms_smtp_server[ms_smtp_port])
        server.starttls()
        server.login(fromaddr, "YOURPASSWORD")
        text = msg.as_string()
        server.sendmail(fromaddr, toaddrs, text)
        server.quit()

这是我的第二次尝试,所有“ms_...”变量都是通过更大的程序全局的。

【问题讨论】:

我的猜测是你的字符串在你连接它们之后丢失了一些非常重要的东西。我建议您使用已注释掉的 mime 模块创建消息。 docs.python.org/2/library/email-examples.html 使用 MIME 而不是 smtplib 有什么好处吗?我找到的有关 MIME 模块的资源并不是很有帮助。 【参考方案1】:

您不应该重新发明***。使用 Python 包含在标准库中的 mime 模块,而不是尝试自己创建标头。我无法对其进行测试,但请检查它是否有效:

import smtplib
import base64
import ConfigParser
from email.mime.application import MIMEApplication
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText

filename = "test.pcapng"

with open(filename, 'rb') as fo:
    filecontent = fo.read()
    encoded_content = base64.b64encode(filecontent)

sender = 'notareal@email.com'  # raw_input("Sender: ")
receiver = 'someother@fakeemail.com'  # raw_input("Recipient: ")

marker = raw_input("Please input a unique set of numbers that will not be found elsewhere in the message, ie- roll face: ")

body ="""
This is a test email to send an attachment.
"""

message = MIMEMultipart(
    From=sender,
    To=receiver,
    Subject='Sending Attachment')

message.attach(MIMEText(body))          # body of the email

message.attach(MIMEApplication(
    encoded_content,
    Content_Disposition='attachment; filename="0"'.format(filename))  # b64 encoded file
    )

try:
    smtpObj = smtplib.SMTP('smtp.gmail.com')
    smtpObj.sendmail(sender, receiver, message)
    print "Successfully sent email!"
except Exception:
    print "Error: unable to send email"

我省略了一些部分(如ConfigParser 变量),只演示了与电子邮件相关的部分。

参考资料:

How to send email attachments with Python

【讨论】:

我发现的关于 python 的 SMTP/MIME 模块的每一个资源都让像我这样的 python 新手非常困惑,而且它们都不同。稍后我将编辑我的帖子以显示我的第二次尝试。【参考方案2】:

想通了,添加了 ConfigParser。这是一个 .ini 文件的完整功能

import smtplib
####import sys#### duplicate
from email.parser import Parser
from email.mime.image import MIMEImage
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.base import MIMEBase
from email import encoders
import ConfigParser


def mail_man(cfg_file, event_file):
    # Parse email configs from cfg file
    Config = ConfigParser.ConfigParser()
    Config.read(str(cfg_file))

    mail_man_start = Config.get('DC_MS', 'ms')
    security = Config.get('DC_MS', 'ms_security')
    add_attachment = Config.get('DC_MS', 'ms_attach')
    try:
        if mail_man_start == "y" or mail_man_start == "Y":
            fromaddr = Config.get("DC_MS", "ms_from")
            addresses = [Config.get("DC_MS", "ms_sendto")] + [Config.get("DC_MS", "ms_cc")] + [Config.get("DC_MS", "ms_bcc")]

            msg = MIMEMultipart()  # creates multipart email
            msg['Subject'] = Config.get('DC_MS', 'ms_subject')  # sets up the header
            msg['From'] = Config.get('DC_MS', 'ms_from')
            msg['To'] = Config.get('DC_MS', 'ms_sendto')
            msg['reply-to'] = Config.get('DC_MS', 'ms_replyto')
            msg['X-Priority'] = Config.get('DC_MS', 'ms_importance')
            msg['CC'] = Config.get('DC_MS', 'ms_cc')
            msg['BCC'] = Config.get('DC_MS', 'ms_bcc')
            msg['Return-Receipt-To'] = Config.get('DC_MS', 'ms_rrr')
            msg.preamble = 'Event Notification'

            message = '... use this to add a body to the email detailing event. dumpcap.py location??'
            msg.attach(MIMEText(message))   # attaches body to email

            # Adds attachment if ms_attach = Y/y
            if add_attachment == "y" or add_attachment == "Y":
                attachment = open(event_file, "rb")
                # Encodes the attachment and adds it to the email
                part = MIMEBase('application', 'octet-stream')
                part.set_payload(attachment.read())
                encoders.encode_base64(part)
                part.add_header('Content-Disposition', "attachment; filename = %s" % event_file)

                msg.attach(part)
            else:
                print "No attachment sent."

            server = smtplib.SMTP(Config.get('DC_MS', 'ms_smtp_server'), Config.get('DC_MS', 'ms_smtp_port'))
            server.ehlo()
            server.starttls()
            if security == "y" or security == "Y":
                server.login(Config.get('DC_MS', 'ms_user'), Config.get('DC_MS', 'ms_password'))
            text = msg.as_string()
            max_size = Config.get('DC_MS', 'ms_maxattach')
            msg_size = sys.getsizeof(msg)
            if msg_size <= max_size:
                server.sendmail(fromaddr, addresses, text)
            else:
                print "Your message exceeds maximum attachment size.\n Please Try again"
            server.quit()
            attachment.close()
        else:
            print "Mail_man not activated"
    except:
       print "Error! Something went wrong with Mail Man. Please try again."

【讨论】:

以上是关于Python SMTP/MIME 消息正文的主要内容,如果未能解决你的问题,请参考以下文章

Python:如何更改 smtp/MIME 脚本中的“to”字段而不是添加一个新字段?

使用GAE python接收邮件,但是邮件正文中包含意外信息

原生socket请求url获取状态码消息报头响应正文

PEAR 邮件 SMTP/MIME 和 HTML 格式

反序列化操作“queryAll”消息的回复消息正文时出错:

Apache Camel Azure 队列:发送消息时消息正文为空