Ver código fonte

docs: updated tutorials

Mikael Koli 4 anos atrás
pai
commit
e93993c8e7

BIN
docs/imgs/email_emb_img.png


BIN
docs/imgs/email_emb_plt.png


+ 6 - 1
docs/index.rst

@@ -158,7 +158,12 @@ There is much more to offer. Install the package:
 
     pip install redmail
 
-and read further.
+and read further. Here are some example use cases:
+
+- :ref:`cookbook-campaign`
+- :ref:`cookbook-alerts`
+- :ref:`cookbook-stats`
+- :ref:`examples-mega`
 
 .. toctree::
    :maxdepth: 2

+ 66 - 9
docs/tutorials/body_content.rst

@@ -23,19 +23,19 @@ or styling in general. Here is a comparison
 of using ``df.to_html()`` directly vs embedding
 via Red Mail:
 
-|pic1| -- |pic2|
+|pic1| vs |pic2|
 
-.. |pic1| image:: /imgs/table_unrendered.png
+.. |pic1| image:: /imgs/table_without_style.png
    :height: 150px
    :align: top
    
 
-.. |pic2| image:: /imgs/table_rendered.png
+.. |pic2| image:: /imgs/table_with_style.png
    :height: 150px
    :align: top
 
 
-To embed tables, you can si  mply pass them 
+To embed tables, you can simply pass them 
 to the send function as Pandas dataframes:
 
 .. code-block:: python
@@ -68,7 +68,23 @@ well CSS.
     dataframe strucutres (empty, multi-indexed etc.) but
     sometimes the rendering may be off if the dataframe
     is especially complex in structural sense. There are
-    development plans to make it even more better.
+    plans to make it even more better.
+
+You may also override the template paths (see 
+:ref:`templating`) to create custom templates
+if you wish to make your own table prettifying:
+
+.. code-block:: python
+
+    email.set_template_paths(
+        html_table="path/to/templates", 
+        text_template="path/to/templates"
+    )
+    email.default_html_theme = "my_table_template.html"
+    email.default_text_theme = "my_table_template.txt"
+
+The templates get parameter ``df`` which is the dataframe
+to be prettified.
 
 .. _embedding-images:
 
@@ -83,12 +99,19 @@ of the email:
     email.send(
         subject='Some attachments',
         receivers=['first.last@example.com'],
-        html="<h1>This is an image:</h1> {{ myimage }}",
+        html="""<h1>This is an image:</h1> 
+                {{ my_image }}
+        """,
         body_images={
-            'myimage': 'path/to/image.png', 
+            'my_image': 'path/to/image.png', 
         }
     )
 
+The outcome looks like this:
+
+.. image:: /imgs/email_emb_img.png
+    :align: center
+
 The image will be rendered as ``<img src="cid:...">``.
 In case you need to control the image (like the size)
 you can also create the ``img`` tag yourself:
@@ -98,9 +121,9 @@ you can also create the ``img`` tag yourself:
     email.send(
         subject='Some attachments',
         receivers=['first.last@example.com'],
-        html='<h1>This is an image:</h1> <img src="{{ myimage.src }}">',
+        html='<h1>This is an image:</h1> <img src="{{ my_image.src }}" width=500 height=350>',
         body_images={
-            'myimage': 'path/to/image.png', 
+            'my_image': 'path/to/image.png', 
         }
     )
 
@@ -110,3 +133,37 @@ In addition to paths as strings, the following are supported:
 - ``bytes`` (the image as raw bytes)
 - ``matplotlib.pyplot.Figure``
 - ``PIL.Image``
+
+.. _embedding-plt:
+
+Embedding Figure
+^^^^^^^^^^^^^^^^
+
+As mentioned, you may also include Matplotlib figures directly to the email.
+This is especially handy if you are creating automatic statistics.
+
+A simple example to include a figure:
+
+.. code-block:: python
+
+    # Create a simple plot
+    import matplotlib.pyplot as plt
+    fig = plt.figure()
+    plt.plot([1,2,3,2,3])
+
+    # Send the plot
+    email.send(
+        subject='Some attachments',
+        receivers=['first.last@example.com'],
+        html="""<h1>This is a plot:</h1> 
+                {{ my_plot }}
+        """,
+        body_images={
+            'my_plot': fig, 
+        }
+    )
+
+The outcome looks like this:
+
+.. image:: /imgs/email_emb_plt.png
+    :align: center

+ 37 - 0
docs/tutorials/config.rst

