Issue
I am using a workflow automation program called Alteryx. It has its own "Send Email" tool but it is inherently limited to 10mb attachments and I have a number of daily/weekly reports that are larger than that. I am trying to design a short example workflow that can intake an array of variables that represent different parts of an email. I have each piece working except for the email body. I am trying to write it in a way so that anything can be input as the body string variable, but it seems like single quotes, double quotes, and slashes break that variable though the email still sends just with an empty body.
Is there a way I can encode the entire variable to get python to ignore every escape character in the input string? Should I build in some processing before the Python step that replaces ' with ''' etc?
# List all non-standard packages to be imported by your
# script here (only missing packages will be installed)
from ayx import Package
#Package.installPackages(['pandas','numpy'])
from ayx import Alteryx
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email import encoders
pyArray = Alteryx.read("#1")
body = pyArray["pymailBody"][0]
msg = MIMEMultipart()
msg['From'] = pyArray["pymailFrom"][0]
msg['To'] = pyArray["pymailTo"][0]
msg['CC'] = pyArray["pymailCC"][0]
msg['BCC'] = pyArray["pymailBCC"][0]
msg['Subject'] = pyArray["pymailSubject"][0]
msg['Body'] = body.encode('unicode_escape')
attachmentName = pyArray["pymailAttachmentName"][0]
attachmentPath = pyArray["pymailAttachmentPath"][0]
part = MIMEBase('application', "octet-stream")
part.set_payload(open(attachmentPath, "rb").read())
encoders.encode_base64(part)
part.add_header('Content-Disposition', 'attachment', filename=attachmentName)
msg.attach(part)
with smtplib.SMTP("mail.company.com", 25) as server:
server.ehlo()
server.starttls()
server.ehlo()
server.send_message(msg)
Solution
Your code seems to be written for Python 3.5 or earlier (except, curiously, the use of smtplib.send_message
). The email
library was overhauled in 3.6 and is now quite a bit more versatile and logical. My suspicion is that simply upgrading to the modern version of the library should solve your conundrum.
Most acutely, the old email.message.Message
or its MIMEMultipart
etc brethren did not usefully have msg['Body']
for setting the body of the message; but overall, you want to move away from using those legacy APIs.
Reading more than I like between the lines, I'm guessing your code should be refactored to something like
from email.message import EmailMessage
import smtplib
from ayx import Alteryx # , Package was never used
pyArray = Alteryx.read("#1")
msg = EmailMessage()
msg['From'] = pyArray["pymailFrom"][0]
msg['To'] = pyArray["pymailTo"][0]
msg['CC'] = pyArray["pymailCC"][0]
msg['BCC'] = pyArray["pymailBCC"][0]
msg['Subject'] = pyArray["pymailSubject"][0]
msg.set_content(pyArray["pymailBody"][0]) # no encoding here, just pass in the Unicode text
with open(pyArray["pymailAttachmentPath"][0], "rb") as payload:
msg.add_attachment(
payload.read(),
maintype='application', subtype='octet-stream',
filename=pyArray["pymailAttachmentName"][0])
with smtplib.SMTP("mail.company.com", 25) as server:
server.ehlo()
server.starttls()
server.ehlo()
server.send_message(msg)
(If you really wanted to add an explicit Content-Disposition:
it could be done, of course; but the default disposition handling should be fine for an application/octet-stream
attachment.)
It is unfortunate that there are enough old examples of how to send email in Python to populate several of Saturn's rings, but your first stop should be the official Python documentation. https://docs.python.org/3/library/email.examples.html is an excellent starting point.
Answered By - tripleee
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.