django-templated-email-3.0.0/0000775000175000017500000000000014056516731020446 5ustar tuliovintatuliovinta00000000000000django-templated-email-3.0.0/LICENSE0000664000175000017500000000205314044653770021455 0ustar tuliovintatuliovinta00000000000000Copyright (c) 2011 Bradley Whittington Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. django-templated-email-3.0.0/setup.cfg0000664000175000017500000000004614056516731022267 0ustar tuliovintatuliovinta00000000000000[egg_info] tag_build = tag_date = 0 django-templated-email-3.0.0/django_templated_email.egg-info/0000775000175000017500000000000014056516731026610 5ustar tuliovintatuliovinta00000000000000django-templated-email-3.0.0/django_templated_email.egg-info/top_level.txt0000664000175000017500000000002014056516731031332 0ustar tuliovintatuliovinta00000000000000templated_email django-templated-email-3.0.0/django_templated_email.egg-info/PKG-INFO0000664000175000017500000005125314056516731027713 0ustar tuliovintatuliovinta00000000000000Metadata-Version: 2.1 Name: django-templated-email Version: 3.0.0 Summary: A Django oriented templated / transaction email abstraction Home-page: http://github.com/vintasoftware/django-templated-email/ Author: Bradley Whittington Author-email: radbrad182@gmail.com License: MIT Description: ============================== Django-Templated-Email ============================== |GitterBadge|_ |PypiversionBadge|_ |PythonVersionsBadge|_ |LicenseBadge|_ :Info: A Django oriented templated email sending class :Author: Bradley Whittington (http://github.com/bradwhittington, http://twitter.com/darb) :Tests: |TravisBadge|_ |CoverageBadge|_ Overview ================= django-templated-email is oriented towards sending templated emails. The library supports template inheritance, adding cc'd and bcc'd recipients, configurable template naming and location. The send_templated_email method can be thought of as the render_to_response shortcut for email. Make sure you are reading the correct documentation: develop branch: https://github.com/vintasoftware/django-templated-email/blob/develop/README.rst stable pypi/master: https://github.com/vintasoftware/django-templated-email/blob/master/README.rst Requirements ================= * Python (3.6, 3.7, 3.8, 3.9) * Django (2.2, 3.1, 3.2) We **highly recommend** and only officially support the latest patch release of each Python and Django series. Getting going - installation ============================== Installing:: pip install django-templated-email You can add the following to your settings.py (but it works out the box): .. code-block:: python TEMPLATED_EMAIL_BACKEND = 'templated_email.backends.vanilla_django.TemplateBackend' # You can use a shortcut version TEMPLATED_EMAIL_BACKEND = 'templated_email.backends.vanilla_django' # You can also use a class directly from templated_email.backends.vanilla_django import TemplateBackend TEMPLATED_EMAIL_BACKEND = TemplateBackend Sending templated emails ============================== Example usage using vanilla_django TemplateBackend backend Python to send mail: .. code-block:: python from templated_email import send_templated_mail send_templated_mail( template_name='welcome', from_email='from@example.com', recipient_list=['to@example.com'], context={ 'username':request.user.username, 'full_name':request.user.get_full_name(), 'signup_date':request.user.date_joined }, # Optional: # cc=['cc@example.com'], # bcc=['bcc@example.com'], # headers={'My-Custom-Header':'Custom Value'}, # template_prefix="my_emails/", # template_suffix="email", ) If you would like finer control on sending the email, you can use **get_templated_email**, which will return a django **EmailMessage** object, prepared using the **vanilla_django** backend: .. code-block:: python from templated_email import get_templated_mail get_templated_mail( template_name='welcome', from_email='from@example.com', to=['to@example.com'], context={ 'username':request.user.username, 'full_name':request.user.get_full_name(), 'signup_date':request.user.date_joined }, # Optional: # cc=['cc@example.com'], # bcc=['bcc@example.com'], # headers={'My-Custom-Header':'Custom Value'}, # template_prefix="my_emails/", # template_suffix="email", ) You can also **cc** and **bcc** recipients using **cc=['example@example.com']**. Your template ------------- The templated_email/ directory needs to be the templates directory. The backend will look in *my_app/templates/templated_email/welcome.email* : .. code-block:: python {% block subject %}My subject for {{username}}{% endblock %} {% block plain %} Hi {{full_name}}, You just signed up for my website, using: username: {{username}} join date: {{signup_date}} Thanks, you rock! {% endblock %} If you want to include an HTML part to your emails, simply use the 'html' block : .. code-block:: python {% block html %}

Hi {{full_name}},

You just signed up for my website, using:

username
{{username}}
join date
{{signup_date}}

Thanks, you rock!