@@ -0,0 +1,37 @@
+
+Configuring for Different Providers
+===================================
+
+.. _config-gmail:
+
+Gmail
+-----
+
+You need to make an application password `see this Google's answer <https://support.google.com/accounts/answer/185833>`_.
+You may also need to set up `2-step verification <https://support.google.com/accounts/answer/185839>`_ in order to
+be able to create an application password. Don't worry, those are easy things to configure.
+
+When you have your application password you can use Red Mail's gmail object that has the Gmail
+server pre-configured:
+
+.. code-block:: python
+
+    from redmail import gmail
+    gmail.user_name = 'example@gmail.com' # Your Gmail address
+    gmail.password = '<APP PASSWORD>'
+
+    # And then you can send emails
+    gmail.send(
+        subject="Example email",
+        receivers=['example@gmail.com']
+        text="Hi, this is an email."
+    )
+
+.. note::
+
+    You can only send emails using your Gmail email address. Changing ``sender`` has no effect.
+
+.. note::
+
+    ``gmail`` is actually nothing more than an instance of :class:`redmail.EmailSender`
+    with ``smtp.gmail.com`` as the host and ``587`` as the port.

+ 111 - 21
docs/tutorials/cookbook.rst

@@ -1,35 +1,65 @@
 .. _cookbook:
 
-Cook Book
+Cookbook
 =========
 
-This section provides various handy tips.
+This section provides various examples for various 
+needs.
 
-.. _config-gmail:
 
-Gmail
------
+.. _cookbook-campaign:
 
-You need to make an app password `see this Google's answer <https://support.google.com/accounts/answer/185833>`_. 
-When that is done you can use Red Mail's gmail object that has the Gmail
-server pre-configured:
+Email Campaign
+--------------
 
-.. code-block:: python
+In case you have a list of clients or customers you 
+wish to send personalized emails, you may benefit from
+templating. It may help to make the templates to an HTML
+file, polish them and after then send:
 
-    from redmail import gmail
-    gmail.user_name = 'example@gmail.com' # Your Gmail user
-    gmail.password = '<APP PASSWORD>'
+.. code-block:: python
 
