OnlyDean
OnlyDean

Reputation: 1039

Python -- Emailed Zip Archieve not displaying correctly

I have a program that sends daily automated reports to myself and a few other people. These reports are written to a folder in my /tmp/ directory and then compressed into a Zip archive and emailed as an attachment. The result I expect is for all users to see the attachment as Reports_2017-06-20.zip (or whatever the date is that day). On my email client, I see the attachment as _tmp_Engineering_Reports_2017-06-20.zip. One recipient of the report claims that the attachment appears in his email client only 2. In all cases the files are successfully transferred by email, but the zip file usually has to be renamed manually by the end user to extract the files and view them. Below is my email class. The dictionary passed_values is created outside of this class. The filename being passed is /tmp/Reports_2017-06-20.

import smtplib
from email import encoders
from email.MIMEBase import MIMEBase
from email.MIMEMultipart import MIMEMultipart
from email.MIMEText import MIMEText


class EmailHandler(object):
    def __init__(self, passed_values):
        self._filename = passed_values.get('filename')
        self._subject = passed_values.get('subject')
        self._from_address = passed_values.get('from_address')
        self._to_addresses = passed_values.get('to_addresses')
        self._email_password = passed_values.get('email_password')
        self._body = passed_values.get('body')

    @property
    def filename(self):
        return self._filename

    @filename.setter
    def filename(self, value):
        self._filename = value

    @property
    def from_address(self):
        return self._from_address

    @from_address.setter
    def from_address(self, value):
        self._from_address = value

    @property
    def to_addresses(self):
        return self._to_addresses

    @to_addresses.setter
    def to_addresses(self, value):
        self._to_addresses = value

    @property
    def body(self):
        return self._body

    @body.setter
    def body(self, value):
        self._body = value

    @property
    def subject(self):
        return self._body

    @body.setter
    def body(self, value):
        self._body = value

    def send_email_with_attachment(self):
        msg = MIMEMultipart()
        msg['From'] = self._from_address
        msg['To'] = ', '.join(self._to_addresses)
        msg['Subject'] = self._subject
        msg.attach(MIMEText(self._body, 'plain'))
        attachment = open (self._filename + '.zip', "rb")
        part = MIMEBase('application', 'octet-stream')
        part.set_payload(attachment.read())
        encoders.encode_base64(part)
        part.add_header('Content-Disposition', "attachment; filename= %s" % self._filename + '.zip')
        msg.attach(part)
        server = smtplib.SMTP('smtp.gmail.com', 587)
        server.starttls()
        server.login(self._from_address, self._email_password)
        text = msg.as_string()
        server.sendmail(self._from_address, self._to_addresses, text)
        server.quit()

Can anyone advise me on what I've done wrong?

Upvotes: 0

Views: 42

Answers (1)

user94559
user94559

Reputation: 60153

Use os.path.basename so you only send the file name (not the full path) in the Content-Disposition header. It seems that email clients aren't sure what to do with a "filename" containing slashes.

Upvotes: 1

Related Questions