0

I can send the plain text but unable to send html text in html format.

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

body = """
this is first mail by using python
"""
port_email = 587
smtp_server = "smtp.gmail.com"
password = "your password"


subject = "An email with attachment from Python"
sender_email = "sender@gmail.example.com"
receiver_email = "receiver@example.net"

# Create a multipart message and set headers
message = MIMEMultipart()
message["From"] = sender_email
message["To"] = receiver_email
message["Subject"] = subject
message["Bcc"] = receiver_email  # Recommended for mass emails

# Add body to email
message.attach(MIMEText(body, "plain"))
filename = "file name"  # In same directory as script

with open(filename.html, 'r', encoding="utf-8") as attachment:
    part1 = attachment.read()

part2 = MIMEText(part1, "html")
message.attach(part2)
text = message.as_string()

context = ssl.create_default_context()
with smtplib.SMTP_SSL(smtp_server, 465 , context=context) as server:
    server.login(sender_email, password)
    server.sendmail(sender_email, receiver_email, text)

This will send attach file but i want to see the html text in email body. filename is content html table so code should send the html text which will automatic available in html body with html table.

tripleee
  • 175,061
  • 34
  • 275
  • 318

2 Answers2

2

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?

tripleee
  • 175,061
  • 34
  • 275
  • 318
  • Thanks @tripleee i understand totally. I am using MIMEMultipart() and I need both plain text, HTML content in email body and an excel attachment. – OneTouchForHeight Jan 19 '22 at 03:40
  • So do you mean to say that you really want the junk text/plain part as the alternative for the HTML part? That can be done, but obviously sucks monumentally for plain-text recipients who cannot know that there is an alternative part with actual contents which they cannot see. – tripleee Jan 19 '22 at 05:06
  • My suggestion at this point woud be for you to accept one of the answers you received (or if you prefer, post one of your own, and accept that once you can) and ask a new question with your _actual_ requirements. – tripleee Jan 19 '22 at 05:08
  • 1
    As you said i asked another question https://stackoverflow.com/questions/70765339/attach-excel-file-to-email-using-python – OneTouchForHeight Jan 20 '22 at 02:20
1

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...

Serge Ballesta
  • 143,923
  • 11
  • 122
  • 252
  • My reading is that they want a pure HTML message, not a multipart. If they do send `multpart/alternative`, the `text/plain` part should contain something useful (i.e. the same message, just not in HTML), not some random junk. – tripleee Jan 18 '22 at 09:14
  • Thanks @sergeBallesta, I have used MIMEMultipart('alternative') and it worked I am able to send HTML content in email body but plain text is lost and disappear. And also attachment is encrypted and lost when i download from receiver side. – OneTouchForHeight Jan 19 '22 at 03:44