-    # And then you can send emails
-    gmail.send(
-        subject="Example email",
-        receivers=['example@gmail.com']
-        text="Hi, this is an email."
+    from redmail import EmailSender
+    
+    email = EmailSender(...)
+    email.receivers = ['we@example.com']
+    email.set_template_paths(
+        html="path/to/campaigns"
     )
 
-.. note::
+Then make a HTML file, for example ``path/to/campaigns/summer_sale.html``:
+
+.. code-block:: html
+
+    <h1>Thank you, {{ customer }}, for being awesome!</h1>
+    <p>
+        We are pleased to inform you that we have a lot of products
+        in huge discounts.
+    </p>
+    <ul>
+    {% for product, discount, in discounts.items() %}
+        <li>{{ product }}: {{ '{:.0f} %'.format(discount * 100) }}</li>
+    {% endfor %}
+    </ul>
+    <p>Kind regards, We Ltd.</p>
 
-    You can only send emails using your Gmail email address. Changing ``sender`` has no effect.
+Finally send the emails:
+
+.. code-block:: python
+
+    discounts = {'shoes': 0.2, 'shirts': 0.4}
+    customers = ['cust1@example.com', 'cust2@example.com', ...]
+    for customer in customers:
+        email.send(
+            subject="Summer Sale!",
+            html_template="summer_sale.html",
+            body_params={
+                "customer": customer,
+                "discounts": discounts
+            }
+        )
+
+.. _cookbook-alerts:
 
 Error Alerts
 ------------
@@ -42,11 +72,71 @@ templated error alerts that include the full traceback:
     from redmail import EmailSender
     
     error_email = EmailSender(...)
+    error_email.sender = 'me@example.com'
     error_email.receivers = ['me@example.com']
-    error_email.html = """<h2>An error encountered</h2>{{ error }}"""
+    error_email.html = """
+        <h2>An error encountered</h2>
+        {{ error }}
+    """
 
     try:
         raise RuntimeError("Oops")
     except:
         # Send an email including the traceback
-        error_email.send(subject="Fail: doing stuff failed")
+        error_email.send(subject="Fail: doing stuff failed")
+
+.. note::
+
+    The ``error`` formatting object identifies which body it is being
+    attached to. If you wish to use text body, ``error`` will show up
+    similarly as Python errors you see on terminals. See more from
+    :class:`redmail.models.Error`
+
+.. _cookbook-stats:
+
+Stats Reports
+-------------
+
+As demonstrated :ref:`here <embedding-plt>`, embedding Matplotlib 
+figures to the HTML bodies is trivial. Therefore you can easily
+create diagnostic reports or automatic analyses. Just create 
+the plots and let Red Mail send them to you:
+
+.. code-block:: python
+
+    from redmail import EmailSender
+    
+    stats_report = EmailSender(...)
+    stats_report.sender = 'no-reply@example.com'
+    stats_report.receivers = ['me@example.com']
+
+    # Create a plot
+    import matplotlib.pyplot as plt
+    fig_performance = plt.Figure()
+    plt.plot([1,2,3,2,3])
+
+    # Create summary table
+    import pandas as pd
+    df = pd.DataFrame(...)
+    df_summary = df.describe()
+
+    # Send the report
+    stats_report.send(
+        subject="System Diagnostics",
+        html="""
+            <h1>System Diagnostics ({{ now }})</h1>
+            <hr>
+            <h2>Performance</h2>
+            {{ perf_plot }}
+            <h2>Summary Statistics</h2>
+            {{ tbl_summary }}
+            <hr>
+            <p>System running on {{ node }}</p>
+        """,
+        body_images={
+            "perf_plot": fig_performance,
+        },
+        body_tables={
+            "tbl_summary": df_summary
+        }
+    )

+ 115 - 0
docs/tutorials/example.rst

@@ -0,0 +1,115 @@
+
+.. _examples-simple:
+
+Examples
+========
+
+Simple Example
+--------------
+
+.. code-block:: python
+
+    from redmail import EmailSender
+
+    email = EmailSender(
+        host='localhost', 
+        port=0, 
+        user_name='me@example.com', 
+        password='<PASSWORD>'
+    )
+    email.send(
+        subject="An email",
+        sender="me@example.com",
+        receivers=['you@example.com'],
+        test="Hi, this is an email.",
+        html="<h1>Hi, </h1><p>this is an email.</p>"
+    )
+
+.. _examples-mega:
+
+Super Example
+-------------
+
+This example covers the most interesting 
+features of Red Mail:
+
+.. code-block:: python
+
+    from pathlib import Path
+    from redmail import EmailSender
+
+    import pandas as pd
+    from PIL import Image
+    import matplotlib.pyplot as plt
+
+    fig = plt.figure()
+    plt.plot([1, 2, 3])
+
+    df = pd.DataFrame({"A": [1, 2, 3], "B": [1, 2, 3]})
+
+    byte_content = Path("a_file.bin").read_bytes()
+
+    email = EmailSender(
+        host='localhost', 
+        port=0, 
+        user_name='me@example.com', 
+        password='<PASSWORD>'
+    )
+
+    # Send an email
+    email.send(
+        subject="A lot of stuff!",
+        sender="me@example.com",
+
+        # Receivers
+        receivers=["you@example.com"],
+        cc=['also@example.com'],
+        bcc=['external@example.com'],
+
+        # Bodies
+        text="""Hi {{ friend }},
+        This email has a lot of stuff!
+        Use HTML to view the awesome content.
+        """,
+        html="""<h1>Hi {{ friend }},</h1>
+        <p>This email has a lot of stuff!</p>
+        <p>Like this image:</p>
+        {{ my_image }}
+        <p>or this image:</p>
+        {{ my_pillow }}
+        <p>or this plot:</p>
+        {{ my_plot }}
+        <p>or this table:</p>
+        {{ my_table }}
+        <p>or this loop:</p>
+        <ul>
+        {% for value in container %}
+            {% if value > 5 %}
+                <li>{{ value }}</li>
+            {% else %}
+                <li style="color: red">{{ value }}</li>
+            {% endif %}
+        {% endfor %}
+        </ul>
+        """,
+
+        # Embedded content
+        body_images={
+            "my_image": "path/to/image.png",
+            "my_pillow": Image.new('RGB', (100, 30), color = (73, 109, 137))
+            "my_plot": fig,
+        },
+        body_tables={
+            "my_table": df,
+        },
+        body_params={
+            "friend": "Jack",
+            "container": [1, 3, 5, 7, 9],
+        },
+        attachments={
+            "data.csv": df,
+            "file.txt": "This is file content",
+            "file.html": Path("path/to/a_file.html"),
+            "file.bin": byte_content,
+        }
+    )

+ 10 - 11
docs/tutorials/getting_started.rst

@@ -16,7 +16,6 @@ Configuring Email
 
 You can configure your sender by:
 
-
 .. code-block:: python
 
    from redmail import EmailSender
@@ -28,18 +27,17 @@ You can configure your sender by:
        password='<PASSWORD>'
    )
 
-If your SMTP server does not require login to send emails then 
-just don't pass ``user_name`` and ``password`` to ``EmailSender``.
-
-Alternatively, if you use Gmail there is a pre-configured sender
-which you can just import and set user name and password:
-
 .. code-block:: python
 
-   from redmail import gmail
+   # Or if your SMTP server does not require credentials
+   email = EmailSender(
+       host='<SMTP HOST>',
+       port='<SMTP PORT>',
+   )
+
+Alternatively, there is a pre-configured sender for Gmail. 
+Please see :ref:`how to configure Gmail <config-gmail>` for more.
 