{% endblock %} The plain part can also be calculated from the HTML using `html2text `_. If you don't specify the plain block and `html2text `_ package is installed, the plain part will be calculated from the HTML part. You can disable this behaviour in settings.py : .. code-block:: python TEMPLATED_EMAIL_AUTO_PLAIN = False You can also specify a custom function that converts from HTML to the plain part : .. code-block:: python def convert_html_to_text(html): ... TEMPLATED_EMAIL_PLAIN_FUNCTION = convert_html_to_text You can globally override the template dir, and file extension using the following variables in settings.py : .. code-block:: python TEMPLATED_EMAIL_TEMPLATE_DIR = 'templated_email/' #use '' for top level template dir, ensure there is a trailing slash TEMPLATED_EMAIL_FILE_EXTENSION = 'email' You can also set a value for **template_prefix** and **template_suffix** for every time you call **send_templated_mail**, if you wish to store a set of templates in a different directory. Remember to include a trailing slash. Using with `Django Anymail `_ ========================================================================= Anymail integrates several transactional email service providers (ESPs) into Django, with a consistent API that lets you use ESP-added features without locking your code to a particular ESP. It supports Mailgun, Postmark, SendGrid, SparkPost and more. You can use it with django-templated-email, just follow their instructions in their `quick start `_ to configure it. Optionally you can use their custom `EmailMessage `_ class with django-templated-email by using the following settings: .. code-block:: python # This replaces django.core.mail.EmailMessage TEMPLATED_EMAIL_EMAIL_MESSAGE_CLASS='anymail.message.AnymailMessage' # This replaces django.core.mail.EmailMultiAlternatives TEMPLATED_EMAIL_EMAIL_MULTIALTERNATIVES_CLASS='anymail.message.AnymailMessage' Inline images ============== You can add inline images to your email using the *InlineImage* class. First get the image content from a file or a *ImageField*: .. code-block:: python # From a file with open('pikachu.png', 'rb') as pikachu: image = pikachu.read() # From an ImageField # Suppose we have this model class Company(models.Model): logo = models.ImageField() image = company.logo.read() Then create an instance of *InlineImage*: .. code-block:: python from templated_email import InlineImage inline_image = InlineImage(filename="pikachu.png", content=image) Now pass the object on the context to the template when you send the email. .. code-block:: python send_templated_mail(template_name='welcome', from_email='from@example.com', recipient_list=['to@example.com'], context={'pikachu_image': inline_image}) Finally in your template add the image on the html template block: .. code-block:: html Note: All *InlineImage* objects you add to the context will be attached to the e-mail, even if they are not used in the template. Add link to view the email on the web ===================================== .. code-block:: python # Add templated email to INSTALLED_APPS INSTALLED_APPS = [ ... 'templated_email' ] .. code-block:: python # and this to your url patterns url(r'^', include('templated_email.urls', namespace='templated_email')), .. code-block:: python # when sending the email use the *create_link* parameter. send_templated_mail( template_name='welcome', from_email='from@example.com', recipient_list=['to@example.com'], context={}, create_link=True) And, finally add the link to your template. .. code-block:: html {% if email_uuid %} You can view this e-mail on the web here: here {% endif %} Notes: - A copy of the rendered e-mail will be stored on the database. This can grow if you send too many e-mails. You are responsible for managing it. - If you use *InlineImage* all images will be uploaded to your media storage, keep that in mind too. Class Based Views ================== It's pretty common for emails to be sent after a form is submitted. We include a mixin to be used with any view that inherit from Django's FormMixin. In your view add the mixin and the usual Django's attributes: .. code-block:: python from templated_email.generic_views import TemplatedEmailFormViewMixin class AuthorCreateView(TemplatedEmailFormViewMixin, CreateView): model = Author fields = ['name', 'email'] success_url = '/create_author/' template_name = 'authors/create_author.html' By default the template will have the *form_data* if the form is valid or *from_errors* if the form is not valid in it's context. You can view an example `here `_ Now you can use the following attributes/methods to customize it's behavior: Attributes: **templated_email_template_name** (mandatory if you don't implement **templated_email_get_template_names()**): String naming the template you want to use for the email. ie: templated_email_template_name = 'welcome'. **templated_email_send_on_success** (default: True): This attribute tells django-templated-email to send an email if the form is valid. **templated_email_send_on_failure** (default: False): This attribute tells django-templated-email to send an email if the form is invalid. **templated_email_from_email** (default: **settings.TEMPLATED_EMAIL_FROM_EMAIL**): String containing the email to send the email from. Methods: **templated_email_get_template_names(self, valid)** (mandatory if you don't set **templated_email_template_name**): If the method returns a string it will use it as the template to render the email. If it returns a list it will send the email *only* with the first existing template. **templated_email_get_recipients(self, form)** (mandatory): Return the recipient list to whom the email will be sent to. ie: .. code-block:: python def templated_email_get_recipients(self, form): return [form.data['email']] **templated_email_get_context_data(**kwargs)** (optional): Use this method to add extra data to the context used for rendering the template. You should get the parent class's context from calling super. ie: .. code-block:: python def templated_email_get_context_data(self, **kwargs): context = super(ThisClassView, self).templated_email_get_context_data(**kwargs) # add things to context return context **templated_email_get_send_email_kwargs(self, valid, form)** (optional): Add or change the kwargs that will be used to send the e-mail. You should call super to get the default kwargs. ie: .. code-block:: python def templated_email_get_send_email_kwargs(valid, form): kwargs = super(ThisClassView, self).templated_email_get_send_email_kwargs(valid, form) kwargs['bcc'] = ['admin@example.com'] return kwargs **templated_email_send_templated_mail(*args, **kwargs)** (optional): This method calls django-templated-email's *send_templated_mail* method. You could change this method to use a celery's task for example or to handle errors. Future Plans ============= See https://github.com/vintasoftware/django-templated-email/issues?state=open Using django_templated_email in 3rd party applications ======================================================= If you would like to use django_templated_email to handle mail in a reusable application, you should note that: * Your calls to **send_templated_mail** should set a value for **template_dir**, so you can keep copies of your app-specific templates local to your app (although the loader will find your email templates if you store them in */templates/templated_email*, if **TEMPLATED_EMAIL_TEMPLATE_DIR** has not been overridden) * If you do (and you should) set a value for **template_dir**, remember to include a trailing slash, i.e. *'my_app_email/'* * The deployed app may use a different backend which doesn't use the django templating backend, and as such make a note in your README warning developers that if they are using django_templated_email already, with a different backend, they will need to ensure their email provider can send all your templates (ideally enumerate those somewhere convenient) Notes on specific backends ============================== Using vanilla_django -------------------------- This is the default backend, and as such requires no special configuration, and will work out of the box. By default it assumes the following settings (should you wish to override them): .. code-block:: python TEMPLATED_EMAIL_TEMPLATE_DIR = 'templated_email/' #Use '' for top level template dir TEMPLATED_EMAIL_FILE_EXTENSION = 'email' For legacy purposes you can specify email subjects in your settings file (but, the preferred method is to use a **{% block subject %}** in your template): .. code-block:: python TEMPLATED_EMAIL_DJANGO_SUBJECTS = { 'welcome':'Welcome to my website', } Additionally you can call **send_templated_mail** and optionally override the following parameters:: template_prefix='your_template_dir/' # Override where the method looks for email templates (alternatively, use template_dir) template_suffix='email' # Override the file extension of the email templates (alternatively, use file_extension) cc=['fubar@example.com'] # Set a CC on the mail bcc=['fubar@example.com'] # Set a BCC on the mail template_dir='your_template_dir/' # Override where the method looks for email templates connection=your_connection # Takes a django mail backend connection, created using **django.core.mail.get_connection** auth_user='username' # Override the user that the django mail backend uses, per **django.core.mail.send_mail** auth_password='password' # Override the password that the django mail backend uses, per **django.core.mail.send_mail** Releasing a new version of this package: ======================================== Update CHANGELOG file. Execute the following commands:: bumpversion [major,minor,patch] python setup.py publish git push origin --tags Commercial Support ================== This library, as others, is used in projects of Vinta clients. We are always looking for exciting work, so if you need any commercial support, feel free to get in touch: contact@vinta.com.br .. _Django: http://djangoproject.com .. |GitterBadge| image:: https://badges.gitter.im/vintasoftware/django-templated-email.svg .. _GitterBadge: https://gitter.im/vintasoftware/django-templated-email?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge .. |TravisBadge| image:: https://travis-ci.org/vintasoftware/django-templated-email.svg?branch=develop .. _TravisBadge: https://travis-ci.org/vintasoftware/django-templated-email .. |CoverageBadge| image:: https://coveralls.io/repos/github/vintasoftware/django-templated-email/badge.svg?branch=develop .. _CoverageBadge: https://coveralls.io/github/vintasoftware/django-templated-email?branch=develop .. |PypiversionBadge| image:: https://img.shields.io/pypi/v/django-templated-email.svg .. _PypiversionBadge: https://pypi.python.org/pypi/django-templated-email .. |PythonVersionsBadge| image:: https://img.shields.io/pypi/pyversions/django-templated-email.svg .. _PythonVersionsBadge: https://pypi.python.org/pypi/django-templated-email .. |LicenseBadge| image:: https://img.shields.io/pypi/l/django-templated-email.svg .. _LicenseBadge: https://github.com/vintasoftware/django-templated-email/blob/develop/LICENSE Platform: any Classifier: Development Status :: 5 - Production/Stable Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: MIT License Classifier: Operating System :: OS Independent Classifier: Programming Language :: Python :: 3.6 Classifier: Programming Language :: Python :: 3.7 Classifier: Programming Language :: Python :: 3.8 Classifier: Programming Language :: Python :: 3.9 Classifier: Topic :: Software Development :: Libraries :: Python Modules Classifier: Framework :: Django Description-Content-Type: text/x-rst django-templated-email-3.0.0/django_templated_email.egg-info/dependency_links.txt0000664000175000017500000000000114056516731032656 0ustar tuliovintatuliovinta00000000000000 django-templated-email-3.0.0/django_templated_email.egg-info/SOURCES.txt0000664000175000017500000000122214056516731030471 0ustar tuliovintatuliovinta00000000000000AUTHORS LICENSE MANIFEST.in README.rst setup.py django_templated_email.egg-info/PKG-INFO django_templated_email.egg-info/SOURCES.txt django_templated_email.egg-info/dependency_links.txt django_templated_email.egg-info/requires.txt django_templated_email.egg-info/top_level.txt templated_email/__init__.py templated_email/generic_views.py templated_email/models.py templated_email/urls.py templated_email/utils.py templated_email/views.py templated_email/backends/__init__.py templated_email/backends/vanilla_django.py templated_email/migrations/0001_initial.py templated_email/migrations/__init__.py templated_email/templates/templated_email/saved_email.htmldjango-templated-email-3.0.0/django_templated_email.egg-info/requires.txt0000664000175000017500000000003114056516731031202 0ustar tuliovintatuliovinta00000000000000django-render-block>=0.5 django-templated-email-3.0.0/README.rst0000664000175000017500000004063514056516121022136 0ustar tuliovintatuliovinta00000000000000============================== Django-Templated-Email ============================== |GitterBadge|_ |PypiversionBadge|_ |PythonVersionsBadge|_ |LicenseBadge|_ :Info: A Django oriented templated email sending class :Author: Bradley Whittington (http://github.com/bradwhittington, http://twitter.com/darb) :Tests: |TravisBadge|_ |CoverageBadge|_ Overview ================= django-templated-email is oriented towards sending templated emails. The library supports template inheritance, adding cc'd and bcc'd recipients, configurable template naming and location. The send_templated_email method can be thought of as the render_to_response shortcut for email. Make sure you are reading the correct documentation: develop branch: https://github.com/vintasoftware/django-templated-email/blob/develop/README.rst stable pypi/master: https://github.com/vintasoftware/django-templated-email/blob/master/README.rst Requirements ================= * Python (3.6, 3.7, 3.8, 3.9) * Django (2.2, 3.1, 3.2) We **highly recommend** and only officially support the latest patch release of each Python and Django series. Getting going - installation ============================== Installing:: pip install django-templated-email You can add the following to your settings.py (but it works out the box): .. code-block:: python TEMPLATED_EMAIL_BACKEND = 'templated_email.backends.vanilla_django.TemplateBackend' # You can use a shortcut version TEMPLATED_EMAIL_BACKEND = 'templated_email.backends.vanilla_django' # You can also use a class directly from templated_email.backends.vanilla_django import TemplateBackend TEMPLATED_EMAIL_BACKEND = TemplateBackend Sending templated emails ============================== Example usage using vanilla_django TemplateBackend backend Python to send mail: .. code-block:: python from templated_email import send_templated_mail send_templated_mail( template_name='welcome', from_email='from@example.com', recipient_list=['to@example.com'], context={ 'username':request.user.username, 'full_name':request.user.get_full_name(), 'signup_date':request.user.date_joined }, # Optional: # cc=['cc@example.com'], # bcc=['bcc@example.com'], # headers={'My-Custom-Header':'Custom Value'}, # template_prefix="my_emails/", # template_suffix="email", ) If you would like finer control on sending the email, you can use **get_templated_email**, which will return a django **EmailMessage** object, prepared using the **vanilla_django** backend: .. code-block:: python from templated_email import get_templated_mail get_templated_mail( template_name='welcome', from_email='from@example.com', to=['to@example.com'], context={ 'username':request.user.username, 'full_name':request.user.get_full_name(), 'signup_date':request.user.date_joined }, # Optional: # cc=['cc@example.com'], # bcc=['bcc@example.com'], # headers={'My-Custom-Header':'Custom Value'}, # template_prefix="my_emails/", # template_suffix="email", ) You can also **cc** and **bcc** recipients using **cc=['example@example.com']**. Your template ------------- The templated_email/ directory needs to be the templates directory. The backend will look in *my_app/templates/templated_email/welcome.email* : .. code-block:: python {% block subject %}My subject for {{username}}{% endblock %} {% block plain %} Hi {{full_name}}, You just signed up for my website, using: username: {{username}} join date: {{signup_date}} Thanks, you rock! {% endblock %} If you want to include an HTML part to your emails, simply use the 'html' block : .. code-block:: python {% block html %}

