0

I need to send a daily email with an excel file that must be password protected. I have been using exchangelib for my email needs so far. I would prefer not to switch / add a different library if possible.

sending emails with attachments has not been a problem, just figuring out how to password protect and send. I thought I got close with this solution, compressing and sending as a zip file, but can't seem to attach the zip archive, just the contents.

from exchangelib import Message, Account, FileAttachment
from pyminizip import compress

m = Message(
    account=Account(...),
    subject="Some Subject",
    to_recipients=['somebody@theiremail.com']
)

xl_file_path = 'temp.xlsx'
zip_archive = 'secure.zip'
password = 'HomerSimpson'

compress(
    xl_file_path,
    None,
    zip_archive,
    password,
    5
)

with open(zip_archive, 'wb') as f:
    zip_archive_content = f.read()

m.attach(FileAttachment(
    name=zip_archive,
    content=zip_archive_content
))

m.send()

When this gets sent, it is actually sending the original excel file. To prove it to myself, when the attachment is downloaded and given a ".xlsx" extension instead of ".zip" it opens right up.

I am aware that there is password protection in the openpyxl library, but that is a weak protection (does not encrypt). My understanding is that the compress function is actually encrypting the data - which is what I want.

My hope is that I am just missing something simple about sending a zip archive as an attachment, but would accept other alternatives to password protecting the file or if there really is no other option - switching to a different method for sending emails.

Thoughts?

Edit

I did verify that the secure.zip archive is in the same directory as this script and does work correctly when opening manually (i.e. it contains my Excel file and is password protected).

  • Can you see the file `secure.zip` in your filesystem, in the same directory as the Python script? Is it compressed and protected? – Selcuk May 06 '21 at 04:46
  • If you have checked that `content` actually contains zipped data, and `name` actually contains the zip filename, then it's possible that your client (Outlook, I presume) automatically unzips the attachment. Finally, you may need to set the `content_type` attribute on the attachment to something that is relevant for zipped files. – Erik Cederstrand May 06 '21 at 10:40
  • `secure.zip` is in my filesystem and is protected. – Danny Beachnau May 06 '21 at 12:38
  • I do not think opening a zip archive works the way I have done it here. If I take that `zip_archive_content` and re-save in my script with `open('new_archive.zip', 'rb') as f` then `f.write(zip_archive_content)`, I find that the 'new_archive.zip' file is actually an excel file and I rename it with a `.xlsx` extension I can open it directly in Excel. – Danny Beachnau May 06 '21 at 12:40

1 Answers1

1

Thank you Erik in the comments. Setting content_type='application/zip' in the FileAttachment is what I needed.

m.attach(FileAttachment(
    name=name,
    content=content,
    content_type='application/zip',
))