Home > Mobile >  smtplib multiple attachments failed to be received
smtplib multiple attachments failed to be received

Time:10-17

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.

  • Related