Hi {{full_name}},

You just signed up for my website, using:

username
{{username}}
join date
{{signup_date}}

Thanks, you rock!

{% endblock %} The plain part can also be calculated from the HTML using `html2text `_. If you don't specify the plain block and `html2text `_ package is installed, the plain part will be calculated from the HTML part. You can disable this behaviour in settings.py : .. code-block:: python TEMPLATED_EMAIL_AUTO_PLAIN = False You can also specify a custom function that converts from HTML to the plain part : .. code-block:: python def convert_html_to_text(html): ... TEMPLATED_EMAIL_PLAIN_FUNCTION = convert_html_to_text You can globally override the template dir, and file extension using the following variables in settings.py : .. code-block:: python TEMPLATED_EMAIL_TEMPLATE_DIR = 'templated_email/' #use '' for top level template dir, ensure there is a trailing slash TEMPLATED_EMAIL_FILE_EXTENSION = 'email' You can also set a value for **template_prefix** and **template_suffix** for every time you call **send_templated_mail**, if you wish to store a set of templates in a different directory. Remember to include a trailing slash. Using with `Django Anymail `_ ========================================================================= Anymail integrates several transactional email service providers (ESPs) into Django, with a consistent API that lets you use ESP-added features without locking your code to a particular ESP. It supports Mailgun, Postmark, SendGrid, SparkPost and more. You can use it with django-templated-email, just follow their instructions in their `quick start `_ to configure it. Optionally you can use their custom `EmailMessage `_ class with django-templated-email by using the following settings: .. code-block:: python # This replaces django.core.mail.EmailMessage TEMPLATED_EMAIL_EMAIL_MESSAGE_CLASS='anymail.message.AnymailMessage' # This replaces django.core.mail.EmailMultiAlternatives TEMPLATED_EMAIL_EMAIL_MULTIALTERNATIVES_CLASS='anymail.message.AnymailMessage' Inline images ============== You can add inline images to your email using the *InlineImage* class. First get the image content from a file or a *ImageField*: .. code-block:: python # From a file with open('pikachu.png', 'rb') as pikachu: image = pikachu.read() # From an ImageField # Suppose we have this model class Company(models.Model): logo = models.ImageField() image = company.logo.read() Then create an instance of *InlineImage*: .. code-block:: python from templated_email import InlineImage inline_image = InlineImage(filename="pikachu.png", content=image) Now pass the object on the context to the template when you send the email. .. code-block:: python send_templated_mail(template_name='welcome', from_email='from@example.com', recipient_list=['to@example.com'], context={'pikachu_image': inline_image}) Finally in your template add the image on the html template block: .. code-block:: html Note: All *InlineImage* objects you add to the context will be attached to the e-mail, even if they are not used in the template. Add link to view the email on the web ===================================== .. code-block:: python # Add templated email to INSTALLED_APPS INSTALLED_APPS = [ ... 'templated_email' ] .. code-block:: python # and this to your url patterns url(r'^', include('templated_email.urls', namespace='templated_email')), .. code-block:: python # when sending the email use the *create_link* parameter. send_templated_mail( template_name='welcome', from_email='from@example.com', recipient_list=['to@example.com'], context={}, create_link=True) And, finally add the link to your template. .. code-block:: html {% if email_uuid %} You can view this e-mail on the web here: here {% endif %} Notes: - A copy of the rendered e-mail will be stored on the database. This can grow if you send too many e-mails. You are responsible for managing it. - If you use *InlineImage* all images will be uploaded to your media storage, keep that in mind too. Class Based Views ================== It's pretty common for emails to be sent after a form is submitted. We include a mixin to be used with any view that inherit from Django's FormMixin. In your view add the mixin and the usual Django's attributes: .. code-block:: python from templated_email.generic_views import TemplatedEmailFormViewMixin class AuthorCreateView(TemplatedEmailFormViewMixin, CreateView): model = Author fields = ['name', 'email'] success_url = '/create_author/' template_name = 'authors/create_author.html' By default the template will have the *form_data* if the form is valid or *from_errors* if the form is not valid in it's context. You can view an example `here `_ Now you can use the following attributes/methods to customize it's behavior: Attributes: **templated_email_template_name** (mandatory if you don't implement **templated_email_get_template_names()**): String naming the template you want to use for the email. ie: templated_email_template_name = 'welcome'. **templated_email_send_on_success** (default: True): This attribute tells django-templated-email to send an email if the form is valid. **templated_email_send_on_failure** (default: False): This attribute tells django-templated-email to send an email if the form is invalid. **templated_email_from_email** (default: **settings.TEMPLATED_EMAIL_FROM_EMAIL**): String containing the email to send the email from. Methods: **templated_email_get_template_names(self, valid)** (mandatory if you don't set **templated_email_template_name**): If the method returns a string it will use it as the template to render the email. If it returns a list it will send the email *only* with the first existing template. **templated_email_get_recipients(self, form)** (mandatory): Return the recipient list to whom the email will be sent to. ie: .. code-block:: python def templated_email_get_recipients(self, form): return [form.data['email']] **templated_email_get_context_data(**kwargs)** (optional): Use this method to add extra data to the context used for rendering the template. You should get the parent class's context from calling super. ie: .. code-block:: python def templated_email_get_context_data(self, **kwargs): context = super(ThisClassView, self).templated_email_get_context_data(**kwargs) # add things to context return context **templated_email_get_send_email_kwargs(self, valid, form)** (optional): Add or change the kwargs that will be used to send the e-mail. You should call super to get the default kwargs. ie: .. code-block:: python def templated_email_get_send_email_kwargs(valid, form): kwargs = super(ThisClassView, self).templated_email_get_send_email_kwargs(valid, form) kwargs['bcc'] = ['admin@example.com'] return kwargs **templated_email_send_templated_mail(*args, **kwargs)** (optional): This method calls django-templated-email's *send_templated_mail* method. You could change this method to use a celery's task for example or to handle errors. Future Plans ============= See https://github.com/vintasoftware/django-templated-email/issues?state=open Using django_templated_email in 3rd party applications ======================================================= If you would like to use django_templated_email to handle mail in a reusable application, you should note that: * Your calls to **send_templated_mail** should set a value for **template_dir**, so you can keep copies of your app-specific templates local to your app (although the loader will find your email templates if you store them in */templates/templated_email*, if **TEMPLATED_EMAIL_TEMPLATE_DIR** has not been overridden) * If you do (and you should) set a value for **template_dir**, remember to include a trailing slash, i.e. *'my_app_email/'* * The deployed app may use a different backend which doesn't use the django templating backend, and as such make a note in your README warning developers that if they are using django_templated_email already, with a different backend, they will need to ensure their email provider can send all your templates (ideally enumerate those somewhere convenient) Notes on specific backends ============================== Using vanilla_django -------------------------- This is the default backend, and as such requires no special configuration, and will work out of the box. By default it assumes the following settings (should you wish to override them): .. code-block:: python TEMPLATED_EMAIL_TEMPLATE_DIR = 'templated_email/' #Use '' for top level template dir TEMPLATED_EMAIL_FILE_EXTENSION = 'email' For legacy purposes you can specify email subjects in your settings file (but, the preferred method is to use a **{% block subject %}** in your template): .. code-block:: python TEMPLATED_EMAIL_DJANGO_SUBJECTS = { 'welcome':'Welcome to my website', } Additionally you can call **send_templated_mail** and optionally override the following parameters:: template_prefix='your_template_dir/' # Override where the method looks for email templates (alternatively, use template_dir) template_suffix='email' # Override the file extension of the email templates (alternatively, use file_extension) cc=['fubar@example.com'] # Set a CC on the mail bcc=['fubar@example.com'] # Set a BCC on the mail template_dir='your_template_dir/' # Override where the method looks for email templates connection=your_connection # Takes a django mail backend connection, created using **django.core.mail.get_connection** auth_user='username' # Override the user that the django mail backend uses, per **django.core.mail.send_mail** auth_password='password' # Override the password that the django mail backend uses, per **django.core.mail.send_mail** Releasing a new version of this package: ======================================== Update CHANGELOG file. Execute the following commands:: bumpversion [major,minor,patch] python setup.py publish git push origin --tags Commercial Support ================== This library, as others, is used in projects of Vinta clients. We are always looking for exciting work, so if you need any commercial support, feel free to get in touch: contact@vinta.com.br .. _Django: http://djangoproject.com .. |GitterBadge| image:: https://badges.gitter.im/vintasoftware/django-templated-email.svg .. _GitterBadge: https://gitter.im/vintasoftware/django-templated-email?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge .. |TravisBadge| image:: https://travis-ci.org/vintasoftware/django-templated-email.svg?branch=develop .. _TravisBadge: https://travis-ci.org/vintasoftware/django-templated-email .. |CoverageBadge| image:: https://coveralls.io/repos/github/vintasoftware/django-templated-email/badge.svg?branch=develop .. _CoverageBadge: https://coveralls.io/github/vintasoftware/django-templated-email?branch=develop .. |PypiversionBadge| image:: https://img.shields.io/pypi/v/django-templated-email.svg .. _PypiversionBadge: https://pypi.python.org/pypi/django-templated-email .. |PythonVersionsBadge| image:: https://img.shields.io/pypi/pyversions/django-templated-email.svg .. _PythonVersionsBadge: https://pypi.python.org/pypi/django-templated-email .. |LicenseBadge| image:: https://img.shields.io/pypi/l/django-templated-email.svg .. _LicenseBadge: https://github.com/vintasoftware/django-templated-email/blob/develop/LICENSE django-templated-email-3.0.0/templated_email/0000775000175000017500000000000014056516731023574 5ustar tuliovintatuliovinta00000000000000django-templated-email-3.0.0/templated_email/__init__.py0000664000175000017500000000632014054251551025700 0ustar tuliovintatuliovinta00000000000000from django.conf import settings from django.utils.module_loading import import_string from templated_email.backends.vanilla_django import TemplateBackend from templated_email.utils import InlineImage # noqa def get_connection(backend=None, template_prefix=None, template_suffix=None, fail_silently=False, **kwargs): """Load a templated e-mail backend and return an instance of it. If backend is None (default) settings.TEMPLATED_EMAIL_BACKEND is used. Both fail_silently and other keyword arguments are used in the constructor of the backend. """ # This method is mostly a copy of the backend loader present in # django.core.mail.get_connection klass_path = backend or getattr(settings, 'TEMPLATED_EMAIL_BACKEND', TemplateBackend) if isinstance(klass_path, str): try: # First check if class name is omitted and we have module in settings klass = import_string(klass_path + '.' + 'TemplateBackend') except ImportError: # Fallback to class name klass = import_string(klass_path) else: klass = klass_path return klass(fail_silently=fail_silently, template_prefix=template_prefix, template_suffix=template_suffix, **kwargs) def get_templated_mail(template_name, context, from_email=None, to=None, cc=None, bcc=None, headers=None, template_prefix=None, template_suffix=None, template_dir=None, file_extension=None, create_link=False): """Returns a templated EmailMessage instance without a connection using the django templating backend.""" template_prefix = template_prefix or template_dir template_suffix = template_suffix or file_extension templater = TemplateBackend(template_prefix=template_prefix, template_suffix=template_suffix) return templater.get_email_message(template_name, context, from_email=from_email, to=to, cc=cc, bcc=bcc, headers=headers, template_prefix=template_prefix, template_suffix=template_suffix, create_link=create_link) def send_templated_mail(template_name, from_email, recipient_list, context, cc=None, bcc=None, fail_silently=False, connection=None, headers=None, template_prefix=None, template_suffix=None, create_link=False, **kwargs): """Easy wrapper for sending a templated email to a recipient list. Final behaviour of sending depends on the currently selected engine. See BackendClass.send.__doc__ """ connection = connection or get_connection(template_prefix=template_prefix, template_suffix=template_suffix) return connection.send(template_name, from_email, recipient_list, context, cc=cc, bcc=bcc, fail_silently=fail_silently, headers=headers, create_link=create_link, **kwargs) django-templated-email-3.0.0/templated_email/migrations/0000775000175000017500000000000014056516731025750 5ustar tuliovintatuliovinta00000000000000django-templated-email-3.0.0/templated_email/migrations/0001_initial.py0000664000175000017500000000121014054251551030377 0ustar tuliovintatuliovinta00000000000000# -*- coding: utf-8 -*- # Generated by Django 1.10 on 2016-10-05 17:09 from django.db import migrations, models import uuid class Migration(migrations.Migration): initial = True dependencies = [ ] operations = [ migrations.CreateModel( name='SavedEmail', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('uuid', models.UUIDField(default=uuid.uuid4)), ('content', models.TextField()), ('created', models.DateTimeField(auto_now_add=True)), ], ), ] django-templated-email-3.0.0/templated_email/migrations/__init__.py0000664000175000017500000000000014044653770030051 0ustar tuliovintatuliovinta00000000000000django-templated-email-3.0.0/templated_email/views.py0000664000175000017500000000040014044653770025277 0ustar tuliovintatuliovinta00000000000000from django.views.generic import DetailView from templated_email.models import SavedEmail class ShowEmailView(DetailView): model = SavedEmail template_name = 'templated_email/saved_email.html' slug_field = 'uuid' slug_url_kwarg = 'uuid' django-templated-email-3.0.0/templated_email/backends/0000775000175000017500000000000014056516731025346 5ustar tuliovintatuliovinta00000000000000django-templated-email-3.0.0/templated_email/backends/__init__.py0000664000175000017500000000006714044653770027464 0ustar tuliovintatuliovinta00000000000000class HeaderNotSupportedException(Exception): pass django-templated-email-3.0.0/templated_email/backends/vanilla_django.py0000664000175000017500000002347114056514643030677 0ustar tuliovintatuliovinta00000000000000import uuid import hashlib from io import BytesIO from django.conf import settings from django.core.mail import get_connection from django.template import Context from django.utils.translation import gettext as _ from django.core.files.storage import default_storage from templated_email.utils import ( get_emailmessage_klass, get_emailmultialternatives_klass) from templated_email.utils import InlineImage from render_block import render_block_to_string, BlockNotFound try: import html2text except ImportError: html2text = None class EmailRenderException(Exception): pass class TemplateBackend(object): """ Backend which uses Django's templates, and django's send_mail function. Heavily inspired by http://stackoverflow.com/questions/2809547/creating-email-templates-with-django Default / preferred behaviour works like so: templates named templated_email/.email {% block subject %} declares the subject {% block plain %} declares text/plain {% block html %} declares text/html Legacy behaviour loads from: Subjects for email templates can be configured in one of two ways: * If you are using internationalisation, you can simply create entries for " email subject" as a msgid in your PO file * Using a dictionary in settings.py, TEMPLATED_EMAIL_DJANGO_SUBJECTS, for e.g.: TEMPLATED_EMAIL_DJANGO_SUBJECTS = { 'welcome':'Welcome to my website', } Subjects are templatable using the context, i.e. A subject that resolves to 'Welcome to my website, %(username)s', requires that the context passed in to the send() method contains 'username' as one of it's keys """ def __init__(self, fail_silently=False, template_prefix=None, template_suffix=None, **kwargs): self.template_prefix = template_prefix or getattr(settings, 'TEMPLATED_EMAIL_TEMPLATE_DIR', 'templated_email/') self.template_suffix = template_suffix or getattr(settings, 'TEMPLATED_EMAIL_FILE_EXTENSION', 'email') def attach_inline_images(self, message, context): for value in context.values(): if isinstance(value, InlineImage): value.attach_to_message(message) def host_inline_image(self, inline_image): from templated_email.urls import app_name md5sum = hashlib.md5(inline_image.content).hexdigest() filename = inline_image.filename filename = app_name + '/' + md5sum + filename if not default_storage.exists(filename): filename = default_storage.save(filename, BytesIO(inline_image.content)) return default_storage.url(filename) def _render_email(self, template_name, context, template_dir=None, file_extension=None): response = {} errors = {} file_extension = file_extension or self.template_suffix if file_extension.startswith('.'): file_extension = file_extension[1:] template_extension = '.%s' % file_extension if isinstance(template_name, (tuple, list, )): prefixed_templates = template_name else: prefixed_templates = [template_name] full_template_names = [] for one_prefixed_template in prefixed_templates: one_full_template_name = ''.join((template_dir or self.template_prefix, one_prefixed_template)) if not one_full_template_name.endswith(template_extension): one_full_template_name += template_extension full_template_names.append(one_full_template_name) for part in ['subject', 'html', 'plain']: render_context = Context(context, autoescape=(part == 'html')) try: response[part] = render_block_to_string(full_template_names, part, render_context) except BlockNotFound as error: errors[part] = error if response == {}: raise EmailRenderException("Couldn't render email parts. Errors: %s" % errors) return response def get_email_message(self, template_name, context, from_email=None, to=None, cc=None, bcc=None, headers=None, template_prefix=None, template_suffix=None, template_dir=None, file_extension=None, attachments=None, create_link=False): if create_link: email_uuid = uuid.uuid4() link_context = dict(context) context['email_uuid'] = email_uuid.hex for key, value in context.items(): if isinstance(value, InlineImage): link_context[key] = self.host_inline_image(value) EmailMessage = get_emailmessage_klass() EmailMultiAlternatives = get_emailmultialternatives_klass() parts = self._render_email(template_name, context, template_prefix or template_dir, template_suffix or file_extension) plain_part = 'plain' in parts html_part = 'html' in parts if create_link and html_part: static_html_part = self._render_email( template_name, link_context, template_prefix or template_dir, template_suffix or file_extension)['html'] from templated_email.models import SavedEmail SavedEmail.objects.create(content=static_html_part, uuid=email_uuid) if 'subject' in parts: subject = parts['subject'] else: subject_dict = getattr(settings, 'TEMPLATED_EMAIL_DJANGO_SUBJECTS', {}) if isinstance(template_name, (list, tuple)): for template in template_name: if template in subject_dict: subject_template = subject_dict[template] break else: subject_template = _('%s email subject' % template_name[0]) else: subject_template = subject_dict.get(template_name, _('%s email subject' % template_name)) subject = subject_template % context subject = subject.strip('\n\r') # strip newlines from subject if not plain_part: plain_part = self._generate_plain_part(parts) if plain_part and not html_part: e = EmailMessage( subject, parts['plain'], from_email, to, cc=cc, bcc=bcc, headers=headers, attachments=attachments, ) elif html_part and not plain_part: e = EmailMessage( subject, parts['html'], from_email, to, cc=cc, bcc=bcc, headers=headers, attachments=attachments, ) e.content_subtype = 'html' elif plain_part and html_part: e = EmailMultiAlternatives( subject, parts['plain'], from_email, to, cc=cc, bcc=bcc, headers=headers, attachments=attachments, ) e.attach_alternative(parts['html'], 'text/html') else: raise EmailRenderException("Please specify at a plain and/or html block.") self.attach_inline_images(e, context) return e def _generate_plain_part(self, parts): """ Depending on some settings, generate a plain part from the HTML part. The user can choose a custom "plain function" that takes an argument of the HTML part and returns the plain text. By default this is "html2text.html2text". """ html_part = 'html' in parts auto_plain = getattr(settings, 'TEMPLATED_EMAIL_AUTO_PLAIN', True) plain_func = getattr(settings, 'TEMPLATED_EMAIL_PLAIN_FUNCTION', None) if not auto_plain: return if not html_part: return if not plain_func and html2text: plain_func = html2text.html2text if not plain_func: return parts['plain'] = plain_func(parts['html']) return True def send(self, template_name, from_email, recipient_list, context, cc=None, bcc=None, fail_silently=False, headers=None, template_prefix=None, template_suffix=None, template_dir=None, file_extension=None, auth_user=None, auth_password=None, connection=None, attachments=None, create_link=False, **kwargs): connection = connection or get_connection(username=auth_user, password=auth_password, fail_silently=fail_silently) e = self.get_email_message(template_name, context, from_email=from_email, to=recipient_list, cc=cc, bcc=bcc, headers=headers, template_prefix=template_prefix, template_suffix=template_suffix, template_dir=template_dir, file_extension=file_extension, attachments=attachments, create_link=create_link) e.connection = connection try: e.send(fail_silently) except NameError: raise EmailRenderException("Couldn't render plain or html parts") return e.extra_headers.get('Message-Id', None) django-templated-email-3.0.0/templated_email/urls.py0000664000175000017500000000041014054251551025120 0ustar tuliovintatuliovinta00000000000000from django.urls import re_path from templated_email.views import ShowEmailView app_name = 'templated_email' urlpatterns = [ re_path(r'^email/(?P([a-f\d]{32})|([a-f\d]{8}(-[a-f\d]{4}){3}-[a-f\d]{12}))/$', ShowEmailView.as_view(), name='show_email'), ] django-templated-email-3.0.0/templated_email/templates/0000775000175000017500000000000014056516731025572 5ustar tuliovintatuliovinta00000000000000django-templated-email-3.0.0/templated_email/templates/templated_email/0000775000175000017500000000000014056516731030720 5ustar tuliovintatuliovinta00000000000000django-templated-email-3.0.0/templated_email/templates/templated_email/saved_email.html0000664000175000017500000000003214044653770034054 0ustar tuliovintatuliovinta00000000000000{{ object.content|safe }} django-templated-email-3.0.0/templated_email/generic_views.py0000664000175000017500000000471214044653770027005 0ustar tuliovintatuliovinta00000000000000from functools import partial from django.conf import settings from django.core.exceptions import ImproperlyConfigured from templated_email import send_templated_mail class TemplatedEmailFormViewMixin(object): templated_email_template_name = None templated_email_send_on_success = True templated_email_send_on_failure = False templated_email_from_email = partial(getattr, settings, 'TEMPLATED_EMAIL_FROM_EMAIL', None) def templated_email_get_template_names(self, valid): if self.templated_email_template_name is None: raise ImproperlyConfigured( "TemplatedEmailFormViewMixin requires either a definition of " "'templated_email_template_name' or an implementation of 'templated_email_get_template_names()'") return [self.templated_email_template_name] def templated_email_get_context_data(self, **kwargs): return kwargs def templated_email_get_recipients(self, form): raise NotImplementedError('You must implement templated_email_get_recipients method') def templated_email_get_send_email_kwargs(self, valid, form): if valid: context = self.templated_email_get_context_data(form_data=form.data) else: context = self.templated_email_get_context_data(form_errors=form.errors) try: from_email = self.templated_email_from_email() except TypeError: from_email = self.templated_email_from_email return { 'template_name': self.templated_email_get_template_names(valid=valid), 'from_email': from_email, 'recipient_list': self.templated_email_get_recipients(form), 'context': context } def templated_email_send_templated_mail(self, *args, **kwargs): return send_templated_mail(*args, **kwargs) def form_valid(self, form): response = super(TemplatedEmailFormViewMixin, self).form_valid(form) if self.templated_email_send_on_success: self.templated_email_send_templated_mail( **self.templated_email_get_send_email_kwargs(valid=True, form=form)) return response def form_invalid(self, form): response = super(TemplatedEmailFormViewMixin, self).form_invalid(form) if self.templated_email_send_on_failure: self.templated_email_send_templated_mail( **self.templated_email_get_send_email_kwargs(valid=False, form=form)) return response django-templated-email-3.0.0/templated_email/models.py0000664000175000017500000000033114044653770025430 0ustar tuliovintatuliovinta00000000000000from uuid import uuid4 from django.db import models class SavedEmail(models.Model): uuid = models.UUIDField(default=uuid4) content = models.TextField() created = models.DateTimeField(auto_now_add=True) django-templated-email-3.0.0/templated_email/utils.py0000664000175000017500000000334614054251551025306 0ustar tuliovintatuliovinta00000000000000from functools import partial from email.utils import unquote from email.mime.image import MIMEImage from django.core.mail import make_msgid from django.utils.module_loading import import_string from django.conf import settings def _get_klass_from_config(config_variable, default): klass_path = getattr(settings, config_variable, default) if isinstance(klass_path, str): klass_path = import_string(klass_path) return klass_path get_emailmessage_klass = partial( _get_klass_from_config, 'TEMPLATED_EMAIL_EMAIL_MESSAGE_CLASS', 'django.core.mail.EmailMessage' ) get_emailmultialternatives_klass = partial( _get_klass_from_config, 'TEMPLATED_EMAIL_EMAIL_MULTIALTERNATIVES_CLASS', 'django.core.mail.EmailMultiAlternatives', ) class InlineImage(object): def __init__(self, filename, content, subtype=None, domain=None): self.filename = filename self._content = content self.subtype = subtype self.domain = domain self._content_id = None @property def content(self): return self._content @content.setter def content(self, value): self._content_id = None self._content = value def attach_to_message(self, message): if not self._content_id: self.generate_cid() image = MIMEImage(self.content, self.subtype) image.add_header('Content-Disposition', 'inline', filename=self.filename) image.add_header('Content-ID', self._content_id) message.attach(image) def generate_cid(self): self._content_id = make_msgid('img', self.domain) def __str__(self): if not self._content_id: self.generate_cid() return 'cid:' + unquote(self._content_id) django-templated-email-3.0.0/PKG-INFO0000664000175000017500000005125314056516731021551 0ustar tuliovintatuliovinta00000000000000Metadata-Version: 2.1 Name: django-templated-email Version: 3.0.0 Summary: A Django oriented templated / transaction email abstraction Home-page: http://github.com/vintasoftware/django-templated-email/ Author: Bradley Whittington Author-email: radbrad182@gmail.com License: MIT Description: ============================== Django-Templated-Email ============================== |GitterBadge|_ |PypiversionBadge|_ |PythonVersionsBadge|_ |LicenseBadge|_ :Info: A Django oriented templated email sending class :Author: Bradley Whittington (http://github.com/bradwhittington, http://twitter.com/darb) :Tests: |TravisBadge|_ |CoverageBadge|_ Overview ================= django-templated-email is oriented towards sending templated emails. The library supports template inheritance, adding cc'd and bcc'd recipients, configurable template naming and location. The send_templated_email method can be thought of as the render_to_response shortcut for email. Make sure you are reading the correct documentation: develop branch: https://github.com/vintasoftware/django-templated-email/blob/develop/README.rst stable pypi/master: https://github.com/vintasoftware/django-templated-email/blob/master/README.rst Requirements ================= * Python (3.6, 3.7, 3.8, 3.9) * Django (2.2, 3.1, 3.2) We **highly recommend** and only officially support the latest patch release of each Python and Django series. Getting going - installation ============================== Installing:: pip install django-templated-email You can add the following to your settings.py (but it works out the box): .. code-block:: python TEMPLATED_EMAIL_BACKEND = 'templated_email.backends.vanilla_django.TemplateBackend' # You can use a shortcut version TEMPLATED_EMAIL_BACKEND = 'templated_email.backends.vanilla_django' # You can also use a class directly from templated_email.backends.vanilla_django import TemplateBackend TEMPLATED_EMAIL_BACKEND = TemplateBackend Sending templated emails ============================== Example usage using vanilla_django TemplateBackend backend Python to send mail: .. code-block:: python from templated_email import send_templated_mail send_templated_mail( template_name='welcome', from_email='from@example.com', recipient_list=['to@example.com'], context={ 'username':request.user.username, 'full_name':request.user.get_full_name(), 'signup_date':request.user.date_joined }, # Optional: # cc=['cc@example.com'], # bcc=['bcc@example.com'], # headers={'My-Custom-Header':'Custom Value'}, # template_prefix="my_emails/", # template_suffix="email", ) If you would like finer control on sending the email, you can use **get_templated_email**, which will return a django **EmailMessage** object, prepared using the **vanilla_django** backend: .. code-block:: python from templated_email import get_templated_mail get_templated_mail( template_name='welcome', from_email='from@example.com', to=['to@example.com'], context={ 'username':request.user.username, 'full_name':request.user.get_full_name(), 'signup_date':request.user.date_joined }, # Optional: # cc=['cc@example.com'], # bcc=['bcc@example.com'], # headers={'My-Custom-Header':'Custom Value'}, # template_prefix="my_emails/", # template_suffix="email", ) You can also **cc** and **bcc** recipients using **cc=['example@example.com']**. Your template ------------- The templated_email/ directory needs to be the templates directory. The backend will look in *my_app/templates/templated_email/welcome.email* : .. code-block:: python {% block subject %}My subject for {{username}}{% endblock %} {% block plain %} Hi {{full_name}}, You just signed up for my website, using: username: {{username}} join date: {{signup_date}} Thanks, you rock! {% endblock %} If you want to include an HTML part to your emails, simply use the 'html' block : .. code-block:: python {% block html %}

