table.rst 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. .. meta::
  2. :description: Send email with table in the body in Python.
  3. :keywords: send, email, Python, table, content
  4. .. _embedding-tables:
  5. Sending Email with Table in Body
  6. ================================
  7. You may include tables simply by turning them
  8. to raw HTML for example using ``df.to_html()``
  9. in Pandas. However, this often lead to very
  10. ugly tables as SMTP is poor at handling CSS
  11. or styling in general. Here is a comparison
  12. of using ``df.to_html()`` directly vs embedding
  13. via Red Mail:
  14. |pic1| vs |pic2|
  15. .. |pic1| image:: /imgs/table_without_style.png
  16. :height: 150px
  17. :align: top
  18. .. |pic2| image:: /imgs/table_with_style.png
  19. :height: 150px
  20. :align: top
  21. To embed tables, you can simply pass them
  22. to the send function as Pandas dataframes:
  23. .. code-block:: python
  24. # Creating a simple dataframe
  25. import pandas as pd
  26. df = pd.DataFrame({
  27. 'nums': [1,2,3],
  28. 'strings': ['yes', 'no', 'yes'],
  29. })
  30. # Let Red Mail to render the dataframe for you:
  31. email.send(
  32. subject='A prettified table',
  33. receivers=['first.last@example.com'],
  34. html="<h1>This is a table:</h1> {{ mytable }}",
  35. body_tables={
  36. 'mytable': df,
  37. }
  38. )
  39. Red Mail uses Jinja and inline HTML styling to make the
  40. tables look nice. Email servers typically don't handle
  41. well CSS.
  42. .. warning::
  43. Red Email Pandas templating should work on various
  44. dataframe strucutres (empty, multi-indexed etc.) but
  45. sometimes the rendering may be off if the dataframe
  46. is especially complex in structural sense. There are
  47. plans to make it even more better.
  48. You may also override the template paths (see
  49. :ref:`templating`) to create custom templates
  50. if you wish to make your own table prettifying:
  51. .. code-block:: python
  52. email.set_template_paths(
  53. html_table="path/to/templates",
  54. text_template="path/to/templates"
  55. )
  56. email.default_html_theme = "my_table_template.html"
  57. email.default_text_theme = "my_table_template.txt"
  58. The templates get parameter ``df`` which is the dataframe
  59. to be prettified.
  60. Using Pandas Styler
  61. -------------------
  62. You may also pass a Pandas style object to the body tables.
  63. This feature depends on `css_inline <https://pypi.org/project/css-inline/>`_
  64. and you need to install this dependency in order to use this feature.
  65. First we make a Pandas style object:
  66. .. code-block:: python
  67. import pandas as pd
  68. # Specify CSS style
  69. styles = [
  70. dict(
  71. selector="th",
  72. props=[
  73. ("font-weight", "bold"),
  74. ("padding", "0.5em 0.5em"),
  75. ("border-bottom", "1px solid black")
  76. ]
  77. ),
  78. dict(
  79. selector="tr:nth-child(even)",
  80. props=[("background-color", "#f5f5f5")]
  81. ),
  82. dict(
  83. selector="tr:nth-child(odd)",
  84. props=[("background-color", "#FFFFFF")]
  85. ),
  86. ]
  87. # Create a dataframe
  88. df = pd.DataFrame({
  89. 'nums': [1,2,3],
  90. 'strings': ['yes', 'no', 'yes'],
  91. })
  92. # Set the style
  93. style = (
  94. df.style
  95. .set_table_styles(styles)
  96. .hide(axis="index")
  97. )
  98. Then to send the email:
  99. .. code-block:: python
  100. email.send(
  101. subject='A prettified table',
  102. receivers=['first.last@example.com'],
  103. html="<h1>This is a table:</h1> {{ mytable }}",
  104. body_tables={
  105. 'mytable': style,
  106. }
  107. )
  108. The result looks like the following:
  109. .. image:: /imgs/table_with_styler.png
  110. :align: left