3
votes

I am trying to send a bokeh graph through outlook email as body. And you know, bokeh graph , I have generated as an HTML file. The same I would like to send in the email embedded as the body of the email.

I tried reading the HTML file reading using the read command and supplying the same as the htmlbody. But, it comes as blank in the email. Nothing comes populated. Below is the code I tried.

import win32com.client as win32
import psutil
import os
import subprocess
outlook = win32.Dispatch('outlook.application')
mail = outlook.CreateItem(0)
mail.To = '[email protected]'
mail.Subject = 'Sent through Python'
html_url='C:/Users/ABC/Documents/XYZ/test.htm'
with open(html_url, 'r') as myfile:
     data=myfile.read()
mail.HTMLBody = data
mail.send

Then tried the below ... But still email body is blank.. Any idea what is going wrong ???

from bokeh.embed import components
from jinja2 import Template
from bokeh.resources import INLINE
from bokeh.plotting import figure
from bokeh.io import output_file,show,output_notebook

import win32com.client as win32
import psutil
import os
import subprocess

outlook = win32.Dispatch('outlook.application')
mail = outlook.CreateItem(0)
mail.To = '[email protected]'
mail.Subject = 'Sent through Python'

def get_plot_components() :
   # build your plot here
    plot = figure()
    plot.circle([2,3,4],[5,6,7])
    show(plot)
    script, div = components(plot)
    return script, div

template = Template('''
       <div id='bokeh_plot_for_the_body'>
          {{ resources | safe }}
          {{ div | safe }}
          {{ script | safe }}
       </div>
                ''')

script, div = get_plot_components()
outlook_body = template.render(resources = INLINE.render(),
                               script = script,
                               div = div)
mail.HTMLBody = outlook_body
mail.send
4

4 Answers

1
votes

Looks like this can't be achieved as no email clients allow to run scripts due to security threat. Only way out is attaching an html file or give a html link in the email.

0
votes

I have no Windows machine to test but I think the problem may be that you are trying to embed a full HTML page generated by Bokeh into the body of another HTML file generated by Outlook. So you are getting:

<!DOCTYPE html>
<html lang='en'>
    <head>
        <title>Outlook Message</title>
    </head>  
    <body>

        <!DOCTYPE html>
        <html lang='en'>
            <head>
                <title>Bokeh Plot</title>
            </head>  
            <body>
                <div id=plot>
                <script id=bokeh_script>
                </script>
                </div>
            </body>
        </html>

    </body>
</html>

What I would advice is to merge your bokeh script with the script sending the Outlook message by adding a function that returns the bokeh components like this:

from bokeh.embed import components
from jinja2 import Template
from bokeh.resources import INLINE

import win32com.client as win32
import psutil
import os
import subprocess

outlook = win32.Dispatch('outlook.application')
mail = outlook.CreateItem(0)
mail.To = '[email protected]'
mail.Subject = 'Sent through Python'
html_url='C:/Users/ABC/Documents/XYZ/test.htm'
with open(html_url, 'r') as myfile:
    data=myfile.read()

def get_plot_components()
   # build your plot here
   script, div = components(plot)
   return script, div

template = Template('''
       <div id='bokeh_plot_for_the_body'>
          {{ resources | safe }}
          {{ div | safe }}
          {{ script | safe }}
       </div>
''')

script, div = get_plot_components()
outlook_body = template.render(resources = INLINE.render(),
                               script = script,
                               div = div)
mail.HTMLBody = outlook_body
mail.send
0
votes

You need to add encoding with open the template file.

Example:

html_url= open('C:/Users/ABC/Documents/XYZ/test.htm', encoding='utf16')
data=html_url.read()

That works for me.

0
votes

If anyone looking for answers is sending HTML Table only in the email body, then the trick given below works:

  1. pip install pywin32
  2. import win32com.client
outlook = win32com.client.Dispatch('outlook.application')
mail = outlook.CreateItem(0)
mail.To = mail_config.get('To')
mail.Subject = mail_config.get('Subject')
mail.HTMLBody = mail_config.get('HTML_body')
mail.Send()