Search code examples
pythonpython-3.xemailattachmentsmtplib

Can't open attachments using SMTPLIB


These are the imports I used to send the email:

import tkinter as tk
from tkinter import filedialog
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
import email, smtplib, ssl
from email import encoders
import os

I have made a script where you can add attachments to emails using tkfiledialog to select files using this function:

def browse_file(): # Select a file to open
        global filelist

        filelist = filedialog.askopenfilenames()
        files_attached_tk.set("Files Attached: " + str(len(filelist)))

This is the part of the script that attaches and sends the file(s): (For and With are on same indentation)

for file in filelist:
            attachment_part = MIMEBase("application", "octet-stream")
            attachment_part.set_payload(open(file, "rb").read())
            encoders.encode_base64(attachment_part)
            attachment_part.add_header("Content-Disposition", "attachment; filename='%s'" % os.path.basename(file))
            message.attach(attachment_part)

# Create Server Connection
with smtplib.SMTP_SSL("smtp.gmail.com", 465, context=context) as server:
            server.login(config.email_sender, config.email_password)
            server.sendmail(
                sender_email, reciever_email, message.as_string()
            )

The problem is that, the files do send, but, they appear to be wrapped in ' ' in the email attachment. They look like this: 'document.pdf' which makes the document unreadable, for example, it does not say PDF File in the email because it is wrapped in ' '.

I have managed to open the files on my computer but I cannot open them on my phone. How would I be able to remove the ' ' from the file name? I have tried to do os.path.basename(file).strip("\'") or .strip("'") but the ' ' are still wrapping the filename. How can I remove these?

Happy to provide more details.


Solution

  • It might help to set 'application/pdf' as the mimetype - some mail clients rely on the mimetype to work out which application should open the attachment.

    # Additional imports
    
    from email.mime.application import MIMEApplication
    import mimetypes
    
    ...
    
    
    for file in filelist:
        mimetype, _ = mimetypes.guess_type(file)
        mimetype = 'application/octet-stream' if mimetype is None else mimetype
        _, _, subtype = mimetype.partition('/')
        attachment_part = MIMEApplication(open(file, "rb").read(), subtype)
        attachment_part.add_header("Content-Disposition", "attachment; filename='%s'" % os.path.basename(file))
        message.attach(attachment_part)
    
    ...