4

How should I send an email with text format and html format in the same body? What is the use of MIMEmultipart?

MIMEMultipart([MIMEText(msg, 'text'),MIMEtext(html,'html')])

I was able to receive an email using this but with a blank body

PS: I am trying to send a text and attach a table in the same body. I don't want to send a table as an attachment.

html = """
  <html>
   <head>
    <style> 
     table, th, td {{ border: 1px solid black; border-collapse: collapse; }} th, td {{ padding: 5px; }}
    </style>
   </head>
   <body><p>Hello, Friend This data is from a data frame.</p>
    <p>Here is your data:</p>
    {table}
    <p>Regards,</p>
    <p>Me</p>
   </body>
  </html> """

text = """
Hello, Friend.

Here is your data:

{table}

Regards,

Me"""
text = text.format(table=tabulate(df, headers=list(df.columns), tablefmt="grid"))
html = html.format(table=tabulate(df, headers=list(df.columns), tablefmt="html"))
if(df['date'][0].year==1900 and df['date'][0].month==datetime.date.today().month and df['date'][0].day==datetime.date.today().day):
a2=smtplib.SMTP(host='smtp-mail.outlook.com', port=587)
a2.starttls()
myadd='abc@gmail.com'
passwd=getpass.getpass(prompt='Password: ')
try :

    a2.login(myadd,passwd)
except Exception :
    print("login unsuccessful")
def get_contacts(filename):
    name=[]
    email=[]
    with open('email.txt','r') as fl:
         l=fl.readlines()
         print(l)
         print(type(l))
         for i in l:
          try: 
              name.append(i.split('\n')[0].split()[0])
              email.append(i.split('\n')[0].split()[1]) 
          except Exception:
              break
         fl.close()
    return (name,email)
def temp_message(filename):
    with open(filename,'r') as fl1:
        l2=fl1.read()
    return(Template(l2))
name,email=get_contacts('email.txt')    
tmp1=temp_message('temp1.txt')   
for name,eml in zip(name,email):
    msg=MIMEMultipart([MIMEText(msg, 'text'),MIMEtext(html,'html')])
    message=tmp1.substitute(USER_NAME=name.title())
    print(message)
    msg['FROM']=myadd
    msg['TO']=eml
    msg['Subject']="This is TEST"
    msg.attach(MIMEText(message, 'plain')) 
    #       msg.set_payload([MIMEText(message, 'plain'),MIMEText(html, 'html')])
    # send the message via the server set up earlier.
    a2.send_message(msg)
    del msg
    a2.quit()
vahdet
  • 6,357
  • 9
  • 51
  • 106
Vineeth Ananthula
  • 85
  • 2
  • 5
  • 12

2 Answers2

7

You need to create the message as

MIMEMultiPart('alternative') 

and then attach the two MIMEText parts.

>>> text = 'Hello World'
>>> html = '<p>Hello World</p>'

>>> msg = MIMEMultipart('alternative')
>>> msg['Subject'] = 'Hello'
>>> msg['To'] = 'a@example.com'
>>> msg['From'] = 'b@example.com'

>>> msg.attach(MIMEText(text, 'plain'))
>>> msg.attach(MIMEText(html, 'html'))

>>> s = smtplib.SMTP('localhost:1025')
>>> s.sendmail('a@example.com', 'b@example.com', msg.as_string())

Received*:

$  python -m smtpd -n -c DebuggingServer localhost:1025
---------- MESSAGE FOLLOWS ----------
Content-Type: multipart/alternative; boundary="===============2742770895617986609=="
MIME-Version: 1.0
Subject: Hello
To: a@example.com
From: b@example.com
X-Peer: 127.0.0.1

--===============2742770895617986609==
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit

Hello World
--===============2742770895617986609==
Content-Type: text/html; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit

<p>Hello World</p>
--===============2742770895617986609==--
------------ END MESSAGE ------------

The reworked email package (Python 3.6+) can be used to send the same message like this (this should be the preferred approach in modern code):

>>> from email.message import EmailMessage
>>> msg = EmailMessage()
>>> msg['Subject'] = 'Hello'
>>> msg['To'] = 'a@example.com'
>>> msg['From'] = 'b@example.com'
>>> msg.set_content(text)
>>> msg.add_alternative(html, subtype='html')
>>> s.send_message(msg)

Output:

---------- MESSAGE FOLLOWS ----------
Subject: Hello
To: a@example.com
From: b@example.com
MIME-Version: 1.0
Content-Type: multipart/alternative;
 boundary="===============1374158239299927384=="
X-Peer: 127.0.0.1

--===============1374158239299927384==
Content-Type: text/plain; charset="utf-8"
Content-Transfer-Encoding: 7bit

Hello World

--===============1374158239299927384==
Content-Type: text/html; charset="utf-8"                                                                                            
Content-Transfer-Encoding: 7bit                                                                                                     
MIME-Version: 1.0                                                                                                                   
                                                                                                                                    
<p>Hello World</p>                                                                                                                  
                                                                                                                                    
--===============1374158239299927384==--                                                                                            
------------ END MESSAGE ------------

* the smtpd package has been deprecated since Python 3.9. The third party aiosmtpd package is the recommended replacement. The equivalent command is python -m aiosmtpd -n -l localhost:1025

snakecharmerb
  • 47,570
  • 11
  • 100
  • 153
  • 1
    Tangentially, perhaps see also [What are the parts in a multipart email?](https://stackoverflow.com/questions/48562935/what-are-the-parts-in-a-multipart-email/48563281#48563281) for a brief overview of MIME. – tripleee Nov 20 '22 at 10:10
0

At your 'with':

def temp_message(filename): 
   with open(filename,'r') as fl1:
      l2=fl1.read()

Change it to:

def temp_message(filename):
   filename = temp_message('temp1.txt') #changed tmp1 to filename
   with open(filename, 'w+', encoding='utf-8') as fl1:
      fl1.write(text)
      fl1.write(html)
      fl1.write(regards)

You can just split the 'regards' part of your text variable so your html(table) can be between the two. I was confused as to what your problem is (A lot of edits) but if I'm not mistaken your fl1(tempt1.txt) doesn't have any data you've only 'read'(r) the text file but didn't write anything. I would also recommend that you put your 'tmp1=temp_message('temp1.txt')' inside your 'def temp_message(filename)' to avoid confusion.

Ibaboiii
  • 89
  • 12
  • 1
    This is not my problem. My question is How should i send text object and html object using MIMEmultipart. I have clearly mentioned it in the question. I have pasted the code for @DavidCain requirement – Vineeth Ananthula Mar 07 '19 at 06:16