I wrote a code that create a PDF, and I wanted to send it with another file (still a .pdf) with a python code based on SMTPLIB library.
You can see str(names[i])
value for the receiver email, since is taken from a table and also the sending-process is managed with a for cycle, were the name of the just-created pdf is depending on the str(names[i])
value.
I'm trying to manage the following code, considering a two factor authentication in order to send the automated email via python, from a gmail-based email:
sender_email = "[email protected]"
receiver_email = str(names[i])
password = input("Authentication code: ")
subject = "Title"
body = """Hi,
This is the body of the email
"""
attachments = ['file1' str(names[i]) '.pdf', 'file2.pdf'] # list of attachments
# Create a multipart message and set headers
message = MIMEMultipart()
message["From"] = sender_email
message["To"] = receiver_email
message["Subject"] = subject
message["Bcc"] = receiver_email # For mass emails
# Add body to email
message.attach(MIMEText(body, "plain"))
if 'attachments' in globals() and len('attachments') > 0:
for filename in attachments:
f = filename
part = MIMEBase('application', "octet-stream")
part.set_payload( open(f,"rb").read() )
encoders.encode_base64(part)
part.add_header('Content-Disposition', 'attachment; filename="%s"' % os.path.basename(f))
message.attach(part)
# Add header as key/value pair to attachment part
part.add_header("Content-Disposition",f"attachment; filename= {attachments}",)
# Add attachment to message and convert message to string
message.attach(part)
text = message.as_string()
# Log in to server using secure context and send email
context = ssl.create_default_context()
with smtplib.SMTP_SSL("smtp.gmail.com", 465, context=context) as server:
server.login(sender_email, password)
server.sendmail(sender_email, receiver_email, text)
Everything works just fine: PDF is created, the mail is sent and received but.... the attachments are not ok in non-gmail emails.
What I find in the attachment list in a Outlook mail are files (with no extention) called ['file1' str(names[i]) '.pdf', 'file2.pdf']
, and trying with different receivers gives the same result.
It seems like non-gmail servers do not load files in the proper manner, while the gmail server recognizes the overall process
I thought about writing a "multiserver" object in the last with
condition, but I don't know how to do it.
Thank you all!
CodePudding user response:
In simplified code you do this:
# block#1 The following is simplified ---
for filename in attachments:
part = ... # construct part, include file content
part.add_header('Content-Disposition', ...)
message.attach(part)
# block#2: The following is original code ----
# Add header as key/value pair to attachment part
part.add_header("Content-Disposition",f"attachment; filename= {attachments}",)
# Add attachment to message and convert message to string
message.attach(part)
Thus, you
- in block#1 you first create a part for each file
- in block#2 you then take the last part from block#1 and add another content-disposition header, with including the name list as name
- in block#2 you then attach this part again to this message
Obviously, block#1 is all you need and block#2 just messes up everything. Remove it.