pythonemailhtml-emailmime-mail

send HTMLbody from file using python


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.


Solution

  • 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?