-   gmail.user_name = 'me@gmail.com'
-   gmail.password = '<PASSWORD>'
 
 Sending Emails
 --------------
@@ -50,7 +48,8 @@ You can just send emails by calling the method ``send``:
 
    email.send(
        subject='email subject',
-       receivers=['first.last@example.com'],
+       sender="me@example.com",
+       receivers=['you@example.com'],
        text="Hi, this is an email."
    )
 

+ 15 - 2
docs/tutorials/index.rst

@@ -5,6 +5,18 @@ Tutorials
 
 Welcome to Red Mail's tutorials!
 
+See:
+
+- :ref:`This to learn how to configure and get started <getting-started>`
+- :ref:`This to send with text and HTML bodies <sending-emails>`
+- :ref:`This to send with attachments <attachments>`
+- :ref:`This to send with embedded content (in HTML) <embedded>`
+- :ref:`This to send with dynamic HTML (Jinja) <jinja-support>`
+- :ref:`This to send using HTML templates (Jinja) <templating>`
+- :ref:`This to configure Red Mail to various SMTP providers (ie. Gmail) <templating>`
+
+And see - :ref:`cookbook <cookbook>` for example use cases.
+
 .. toctree::
    :maxdepth: 1
    :caption: Contents:
@@ -12,8 +24,9 @@ Welcome to Red Mail's tutorials!
    getting_started
    sending
    attachments
-   jinja_support
    body_content
+   jinja_support
    templating
    cookbook
-
+   config
+   example

+ 1 - 1
docs/tutorials/jinja_support.rst

@@ -65,7 +65,7 @@ some of them:
 Here is a list of default parameters:
 
 ================ ==================================== =========================================================
-Parameter Name   Class                                Description
+Parameter Name   Type                                 Description
 ================ ==================================== =========================================================
 sender           :class:`redmail.models.EmailAddress` Format class of the email sender
 error            :class:`redmail.models.Error`        Format class of the current exception (if any)

+ 33 - 5
docs/tutorials/sending.rst

@@ -4,8 +4,32 @@ Sending Emails
 ==============
 
 This section covers the basics of sending emails.
-We use an ``EmailSender`` configured in :ref:`configure`.
+See :ref:`configure` to revise how ``EmailSender``
+is configured. At minimum, sending an email requires:
 
+.. code-block:: python
+
+    from email import EmailSender
+    email = EmailSender(host='localhost', port=0)
+
+    email.send(
+        subject='email subject',
+        sender="me@example.com",
+        receivers=['you@example.com']
+    )
+
+.. note::
+
+    If you don't spesify the ``sender``, the sender is considered to 
+    be ``email.sender``. If ``email.sender`` is also missing, the sender
+    is then set to be ``email.user_name``. Ensure that any of these is a 
+    valid email address. 
+
+.. note::
+
+    Some email providers (such as Gmail) do not allow specifying
+    sender. For example, Gmail will outright ignore it and always
+    use your own email address.
 
 Sending Email with Text Body
 ----------------------------
@@ -16,7 +40,8 @@ To send an email with plain text message:
 
    email.send(
        subject='email subject',
-       receivers=['first.last@example.com'],
+       sender="me@example.com",
+       receivers=['you@example.com'],
        text="Hi, this is an email."
    )
 
@@ -29,7 +54,8 @@ To send an email with html content:
 
     email.send(
         subject='email subject',
-        receivers=['first.last@example.com'],
+        sender="me@example.com",
+        receivers=['you@example.com'],
         html="""
             <h1>Hi,</h1>
             <p>this is an email.</p>
@@ -46,7 +72,8 @@ You can also include both to your email:
 
     email.send(
         subject='email subject',
-        receivers=['first.last@example.com'],
+        sender="me@example.com",
+        receivers=['you@example.com'],
         text="Hi, this is an email.",
         html="""
             <h1>Hi,</h1>
@@ -66,7 +93,8 @@ to your emails:
 
     email.send(
         subject='email subject',
-        receivers=['first.last@example.com'],
+        sender="me@example.com",
+        receivers=['you@example.com'],
         cc=['also@example.com'],
         bcc=['outsider@example.com']
     )

+ 8 - 1
docs/tutorials/templating.rst

@@ -21,7 +21,14 @@ template path to a custom folder and
     If you are dissatisfied with default HTML and text
     table templates, you can also pass ``html_table``
     and ``text_table`` to specify the templates used
-    to render embedded tables.
+    to render embedded tables:
+
+    .. code-block:: python
+
+        email.set_template_paths(
+            html_table="path/html/tables",
+            text_table="path/text/tables",
+        )
 
 Next we will make a simple template, let's call it 
 ``event_card.html``: