如何在不使用smtplib的情况下使用Python在嵌入式图像文件中发送电子邮件?

时间:2016-03-12 21:44:11

标签: python sockets email

我目前正在开发一个项目,在该项目中,我使用Python的默认库和套接字编程(MAIL FROM,RCPT TO,DATA等)而不是smtplib来构建邮件客户端。我尝试通过套接字连接发送图像作为二进制文件:

if file_path != '':
    imageFile = open(file_path, 'rb')
    client_socket.send(imageFile.read())

这没有用。然后我尝试制作一个我可以在没有smtplib的情况下发送的MIME消息:

def create_message(from_var, to_var, cc_var, subject_var, message, file_path):
    # Create the root message and fill in the from, to, and subject headers
    msgRoot = MIMEMultipart('related')
    msgRoot['Subject'] = subject_var
    msgRoot['From'] = from_var
    msgRoot['To'] = to_var
    msgRoot.preamble = 'This is a multi-part message in MIME format.'

    # Encapsulate the plain and HTML versions of the message body in an
    # 'alternative' part, so message agents can decide which they want to display.
    msgAlternative = MIMEMultipart('alternative')
    msgRoot.attach(msgAlternative)

    msgText = MIMEText(message)
    msgAlternative.attach(msgText)

    # We reference the image in the IMG SRC attribute by the ID we give it below
    msgText = MIMEText(message + '<img src="cid:' + file_path + '">', 'html')
    msgAlternative.attach(msgText)

    # This example assumes the image is in the current directory
    fp = open(file_path, 'rb')
    msgImage = MIMEImage(fp.read())
    fp.close()

    # Define the image's ID as referenced above
    msgImage.add_header('Content-ID', '<' + file_path + '>')
    msgRoot.attach(msgImage)

    return msgRoot.as_string()

取自this question。不幸的是,这也没有用,返回错误堆栈:

Exception in Tkinter callback
Traceback (most recent call last):
  File "C:\Python27\lib\lib-tk\Tkinter.py", line 1486, in __call__
    return self.func(*args)
  File "C:/Users/Archer/Google Drive/PycharmProjects/SMTPClient/SMTPClient.py", line 209, in <lambda>
    toVariable.get(), ccVariable.get(), subjectVariable.get(), textEntry.get('1.0', 'end-1c'), gFilePath))
  File "C:/Users/Archer/Google Drive/PycharmProjects/SMTPClient/SMTPClient.py", line 164, in validate_input
    send_mail(mail_server, from_val, to_arr, cc_arr, subject_val, message, val_filePath)
  File "C:/Users/Archer/Google Drive/PycharmProjects/SMTPClient/SMTPClient.py", line 117, in send_mail
    client_socket.send(create_message(from_var, to_var, cc_var, subject_var, message, file_path))
  File "C:/Users/Archer/Google Drive/PycharmProjects/SMTPClient/SMTPClient.py", line 50, in create_message
    return msgRoot.as_string()
  File "C:\Python27\lib\email\message.py", line 137, in as_string
    g.flatten(self, unixfrom=unixfrom)
  File "C:\Python27\lib\email\generator.py", line 83, in flatten
    self._write(msg)
  File "C:\Python27\lib\email\generator.py", line 115, in _write
    self._write_headers(msg)
  File "C:\Python27\lib\email\generator.py", line 164, in _write_headers
    v, maxlinelen=self._maxheaderlen, header_name=h).encode()
  File "C:\Python27\lib\email\header.py", line 410, in encode
    value = self._encode_chunks(newchunks, maxlinelen)
  File "C:\Python27\lib\email\header.py", line 370, in _encode_chunks
    _max_append(chunks, s, maxlinelen, extra)
  File "C:\Python27\lib\email\quoprimime.py", line 97, in _max_append
    L.append(s.lstrip())
AttributeError: 'list' object has no attribute 'lstrip'

我使用Tkinter作为GUI,但我认为当我调用msgRoot.as_string()时问题就开始了。我现在只是输了,所以任何帮助都会非常感激。

2 个答案:

答案 0 :(得分:2)

使用yagmail为您处理图像会更容易。完全披露:我是开发人员。

import yagmail
yag = yagmail.SMTP(from_var, 'yourpassword')
yag.send(to_var, subject_var, contents = [message, file_path])

请注意,这会发送文字message,然后是file_path神奇地加载的图片。

您必须先安装它:

pip install yagmail

对于其他不错的功能,请查看github上的readme

答案 1 :(得分:0)

在这种情况下,似乎msgRoot.preamble以及MIMEMultipart()的构造函数中的“相关”输入和备用HTML文本在将消息压缩为单个字符串时会出现问题。如果其他人遇到这个问题,我已经包含了我的固定代码:

def create_message(from_var, to_var, cc_var, subject_var, message, file_path):
    # Create the root message and fill in the from, to, and subject headers
    msgRoot = MIMEMultipart()
    msgRoot['Subject'] = subject_var
    msgRoot['To'] = ','.join(to_var)
    msgRoot['From'] = from_var

    if cc_var != '':
        msgRoot['CC'] = ','.join(cc_var)

    msgText = MIMEText(
         message
    )
    msgRoot.attach(msgText)

    if file_path != '':
        file_name = file_path.rpartition('\\')[2]

        # This example assumes the image is in the current directory
        fp = open(file_path, 'rb')
        msgImage = MIMEImage(fp.read(), _subtype='jpg')
        fp.close()

        # Define the image's ID as referenced above
        msgImage.add_header('Content-ID', '<' + file_name + '>')
        msgRoot.attach(msgImage)

    stringMessage = msgRoot.as_string()
    return stringMessage