send HTMLbody from file using python

Mime has a variety of formats. By default MIMEMultipart builds a multipart/mixed message, meaning a simple text body and a bunch of attachments.

When you want an HTML representation of the body, you want a multipart/alternative message:

...
message = MIMEMultipart('alternative')
...

But you are using the old compat32 API. Since Python 3.6 you'd better use email.message.EmailMessage...


Why are you passing a bogus body if that's not what you want?

Your code seems to be written for Python 3.5 or earlier. The email library was overhauled in 3.6 and is now quite a bit more versatile and logical. Probably throw away what you have and start over with the examples from the email documentation.

Here's a brief attempt.

from email.message import EmailMessage

... 
message = EmailMessage()
message["From"] = sender_email
message["To"] = receiver_email
message["Subject"] = subject
# No point in using Bcc if the recipient is already in To:

with open(filename) as fp:
    message.set_content(fp.read(), 'html')

# no need for a context if you are just using the default SSL
with smtplib.SMTP_SSL(smtp_server, 465) as server:
    server.login(sender_email, password)
    # Prefer the modern send_message method
    server.send_message(message)

If you want to send a message in both plain text and HTML, the linked examples show you how to adapt the code to do that, but then really, the text/plain body part should actually contain a useful message, not just a placeholder.

As commented in the code, there is no reason to use Bcc: if you have already specified the recipient in the To: header. If you want to use Bcc: you will have to put something else in the To: header, commonly your own address or an address list like :undisclosed-recipients;

Tangentially, when opening a file, Python (or in fact the operating system) examines the user's current working directory, not the directory from which the Python script was loaded. Perhaps see also What exactly is current working directory?