I have a Python script for sending email from a database that worked well for years on Python 2.7. Recently I revised it to work on Python 3.9. All seemed well until I found that attachments weren’t being included when received by iOS devices. A paperclip icon indicates that an attachment is included, but none is actually there.
I’ve been using MIMEMultipart(‘related’) to include embedded graphics as well as any attachments.
Changing it to MIMEMultipart(‘mixed’) includes the attachments in all cases, but it also causes any embedded graphics to repeat as attachments in all cases.
MIMEMultipart(‘alternative’) sends only the attachment.
Ultimately, it appears that my conversion has yet to properly utilize new email features of Python 3 and MIMEMultipart seems to be obsolete. But in spite of a lot of effort, I’ve been unable to come up with a solution. As I look to examples on any number of Python sites, what they load at the beginning varies greatly from one to another. I can’t seem to make any work.
Here’s my current script, which actually does work except as noted above. In actual use, the message, any embedded images and any attachments are all loaded from variables.
#!/usr/bin/python3
import ss
import smtplib
import mimetypes
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.image import MIMEImage
from email.mime.base import MIMEBase
from email import encoders
try:
strTo = '''Me@GMail.com'''
strFrom = '''Me@My.com'''
strCC = ""
strError = ""
strImages = ""
msg = MIMEMultipart('related')
msg['Subject'] = '''Test'''
msg['From'] = strFrom
msg['Reply-to'] = strTo
msg['To'] = strTo
msg.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 email agents can decide which they want to display.
msgAlternative = MIMEMultipart('alternative')
msg.attach(msgAlternative)
msgText = MIMEText('''
Hello,
Paragraph of words
''')
msgAlternative.attach(msgText)
msgText = MIMEText('''<!DOCTYPE html>
<html lang="en">
<body>
<p>
Hello,
</p><img src="cid:image1" alt=""/>
<p>
Paragraph of words
</p>
</body>
</html>
''', 'html')
msgAlternative.attach(msgText)
# Attach Any Images
images = '''/Users/my/Desktop/logo.png'''.splitlines()
I=1
for image in images:
# print 'Image',i,': ',image,'\n'
fp = open(image, 'rb')
msgImage = MIMEImage(fp.read())
fp.close()
# Define the image's ID as referenced above
msgImage.add_header('Content-ID', '<image'+str(i)+'>')
msg.attach(msgImage)
I+=1
# Attach any files
files = '''/Users/my/Desktop/RKw.jpeg'''.splitlines()
for file in files:
attachment = open(file, "rb")
part = MIMEBase("application", "octet-stream")
part.set_payload((attachment).read())
encoders.encode_base64(part)
part.add_header("Content-Disposition", f"attachment; filename= {file.split('/')[-1].replace(' ','%20')}")
msg.attach(part)
#send the email
smtp = smtplib.SMTP_SSL('''mail.SMTP.com''', '''465''')
smtp.ehlo()
smtp.login('''Me@My.com''', '''MyPassword''')
smtp.sendmail(strFrom, strTo.split(","), msg.as_string())
smtp.quit()
except: print("Sending Error : "+strTo)