I am currently working on a project in which I build a mail client using Python's default library and socket programming (MAIL FROM, RCPT TO, DATA, etc.) instead of smtplib. I've tried sending an image as binary over the socket connection:
if file_path != '':
imageFile = open(file_path, 'rb')
client_socket.send(imageFile.read())
This didn't work. I then tried to make a MIME message that I could send without smtplib:
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()
Taken from this question . Unfortunately, that also didn't work, returning this error stack:
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'
I'm using Tkinter as a GUI, but I think the problem begins when I call msgRoot.as_string(). I'm just lost at this point so any help would be greatly appreciated.
It would be easier to use yagmail to do the handling of images for you. Full disclosure: I'm the developer.
import yagmail
yag = yagmail.SMTP(from_var, 'yourpassword')
yag.send(to_var, subject_var, contents = [message, file_path])
Note that this will send text message
followed by a picture as loaded magically by file_path
.
You'll have to install it first:
pip install yagmail
For other nice features, have a look at the readme on github.
It seems that in this situation, the msgRoot.preamble along with the 'related' input in the constructor for MIMEMultipart() and the alternate HTML text caused a problem when it came time to compress the message into a single string. In case someone else runs into this problem I have included my fixed code:
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
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.