Hi {{full_name}},

You just signed up for my website, using:

username
{{username}}
join date
{{signup_date}}

Thanks, you rock!

{% endblock %} The plain part can also be calculated from the HTML using `html2text `_. If you don't specify the plain block and `html2text `_ package is installed, the plain part will be calculated from the HTML part. You can disable this behaviour in settings.py : .. code-block:: python TEMPLATED_EMAIL_AUTO_PLAIN = False You can also specify a custom function that converts from HTML to the plain part : .. code-block:: python def convert_html_to_text(html): ... TEMPLATED_EMAIL_PLAIN_FUNCTION = convert_html_to_text You can globally override the template dir, and file extension using the following variables in settings.py : .. code-block:: python TEMPLATED_EMAIL_TEMPLATE_DIR = 'templated_email/' #use '' for top level template dir, ensure there is a trailing slash TEMPLATED_EMAIL_FILE_EXTENSION = 'email' You can also set a value for **template_prefix** and **template_suffix** for every time you call **send_templated_mail**, if you wish to store a set of templates in a different directory. Remember to include a trailing slash. Using with `Django Anymail `_ ========================================================================= Anymail integrates several transactional email service providers (ESPs) into Django, with a consistent API that lets you use ESP-added features without locking your code to a particular ESP. It supports Mailgun, Postmark, SendGrid, SparkPost and more. You can use it with django-templated-email, just follow their instructions in their `quick start `_ to configure it. Optionally you can use their custom `EmailMessage `_ class with django-templated-email by using the following settings: .. code-block:: python # This replaces django.core.mail.EmailMessage TEMPLATED_EMAIL_EMAIL_MESSAGE_CLASS='anymail.message.AnymailMessage' # This replaces django.core.mail.EmailMultiAlternatives TEMPLATED_EMAIL_EMAIL_MULTIALTERNATIVES_CLASS='anymail.message.AnymailMessage' Inline images ============== You can add inline images to your email using the *InlineImage* class. First get the image content from a file or a *ImageField*: .. code-block:: python # From a file with open('pikachu.png', 'rb') as pikachu: image = pikachu.read() # From an ImageField # Suppose we have this model class Company(models.Model): logo = models.ImageField() image = company.logo.read() Then create an instance of *InlineImage*: .. code-block:: python from templated_email import InlineImage inline_image = InlineImage(filename="pikachu.png", content=image) Now pass the object on the context to the template when you send the email. .. code-block:: python send_templated_mail(template_name='welcome', from_email='from@example.com', recipient_list=['to@example.com'], context={'pikachu_image': inline_image}) Finally in your template add the image on the html template block: .. code-block:: html Note: All *InlineImage* objects you add to the context will be attached to the e-mail, even if they are not used in the template. Add link to view the email on the web ===================================== .. code-block:: python # Add templated email to INSTALLED_APPS INSTALLED_APPS = [ ... 'templated_email' ] .. code-block:: python # and this to your url patterns url(r'^', include('templated_email.urls', namespace='templated_email')), .. code-block:: python # when sending the email use the *create_link* parameter. send_templated_mail( template_name='welcome', from_email='from@example.com', recipient_list=['to@example.com'], context={}, create_link=True) And, finally add the link to your template. .. code-block:: html {% if email_uuid %} You can view this e-mail on the web here: here {% endif %} Notes: - A copy of the rendered e-mail will be stored on the database. This can grow if you send too many e-mails. You are responsible for managing it. - If you use *InlineImage* all images will be uploaded to your media storage, keep that in mind too. Class Based Views ================== It's pretty common for emails to be sent after a form is submitted. We include a mixin to be used with any view that inherit from Django's FormMixin. In your view add the mixin and the usual Django's attributes: .. code-block:: python from templated_email.generic_views import TemplatedEmailFormViewMixin class AuthorCreateView(TemplatedEmailFormViewMixin, CreateView): model = Author fields = ['name', 'email'] success_url = '/create_author/' template_name = 'authors/create_author.html' By default the template will have the *form_data* if the form is valid or *from_errors* if the form is not valid in it's context. You can view an example `here `_ Now you can use the following attributes/methods to customize it's behavior: Attributes: **templated_email_template_name** (mandatory if you don't implement **templated_email_get_template_names()**): String naming the template you want to use for the email. ie: templated_email_template_name = 'welcome'. **templated_email_send_on_success** (default: True): This attribute tells django-templated-email to send an email if the form is valid. **templated_email_send_on_failure** (default: False): This attribute tells django-templated-email to send an email if the form is invalid. **templated_email_from_email** (default: **settings.TEMPLATED_EMAIL_FROM_EMAIL**): String containing the email to send the email from. Methods: **templated_email_get_template_names(self, valid)** (mandatory if you don't set **templated_email_template_name**): If the method returns a string it will use it as the template to render the email. If it returns a list it will send the email *only* with the first existing template. **templated_email_get_recipients(self, form)** (mandatory): Return the recipient list to whom the email will be sent to. ie: .. code-block:: python def templated_email_get_recipients(self, form): return [form.data['email']] **templated_email_get_context_data(**kwargs)** (optional): Use this method to add extra data to the context used for rendering the template. You should get the parent class's context from calling super. ie: .. code-block:: python def templated_email_get_context_data(self, **kwargs): context = super(ThisClassView, self).templated_email_get_context_data(**kwargs) # add things to context return context **templated_email_get_send_email_kwargs(self, valid, form)** (optional): Add or change the kwargs that will be used to send the e-mail. You should call super to get the default kwargs. ie: .. code-block:: python def templated_email_get_send_email_kwargs(valid, form): kwargs = super(ThisClassView, self).templated_email_get_send_email_kwargs(valid, form) kwargs['bcc'] = ['admin@example.com'] return kwargs **templated_email_send_templated_mail(*args, **kwargs)** (optional): This method calls django-templated-email's *send_templated_mail* method. You could change this method to use a celery's task for example or to handle errors. Future Plans ============= See https://github.com/vintasoftware/django-templated-email/issues?state=open Using django_templated_email in 3rd party applications ======================================================= If you would like to use django_templated_email to handle mail in a reusable application, you should note that: * Your calls to **send_templated_mail** should set a value for **template_dir**, so you can keep copies of your app-specific templates local to your app (although the loader will find your email templates if you store them in */templates/templated_email*, if **TEMPLATED_EMAIL_TEMPLATE_DIR** has not been overridden) * If you do (and you should) set a value for **template_dir**, remember to include a trailing slash, i.e. *'my_app_email/'* * The deployed app may use a different backend which doesn't use the django templating backend, and as such make a note in your README warning developers that if they are using django_templated_email already, with a different backend, they will need to ensure their email provider can send all your templates (ideally enumerate those somewhere convenient) Notes on specific backends ============================== Using vanilla_django -------------------------- This is the default backend, and as such requires no special configuration, and will work out of the box. By default it assumes the following settings (should you wish to override them): .. code-block:: python TEMPLATED_EMAIL_TEMPLATE_DIR = 'templated_email/' #Use '' for top level template dir TEMPLATED_EMAIL_FILE_EXTENSION = 'email' For legacy purposes you can specify email subjects in your settings file (but, the preferred method is to use a **{% block subject %}** in your template): .. code-block:: python TEMPLATED_EMAIL_DJANGO_SUBJECTS = { 'welcome':'Welcome to my website', } Additionally you can call **send_templated_mail** and optionally override the following parameters:: template_prefix='your_template_dir/' # Override where the method looks for email templates (alternatively, use template_dir) template_suffix='email' # Override the file extension of the email templates (alternatively, use file_extension) cc=['fubar@example.com'] # Set a CC on the mail bcc=['fubar@example.com'] # Set a BCC on the mail template_dir='your_template_dir/' # Override where the method looks for email templates connection=your_connection # Takes a django mail backend connection, created using **django.core.mail.get_connection** auth_user='username' # Override the user that the django mail backend uses, per **django.core.mail.send_mail** auth_password='password' # Override the password that the django mail backend uses, per **django.core.mail.send_mail** Releasing a new version of this package: ======================================== Update CHANGELOG file. Execute the following commands:: bumpversion [major,minor,patch] python setup.py publish git push origin --tags Commercial Support ================== This library, as others, is used in projects of Vinta clients. We are always looking for exciting work, so if you need any commercial support, feel free to get in touch: contact@vinta.com.br .. _Django: http://djangoproject.com .. |GitterBadge| image:: https://badges.gitter.im/vintasoftware/django-templated-email.svg .. _GitterBadge: https://gitter.im/vintasoftware/django-templated-email?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge .. |TravisBadge| image:: https://travis-ci.org/vintasoftware/django-templated-email.svg?branch=develop .. _TravisBadge: https://travis-ci.org/vintasoftware/django-templated-email .. |CoverageBadge| image:: https://coveralls.io/repos/github/vintasoftware/django-templated-email/badge.svg?branch=develop .. _CoverageBadge: https://coveralls.io/github/vintasoftware/django-templated-email?branch=develop .. |PypiversionBadge| image:: https://img.shields.io/pypi/v/django-templated-email.svg .. _PypiversionBadge: https://pypi.python.org/pypi/django-templated-email .. |PythonVersionsBadge| image:: https://img.shields.io/pypi/pyversions/django-templated-email.svg .. _PythonVersionsBadge: https://pypi.python.org/pypi/django-templated-email .. |LicenseBadge| image:: https://img.shields.io/pypi/l/django-templated-email.svg .. _LicenseBadge: https://github.com/vintasoftware/django-templated-email/blob/develop/LICENSE Platform: any Classifier: Development Status :: 5 - Production/Stable Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: MIT License Classifier: Operating System :: OS Independent Classifier: Programming Language :: Python :: 3.6 Classifier: Programming Language :: Python :: 3.7 Classifier: Programming Language :: Python :: 3.8 Classifier: Programming Language :: Python :: 3.9 Classifier: Topic :: Software Development :: Libraries :: Python Modules Classifier: Framework :: Django Description-Content-Type: text/x-rst django-templated-email-3.0.0/MANIFEST.in0000664000175000017500000000014114044653770022202 0ustar tuliovintatuliovinta00000000000000include AUTHORS include LICENSE include README.rst recursive-include templated_email/templates * django-templated-email-3.0.0/setup.py0000664000175000017500000000260714056515065022164 0ustar tuliovintatuliovinta00000000000000import os import sys from setuptools import setup, find_packages DESCRIPTION = "A Django oriented templated / transaction email abstraction" VERSION = '3.0.0' LONG_DESCRIPTION = None try: LONG_DESCRIPTION = open('README.rst').read() except: pass requirements = [ 'django-render-block>=0.5' ] # python setup.py publish if sys.argv[-1] == 'publish': os.system("python setup.py sdist upload") sys.exit() CLASSIFIERS = [ 'Development Status :: 5 - Production/Stable', 'Intended Audience :: Developers', 'License :: OSI Approved :: MIT License', 'Operating System :: OS Independent', 'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.7', 'Programming Language :: Python :: 3.8', 'Programming Language :: Python :: 3.9', 'Topic :: Software Development :: Libraries :: Python Modules', 'Framework :: Django', ] setup( name='django-templated-email', version=VERSION, packages=find_packages(exclude=("tests", "tests.*")), include_package_data=True, author='Bradley Whittington', author_email='radbrad182@gmail.com', url='http://github.com/vintasoftware/django-templated-email/', license='MIT', description=DESCRIPTION, long_description=LONG_DESCRIPTION, long_description_content_type='text/x-rst', platforms=['any'], classifiers=CLASSIFIERS, install_requires=requirements, ) django-templated-email-3.0.0/AUTHORS0000664000175000017500000000051714054247402021513 0ustar tuliovintatuliovinta00000000000000Anatoly Kudinov Anderson Resende Andre Ericson Bradley Whittington Carlos Coelho Ewoud Kohl van Wijngaarden Nitin Hayaran Simon Ye Thomas Levine <_@thomaslevine.com>