mirror of
https://github.com/Hopiu/django-fobi.git
synced 2026-03-16 22:10:28 +00:00
prepare 0.13.9
This commit is contained in:
parent
ab60a37bbf
commit
4c8c18cfd2
27 changed files with 687 additions and 32 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -18,6 +18,7 @@ ghostdriver.log
|
|||
tags
|
||||
codebin.py
|
||||
examples/mezzanine_example/dev.db
|
||||
geckodriver.log
|
||||
|
||||
MANIFEST.in~
|
||||
MIND_BUCKET.rst
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ syntax: regexp
|
|||
\.py,cover
|
||||
\.idea/
|
||||
\.pytest_cache/
|
||||
\geckodriver\.log
|
||||
|
||||
^MANIFEST\.in~
|
||||
^tmp/
|
||||
|
|
|
|||
|
|
@ -15,10 +15,27 @@ are used for versioning (schema follows below):
|
|||
0.3.4 to 0.4).
|
||||
- All backwards incompatible changes are mentioned in this document.
|
||||
|
||||
0.13.9
|
||||
------
|
||||
2019-02-28
|
||||
|
||||
.. note::
|
||||
|
||||
Release supported by `Goldmund, Wyldebeast & Wunderliebe
|
||||
<https://goldmund-wyldebeast-wunderliebe.nl/>`_.
|
||||
|
||||
- Add `mail_sender` form handler plugin.
|
||||
- Upgrade test suite.
|
||||
|
||||
0.13.8
|
||||
------
|
||||
2019-01-07
|
||||
|
||||
.. note::
|
||||
|
||||
Release supported by `Goldmund, Wyldebeast & Wunderliebe
|
||||
<https://goldmund-wyldebeast-wunderliebe.nl/>`_.
|
||||
|
||||
- Make it easier to redirect to a new URL (on success) in integration apps.
|
||||
|
||||
0.13.7
|
||||
|
|
|
|||
23
Docker
Normal file
23
Docker
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
# To build:
|
||||
# > docker build -f Dockerfile .
|
||||
FROM python:3.6-stretch
|
||||
ENV DEBIAN_FRONTEND noninteractive
|
||||
|
||||
# Install google chrome
|
||||
RUN wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add
|
||||
RUN echo 'deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main' | tee /etc/apt/sources.list.d/google-chrome.list
|
||||
RUN apt-get update && apt-get upgrade -y
|
||||
RUN apt-get install -y libglib2.0-0=2.50.3-2 \
|
||||
libnss3=2:3.26.2-1.1+deb9u1 \
|
||||
libgconf-2-4=3.2.6-4+b1 \
|
||||
libfontconfig1=2.11.0-6.7+b1
|
||||
RUN apt-get install -y google-chrome-stable
|
||||
RUN apt-get install -y mc
|
||||
|
||||
# Install chrome driver
|
||||
RUN wget -N http://chromedriver.storage.googleapis.com/2.42/chromedriver_linux64.zip
|
||||
RUN unzip chromedriver_linux64.zip
|
||||
RUN chmod +x chromedriver
|
||||
RUN mv -f chromedriver /usr/local/share/chromedriver
|
||||
RUN ln -s /usr/local/share/chromedriver /usr/local/bin/chromedriver
|
||||
RUN ln -s /usr/local/share/chromedriver /usr/bin/chromedriver
|
||||
|
|
@ -51,6 +51,7 @@ recursive-include src/fobi/contrib/plugins/form_elements/content/content_image_u
|
|||
|
||||
recursive-include src/fobi/contrib/plugins/form_handlers/db_store/templates *
|
||||
recursive-include src/fobi/contrib/plugins/form_handlers/mail/templates *
|
||||
recursive-include src/fobi/contrib/plugins/form_handlers/mail_sender/templates *
|
||||
recursive-include src/fobi/contrib/plugins/form_handlers/http_repost/templates *
|
||||
|
||||
recursive-include src/fobi/contrib/plugins/form_importers/mailchimp_importer/templates *
|
||||
|
|
|
|||
|
|
@ -1543,6 +1543,9 @@ README.rst file in directory of each plugin for details.
|
|||
- `Mail
|
||||
<https://github.com/barseghyanartur/django-fobi/tree/stable/src/fobi/contrib/plugins/form_handlers/mail/>`__:
|
||||
Send the form data by email.
|
||||
- `Mail the sender
|
||||
<https://github.com/barseghyanartur/django-fobi/tree/stable/src/fobi/contrib/plugins/form_handlers/mail_sender/>`__:
|
||||
Send the form data by email to the sender (submitter) of the form.
|
||||
|
||||
Integration with third-party apps and frameworks
|
||||
================================================
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
factory_boy==2.11.1
|
||||
Faker==0.8.17
|
||||
Faker==1.0.2
|
||||
py==1.5.4
|
||||
pytest-cov==2.5.1
|
||||
pytest-django==3.3.3
|
||||
pytest-ordering==0.5
|
||||
pytest==3.7.1
|
||||
pytest-cov==2.6.1
|
||||
pytest-django==3.4.8
|
||||
pytest-ordering==0.6
|
||||
pytest==4.3.0
|
||||
selenium==2.53.6
|
||||
tox==3.1.2
|
||||
tox==3.7.0
|
||||
|
|
|
|||
|
|
@ -350,6 +350,7 @@ INSTALLED_APPS = [
|
|||
'fobi.contrib.plugins.form_handlers.db_store',
|
||||
'fobi.contrib.plugins.form_handlers.http_repost',
|
||||
'fobi.contrib.plugins.form_handlers.mail',
|
||||
'fobi.contrib.plugins.form_handlers.mail_sender',
|
||||
|
||||
# ***********************************************************************
|
||||
# ***********************************************************************
|
||||
|
|
|
|||
7
scripts/install_chromedriver.sh
Normal file
7
scripts/install_chromedriver.sh
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
#!/usr/bin/env bash
|
||||
wget -N http://chromedriver.storage.googleapis.com/2.42/chromedriver_linux64.zip
|
||||
unzip chromedriver_linux64.zip
|
||||
chmod +x chromedriver
|
||||
sudo mv -f chromedriver /usr/local/share/chromedriver
|
||||
sudo ln -s /usr/local/share/chromedriver /usr/local/bin/chromedriver
|
||||
sudo ln -s /usr/local/share/chromedriver /usr/bin/chromedriver
|
||||
5
setup.py
5
setup.py
|
|
@ -4,7 +4,7 @@ import sys
|
|||
from distutils.version import LooseVersion
|
||||
from setuptools import setup, find_packages
|
||||
|
||||
version = '0.13.8'
|
||||
version = '0.13.9'
|
||||
|
||||
# ***************************************************************************
|
||||
# ************************** Python version *********************************
|
||||
|
|
@ -140,6 +140,9 @@ template_dirs = [
|
|||
# Mail
|
||||
"src/fobi/contrib/plugins/form_handlers/mail/templates/mail",
|
||||
|
||||
# Mail sender
|
||||
"src/fobi/contrib/plugins/form_handlers/mail_sender/templates/mail_sender",
|
||||
|
||||
# Http re-post
|
||||
"src/fobi/contrib/plugins/form_handlers/http_repost/templates/"
|
||||
"http_repost",
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
__title__ = 'django-fobi'
|
||||
__version__ = '0.13.8'
|
||||
__version__ = '0.13.9'
|
||||
__author__ = 'Artur Barseghyan <artur.barseghyan@gmail.com>'
|
||||
__copyright__ = '2014-2018 Artur Barseghyan'
|
||||
__license__ = 'GPL 2.0/LGPL 2.1'
|
||||
|
|
|
|||
|
|
@ -0,0 +1,34 @@
|
|||
fobi.contrib.plugins.form_handlers.mail_sender
|
||||
----------------------------------------------
|
||||
A ``Fobi`` Mail form handler plugin. Submits the form
|
||||
data by email to the sender (submitter) of the form.
|
||||
|
||||
Installation
|
||||
~~~~~~~~~~~~
|
||||
(1) Add ``fobi.contrib.plugins.form_handlers.mail_sender`` to the
|
||||
``INSTALLED_APPS`` in your ``settings.py``.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
INSTALLED_APPS = (
|
||||
# ...
|
||||
'fobi.contrib.plugins.form_handlers.mail_sender',
|
||||
# ...
|
||||
)
|
||||
|
||||
(2) In the terminal type:
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
./manage.py fobi_sync_plugins
|
||||
|
||||
(3) Assign appropriate permissions to the target users/groups to be using
|
||||
the plugin if ``FOBI_RESTRICT_PLUGIN_ACCESS`` is set to True.
|
||||
|
||||
Usage
|
||||
~~~~~
|
||||
(1) Add the `Mail the sender` form handler to the form.
|
||||
(2) In the value for `Form field name to email` fill in the form field name
|
||||
which shall be used for sending an email to. For instance, if your
|
||||
original form consisted of `name`, `email`, `comment` fields, you should
|
||||
put `email` as a value for `Form field name to email` field.
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
from __future__ import absolute_import
|
||||
|
||||
__title__ = 'fobi.contrib.plugins.form_handlers.mail_sender'
|
||||
__author__ = 'Artur Barseghyan <artur.barseghyan@gmail.com>'
|
||||
__copyright__ = '2014-2018 Artur Barseghyan'
|
||||
__license__ = 'GPL 2.0/LGPL 2.1'
|
||||
__all__ = ('default_app_config', 'UID',)
|
||||
|
||||
default_app_config = 'fobi.contrib.plugins.form_handlers.mail_sender.apps.' \
|
||||
'Config'
|
||||
|
||||
UID = 'mail_sender'
|
||||
15
src/fobi/contrib/plugins/form_handlers/mail_sender/apps.py
Normal file
15
src/fobi/contrib/plugins/form_handlers/mail_sender/apps.py
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
from __future__ import absolute_import
|
||||
from django.apps import AppConfig
|
||||
|
||||
__title__ = 'fobi.contrib.plugins.form_handlers.mail_sender.apps'
|
||||
__author__ = 'Artur Barseghyan <artur.barseghyan@gmail.com>'
|
||||
__copyright__ = '2014-2018 Artur Barseghyan'
|
||||
__license__ = 'GPL 2.0/LGPL 2.1'
|
||||
__all__ = ('Config',)
|
||||
|
||||
|
||||
class Config(AppConfig):
|
||||
"""Config."""
|
||||
|
||||
name = 'fobi.contrib.plugins.form_handlers.mail_sender'
|
||||
label = 'fobi_contrib_plugins_form_handlers_mail_sender'
|
||||
229
src/fobi/contrib/plugins/form_handlers/mail_sender/base.py
Normal file
229
src/fobi/contrib/plugins/form_handlers/mail_sender/base.py
Normal file
|
|
@ -0,0 +1,229 @@
|
|||
from __future__ import absolute_import
|
||||
|
||||
import datetime
|
||||
from mimetypes import guess_type
|
||||
import os
|
||||
|
||||
from six import string_types, PY3
|
||||
|
||||
from django.conf import settings
|
||||
from django.template.loader import render_to_string
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from .....base import (
|
||||
FormHandlerPlugin,
|
||||
FormWizardHandlerPlugin,
|
||||
get_processed_form_data,
|
||||
get_processed_form_wizard_data,
|
||||
)
|
||||
from .....helpers import (
|
||||
safe_text,
|
||||
extract_file_path,
|
||||
get_form_element_entries_for_form_wizard_entry,
|
||||
)
|
||||
|
||||
from . import UID
|
||||
from .forms import MailSenderForm
|
||||
from .helpers import send_mail
|
||||
from .mixins import MailSenderHandlerMixin
|
||||
from .settings import MULTI_EMAIL_FIELD_VALUE_SPLITTER
|
||||
|
||||
__title__ = 'fobi.contrib.plugins.form_handlers.mail_sender.base'
|
||||
__author__ = 'Artur Barseghyan <artur.barseghyan@gmail.com>'
|
||||
__copyright__ = '2014-2018 Artur Barseghyan'
|
||||
__license__ = 'GPL 2.0/LGPL 2.1'
|
||||
__all__ = (
|
||||
'MailSenderHandlerPlugin',
|
||||
'MailSenderWizardHandlerPlugin',
|
||||
)
|
||||
|
||||
# *****************************************************************************
|
||||
# **************************** Form handler ***********************************
|
||||
# *****************************************************************************
|
||||
|
||||
|
||||
class MailSenderHandlerPlugin(FormHandlerPlugin, MailSenderHandlerMixin):
|
||||
"""Mail handler plugin.
|
||||
|
||||
Sends emails to the person specified. Should be executed before
|
||||
``db_store`` and ``http_repost`` plugins.
|
||||
"""
|
||||
|
||||
uid = UID
|
||||
name = _("Mail the sender")
|
||||
form = MailSenderForm
|
||||
|
||||
def run(self, form_entry, request, form, form_element_entries=None):
|
||||
"""Run.
|
||||
|
||||
:param fobi.models.FormEntry form_entry: Instance of
|
||||
``fobi.models.FormEntry``.
|
||||
:param django.http.HttpRequest request:
|
||||
:param django.forms.Form form:
|
||||
:param iterable form_element_entries: Iterable of
|
||||
``fobi.models.FormElementEntry`` objects.
|
||||
"""
|
||||
base_url = self.get_base_url(request)
|
||||
|
||||
# Clean up the values, leave our content fields and empty values.
|
||||
field_name_to_label_map, cleaned_data = get_processed_form_data(
|
||||
form,
|
||||
form_element_entries
|
||||
)
|
||||
|
||||
rendered_data = self.get_rendered_data(
|
||||
cleaned_data,
|
||||
field_name_to_label_map,
|
||||
base_url
|
||||
)
|
||||
|
||||
files = self._prepare_files(request, form)
|
||||
|
||||
self.send_email(rendered_data, cleaned_data, files)
|
||||
|
||||
def plugin_data_repr(self):
|
||||
"""Human readable representation of plugin data.
|
||||
|
||||
:return string:
|
||||
"""
|
||||
context = {
|
||||
'to_name': safe_text(self.data.to_name),
|
||||
'form_field_name_to_email': self.data.form_field_name_to_email,
|
||||
'subject': safe_text(self.data.subject),
|
||||
}
|
||||
return render_to_string('mail_sender/plugin_data_repr.html', context)
|
||||
|
||||
|
||||
# *****************************************************************************
|
||||
# ************************ Form wizard handler ********************************
|
||||
# *****************************************************************************
|
||||
|
||||
|
||||
class MailSenderWizardHandlerPlugin(FormWizardHandlerPlugin):
|
||||
"""Mail wizard handler plugin.
|
||||
|
||||
Sends emails to the person specified. Should be executed before
|
||||
``db_store`` and ``http_repost`` plugins.
|
||||
"""
|
||||
|
||||
uid = UID
|
||||
name = _("Mail the sender")
|
||||
form = MailSenderForm
|
||||
|
||||
def run(self, form_wizard_entry, request, form_list, form_wizard,
|
||||
form_element_entries=None):
|
||||
"""Run.
|
||||
|
||||
:param fobi.models.FormWizardEntry form_wizard_entry: Instance
|
||||
of :class:`fobi.models.FormWizardEntry`.
|
||||
:param django.http.HttpRequest request:
|
||||
:param list form_list: List of :class:`django.forms.Form` instances.
|
||||
:param fobi.wizard.views.dynamic.DynamicWizardView form_wizard:
|
||||
Instance of :class:`fobi.wizard.views.dynamic.DynamicWizardView`.
|
||||
:param iterable form_element_entries: Iterable of
|
||||
``fobi.models.FormElementEntry`` objects.
|
||||
"""
|
||||
base_url = 'http{secure}://{host}'.format(
|
||||
secure=('s' if request.is_secure() else ''),
|
||||
host=request.get_host()
|
||||
)
|
||||
|
||||
if not form_element_entries:
|
||||
form_element_entries = \
|
||||
get_form_element_entries_for_form_wizard_entry(
|
||||
form_wizard_entry
|
||||
)
|
||||
|
||||
# Clean up the values, leave our content fields and empty values.
|
||||
field_name_to_label_map, cleaned_data = get_processed_form_wizard_data(
|
||||
form_wizard,
|
||||
form_list,
|
||||
form_element_entries
|
||||
)
|
||||
|
||||
rendered_data = []
|
||||
for key, value in cleaned_data.items():
|
||||
if value and isinstance(value, string_types) \
|
||||
and value.startswith(settings.MEDIA_URL):
|
||||
cleaned_data[key] = '{base_url}{value}'.format(
|
||||
base_url=base_url, value=value
|
||||
)
|
||||
label = field_name_to_label_map.get(key, key)
|
||||
rendered_data.append('{0}: {1}\n'.format(
|
||||
safe_text(label), safe_text(cleaned_data[key]))
|
||||
)
|
||||
|
||||
files = self._prepare_files(request, form_list)
|
||||
|
||||
to_email = cleaned_data.get(self.data.form_field_name_to_email)
|
||||
# Handling more than one email address
|
||||
if isinstance(to_email, (list, tuple)):
|
||||
pass # Anything else needed here?
|
||||
else:
|
||||
# Assume that it's string
|
||||
to_email = to_email.split(
|
||||
MULTI_EMAIL_FIELD_VALUE_SPLITTER
|
||||
)
|
||||
|
||||
send_mail(
|
||||
safe_text(self.data.subject),
|
||||
"{0}\n\n{1}".format(
|
||||
safe_text(self.data.body),
|
||||
''.join(rendered_data)
|
||||
),
|
||||
self.data.from_email,
|
||||
to_email,
|
||||
fail_silently=False,
|
||||
attachments=files.values()
|
||||
)
|
||||
|
||||
def _prepare_files(self, request, form_list):
|
||||
"""Prepares the files for being attached to the mail message."""
|
||||
files = {}
|
||||
|
||||
def process_path(file_path, imf):
|
||||
"""Processes the file path and the file."""
|
||||
if file_path:
|
||||
# if file_path.startswith(settings.MEDIA_URL):
|
||||
# file_path = file_path[1:]
|
||||
# file_path = settings.PROJECT_DIR('../{0}'.format(file_path))
|
||||
file_path = file_path.replace(
|
||||
settings.MEDIA_URL,
|
||||
os.path.join(settings.MEDIA_ROOT, '')
|
||||
)
|
||||
mime_type = guess_type(imf.name)
|
||||
if PY3:
|
||||
imf_chunks = b''.join([c for c in imf.chunks()])
|
||||
else:
|
||||
imf_chunks = ''.join([c for c in imf.chunks()])
|
||||
|
||||
files[field_name] = (
|
||||
imf.name,
|
||||
imf_chunks,
|
||||
mime_type[0] if mime_type else ''
|
||||
)
|
||||
|
||||
for form in form_list:
|
||||
for field_name, imf in request.FILES.items():
|
||||
try:
|
||||
file_path = form.cleaned_data.get(field_name, '')
|
||||
process_path(file_path, imf)
|
||||
except Exception as err:
|
||||
file_path = extract_file_path(imf.name)
|
||||
process_path(file_path, imf)
|
||||
|
||||
return files
|
||||
|
||||
def plugin_data_repr(self):
|
||||
"""Human readable representation of plugin data.
|
||||
|
||||
:return string:
|
||||
"""
|
||||
context = {
|
||||
'to_name': safe_text(self.data.to_name),
|
||||
'form_field_name_to_email': safe_text(
|
||||
self.data.form_field_name_to_email
|
||||
),
|
||||
'subject': safe_text(self.data.subject),
|
||||
}
|
||||
return render_to_string('mail_sender/plugin_data_repr.html', context)
|
||||
30
src/fobi/contrib/plugins/form_handlers/mail_sender/conf.py
Normal file
30
src/fobi/contrib/plugins/form_handlers/mail_sender/conf.py
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
from django.conf import settings
|
||||
|
||||
from . import defaults
|
||||
|
||||
__title__ = 'fobi.contrib.plugins.form_handlers.mail_sender.conf'
|
||||
__author__ = 'Artur Barseghyan <artur.barseghyan@gmail.com>'
|
||||
__copyright__ = '2014-2018 Artur Barseghyan'
|
||||
__license__ = 'GPL 2.0/LGPL 2.1'
|
||||
__all__ = ('get_setting',)
|
||||
|
||||
|
||||
def get_setting(setting, override=None):
|
||||
"""Get setting.
|
||||
|
||||
Get a setting from ``fobi.contrib.plugins.form_handlers.mail`` conf
|
||||
module, falling back to the default.
|
||||
|
||||
If override is not None, it will be used instead of the setting.
|
||||
|
||||
:param setting: String with setting name
|
||||
:param override: Value to use when no setting is available. Defaults to
|
||||
None.
|
||||
:return: Setting value.
|
||||
"""
|
||||
if override is not None:
|
||||
return override
|
||||
if hasattr(settings, 'FOBI_PLUGIN_MAIL_SENDER_{0}'.format(setting)):
|
||||
return getattr(settings, 'FOBI_PLUGIN_MAIL_SENDER_{0}'.format(setting))
|
||||
else:
|
||||
return getattr(defaults, setting)
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
__title__ = 'fobi.contrib.plugins.form_handlers.mail_sender.defaults'
|
||||
__author__ = 'Artur Barseghyan <artur.barseghyan@gmail.com>'
|
||||
__copyright__ = '2014-2018 Artur Barseghyan'
|
||||
__license__ = 'GPL 2.0/LGPL 2.1'
|
||||
__all__ = (
|
||||
'AUTO_MAIL_BODY',
|
||||
'AUTO_MAIL_FROM',
|
||||
'AUTO_MAIL_SUBJECT',
|
||||
'AUTO_MAIL_TO',
|
||||
'MULTI_EMAIL_FIELD_VALUE_SPLITTER',
|
||||
)
|
||||
|
||||
|
||||
MULTI_EMAIL_FIELD_VALUE_SPLITTER = ',' # But can be '\n'
|
||||
AUTO_MAIL_TO = []
|
||||
AUTO_MAIL_SUBJECT = 'Automatic email'
|
||||
AUTO_MAIL_BODY = 'Automatic email'
|
||||
AUTO_MAIL_FROM = ''
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
from .....base import (
|
||||
form_handler_plugin_registry,
|
||||
form_wizard_handler_plugin_registry,
|
||||
)
|
||||
from .base import MailSenderHandlerPlugin, MailSenderWizardHandlerPlugin
|
||||
|
||||
__title__ = 'fobi.contrib.plugins.form_handlers.mail_sender.fobi_form_handlers'
|
||||
__author__ = 'Artur Barseghyan <artur.barseghyan@gmail.com>'
|
||||
__copyright__ = '2014-2015 Artur Barseghyan'
|
||||
__license__ = 'GPL 2.0/LGPL 2.1'
|
||||
__all__ = (
|
||||
'MailSenderHandlerPlugin',
|
||||
'MailSenderWizardHandlerPlugin',
|
||||
)
|
||||
|
||||
|
||||
form_handler_plugin_registry.register(MailSenderHandlerPlugin)
|
||||
form_wizard_handler_plugin_registry.register(MailSenderWizardHandlerPlugin)
|
||||
71
src/fobi/contrib/plugins/form_handlers/mail_sender/forms.py
Normal file
71
src/fobi/contrib/plugins/form_handlers/mail_sender/forms.py
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
from __future__ import absolute_import
|
||||
|
||||
from django import forms
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from .....base import BasePluginForm, get_theme
|
||||
|
||||
__title__ = 'fobi.contrib.plugins.form_handlers.mail_sender.forms'
|
||||
__author__ = 'Artur Barseghyan <artur.barseghyan@gmail.com>'
|
||||
__copyright__ = '2014-2018 Artur Barseghyan'
|
||||
__license__ = 'GPL 2.0/LGPL 2.1'
|
||||
__all__ = ('MailSenderForm',)
|
||||
|
||||
theme = get_theme(request=None, as_instance=True)
|
||||
|
||||
|
||||
class MailSenderForm(forms.Form, BasePluginForm):
|
||||
"""Form for ``BooleanSelectPlugin``."""
|
||||
|
||||
plugin_data_fields = [
|
||||
("from_name", ""),
|
||||
("from_email", ""),
|
||||
("to_name", ""),
|
||||
("form_field_name_to_email", ""),
|
||||
("subject", ""),
|
||||
("body", ""),
|
||||
]
|
||||
|
||||
from_name = forms.CharField(
|
||||
label=_("From name"),
|
||||
required=True,
|
||||
widget=forms.widgets.TextInput(
|
||||
attrs={'class': theme.form_element_html_class}
|
||||
)
|
||||
)
|
||||
from_email = forms.EmailField(
|
||||
label=_("From email"),
|
||||
required=True,
|
||||
widget=forms.widgets.TextInput(
|
||||
attrs={'class': theme.form_element_html_class}
|
||||
)
|
||||
)
|
||||
to_name = forms.CharField(
|
||||
label=_("To name"),
|
||||
required=True,
|
||||
widget=forms.widgets.TextInput(
|
||||
attrs={'class': theme.form_element_html_class}
|
||||
)
|
||||
)
|
||||
form_field_name_to_email = forms.CharField(
|
||||
label=_("Form field name to email"),
|
||||
required=True,
|
||||
help_text=_("Name of the form field to be used as email."),
|
||||
widget=forms.widgets.TextInput(
|
||||
attrs={'class': theme.form_element_html_class}
|
||||
)
|
||||
)
|
||||
subject = forms.CharField(
|
||||
label=_("Subject"),
|
||||
required=True,
|
||||
widget=forms.widgets.TextInput(
|
||||
attrs={'class': theme.form_element_html_class}
|
||||
)
|
||||
)
|
||||
body = forms.CharField(
|
||||
label=_("Body"),
|
||||
required=False,
|
||||
widget=forms.widgets.Textarea(
|
||||
attrs={'class': theme.form_element_html_class}
|
||||
)
|
||||
)
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
from __future__ import absolute_import
|
||||
|
||||
from django.core.mail import get_connection
|
||||
from django.core.mail.message import EmailMultiAlternatives
|
||||
|
||||
__title__ = 'fobi.contrib.plugins.form_handlers.mail_sender.helpers'
|
||||
__author__ = 'Artur Barseghyan <artur.barseghyan@gmail.com>'
|
||||
__copyright__ = '2014-2018 Artur Barseghyan'
|
||||
__license__ = 'GPL 2.0/LGPL 2.1'
|
||||
__all__ = ('send_mail',)
|
||||
|
||||
|
||||
def send_mail(subject, message, from_email, recipient_list,
|
||||
fail_silently=False, auth_user=None, auth_password=None,
|
||||
connection=None, html_message=None, attachments=None):
|
||||
"""Send email.
|
||||
|
||||
Easy wrapper for sending a single message to a recipient list. All members
|
||||
of the recipient list will see the other recipients in the 'To' field.
|
||||
|
||||
If auth_user is None, the EMAIL_HOST_USER setting is used.
|
||||
If auth_password is None, the EMAIL_HOST_PASSWORD setting is used.
|
||||
|
||||
Note: The API for this method is frozen. New code wanting to extend the
|
||||
functionality should use the EmailMessage class directly.
|
||||
"""
|
||||
connection = connection or get_connection(username=auth_user,
|
||||
password=auth_password,
|
||||
fail_silently=fail_silently)
|
||||
mail = EmailMultiAlternatives(subject, message, from_email, recipient_list,
|
||||
connection=connection,
|
||||
attachments=attachments)
|
||||
if html_message:
|
||||
mail.attach_alternative(html_message, 'text/html')
|
||||
|
||||
return mail.send()
|
||||
131
src/fobi/contrib/plugins/form_handlers/mail_sender/mixins.py
Normal file
131
src/fobi/contrib/plugins/form_handlers/mail_sender/mixins.py
Normal file
|
|
@ -0,0 +1,131 @@
|
|||
from __future__ import absolute_import, unicode_literals
|
||||
|
||||
import datetime
|
||||
from mimetypes import guess_type
|
||||
import os
|
||||
|
||||
from six import string_types, PY3
|
||||
|
||||
from django.conf import settings
|
||||
|
||||
from .....helpers import extract_file_path, safe_text
|
||||
|
||||
from .helpers import send_mail
|
||||
from .settings import MULTI_EMAIL_FIELD_VALUE_SPLITTER
|
||||
|
||||
__title__ = 'fobi.contrib.plugins.form_handlers.mail_sender.mixins'
|
||||
__author__ = 'Artur Barseghyan <artur.barseghyan@gmail.com>'
|
||||
__copyright__ = '2014-2018 Artur Barseghyan'
|
||||
__license__ = 'GPL 2.0/LGPL 2.1'
|
||||
__all__ = (
|
||||
'MailSenderHandlerMixin',
|
||||
)
|
||||
|
||||
# *****************************************************************************
|
||||
# **************************** Form handler ***********************************
|
||||
# *****************************************************************************
|
||||
|
||||
|
||||
class MailSenderHandlerMixin(object):
|
||||
"""Mail handler mixin."""
|
||||
|
||||
def get_base_url(self, request):
|
||||
"""Get base URL.
|
||||
|
||||
Might be used in integration packages.
|
||||
"""
|
||||
base_url = 'http{secure}://{host}'.format(
|
||||
secure=('s' if request.is_secure() else ''),
|
||||
host=request.get_host()
|
||||
)
|
||||
return base_url
|
||||
|
||||
def get_rendered_data(self,
|
||||
cleaned_data,
|
||||
field_name_to_label_map,
|
||||
base_url):
|
||||
"""Get rendered data.
|
||||
|
||||
Might be used in integration packages.
|
||||
"""
|
||||
rendered_data = []
|
||||
for key, value in cleaned_data.items():
|
||||
if value:
|
||||
if isinstance(value, string_types) \
|
||||
and value.startswith(settings.MEDIA_URL):
|
||||
cleaned_data[key] = '{base_url}{value}'.format(
|
||||
base_url=base_url, value=value
|
||||
)
|
||||
|
||||
if isinstance(value, (datetime.datetime, datetime.date)):
|
||||
cleaned_data[key] = value.isoformat() \
|
||||
if hasattr(value, 'isoformat') \
|
||||
else value
|
||||
|
||||
label = field_name_to_label_map.get(key, key)
|
||||
rendered_data.append('{0}: {1}\n'.format(
|
||||
safe_text(label), safe_text(cleaned_data[key]))
|
||||
)
|
||||
return rendered_data
|
||||
|
||||
def send_email(self, rendered_data, cleaned_data, files):
|
||||
"""Send email.
|
||||
|
||||
Might be used in integration packages.
|
||||
"""
|
||||
to_email = cleaned_data.get(self.data.form_field_name_to_email)
|
||||
# Handling more than one email address
|
||||
if isinstance(to_email, (list, tuple)):
|
||||
pass # Anything else needed here?
|
||||
else:
|
||||
# Assume that it's string
|
||||
to_email = to_email.split(
|
||||
MULTI_EMAIL_FIELD_VALUE_SPLITTER
|
||||
)
|
||||
|
||||
send_mail(
|
||||
safe_text(self.data.subject),
|
||||
u"{0}\n\n{1}".format(
|
||||
safe_text(self.data.body),
|
||||
''.join(rendered_data)
|
||||
),
|
||||
self.data.from_email,
|
||||
to_email,
|
||||
fail_silently=False,
|
||||
attachments=files.values()
|
||||
)
|
||||
|
||||
def _prepare_files(self, request, form):
|
||||
"""Prepares the files for being attached to the mail message."""
|
||||
files = {}
|
||||
|
||||
def process_path(file_path, imf):
|
||||
"""Processes the file path and the file."""
|
||||
if file_path:
|
||||
# if file_path.startswith(settings.MEDIA_URL):
|
||||
# file_path = file_path[1:]
|
||||
# file_path = settings.PROJECT_DIR('../{0}'.format(file_path))
|
||||
file_path = file_path.replace(
|
||||
settings.MEDIA_URL,
|
||||
os.path.join(settings.MEDIA_ROOT, '')
|
||||
)
|
||||
mime_type = guess_type(imf.name)
|
||||
if PY3:
|
||||
imf_chunks = b''.join([c for c in imf.chunks()])
|
||||
else:
|
||||
imf_chunks = str('').join([c for c in imf.chunks()])
|
||||
files[field_name] = (
|
||||
imf.name,
|
||||
imf_chunks,
|
||||
mime_type[0] if mime_type else ''
|
||||
)
|
||||
|
||||
for field_name, imf in request.FILES.items():
|
||||
try:
|
||||
file_path = form.cleaned_data.get(field_name, '')
|
||||
process_path(file_path, imf)
|
||||
except Exception as err:
|
||||
file_path = extract_file_path(imf.name)
|
||||
process_path(file_path, imf)
|
||||
|
||||
return files
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
from .conf import get_setting
|
||||
|
||||
__title__ = 'fobi.contrib.plugins.form_handlers.mail_sender.settings'
|
||||
__author__ = 'Artur Barseghyan <artur.barseghyan@gmail.com>'
|
||||
__copyright__ = '2014-2018 Artur Barseghyan'
|
||||
__license__ = 'GPL 2.0/LGPL 2.1'
|
||||
__all__ = (
|
||||
'MULTI_EMAIL_FIELD_VALUE_SPLITTER',
|
||||
)
|
||||
|
||||
MULTI_EMAIL_FIELD_VALUE_SPLITTER = get_setting(
|
||||
'MULTI_EMAIL_FIELD_VALUE_SPLITTER'
|
||||
)
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
{% load i18n %}
|
||||
<p><strong>{% trans "To" %}</strong>: Form field name to email: "{{ form_field_name_to_email|striptags }}"</p>
|
||||
<p><strong>{% trans "Subject" %}</strong>: {{ subject|striptags }}</p>
|
||||
|
|
@ -62,6 +62,7 @@ __all__ = (
|
|||
'do_slugify',
|
||||
'empty_string',
|
||||
'ensure_unique_filename',
|
||||
'extract_file_path',
|
||||
'flatatt_inverse_quotes',
|
||||
'get_app_label_and_model_name',
|
||||
'get_form_element_entries_for_form_wizard_entry',
|
||||
|
|
|
|||
|
|
@ -1,17 +0,0 @@
|
|||
from __future__ import print_function
|
||||
|
||||
import unittest
|
||||
|
||||
from .tests.test_browser_build_dynamic_forms import *
|
||||
from .tests.test_core import *
|
||||
from .tests.test_dynamic_forms import *
|
||||
from .tests.test_sortable_dict import *
|
||||
|
||||
__title__ = 'fobi.test'
|
||||
__author__ = 'Artur Barseghyan <artur.barseghyan@gmail.com>'
|
||||
__copyright__ = '2014-2018 Artur Barseghyan'
|
||||
__license__ = 'GPL 2.0/LGPL 2.1'
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
|
@ -68,6 +68,8 @@ from fobi.contrib.plugins.form_handlers \
|
|||
.db_store.fobi_form_handlers import DBStoreHandlerPlugin
|
||||
from fobi.contrib.plugins.form_handlers \
|
||||
.mail.fobi_form_handlers import MailHandlerPlugin
|
||||
from fobi.contrib.plugins.form_handlers \
|
||||
.mail_sender.fobi_form_handlers import MailSenderHandlerPlugin
|
||||
from fobi.contrib.plugins.form_handlers \
|
||||
.http_repost.fobi_form_handlers import HTTPRepostHandlerPlugin
|
||||
|
||||
|
|
@ -96,13 +98,6 @@ TEST_FORM_ELEMENT_PLUGIN_DATA = {
|
|||
'required': False,
|
||||
},
|
||||
|
||||
# Add a "Select multiple" (select multiple input) form elelement
|
||||
# force_text(CheckboxSelectMultipleInputPlugin.name): {
|
||||
# 'label': "Test checkbox select multiple input",
|
||||
# 'help_text': "Lorem ipsum select multiple input",
|
||||
# 'required': False,
|
||||
# },
|
||||
|
||||
# Add a "Date" input form element
|
||||
force_text(DateInputPlugin.name): {
|
||||
'label': "Test date input",
|
||||
|
|
@ -292,6 +287,14 @@ TEST_FORM_HANDLER_PLUGIN_DATA = {
|
|||
'subject': "Test email subject",
|
||||
'body': "Test email body",
|
||||
},
|
||||
force_text(MailSenderHandlerPlugin.name): {
|
||||
'from_name': "From me",
|
||||
'from_email': "from@example.com",
|
||||
'to_name': "To you",
|
||||
'form_field_name_to_email': "test_email_input",
|
||||
'subject': "Test email subject",
|
||||
'body': "Test email body",
|
||||
},
|
||||
force_text(HTTPRepostHandlerPlugin.name): {
|
||||
'endpoint_url': 'http://dev.example.com'
|
||||
}
|
||||
|
|
|
|||
|
|
@ -502,6 +502,7 @@ class FobiBrowserBuldDynamicFormsTest(BaseFobiBrowserBuldDynamicFormsTest):
|
|||
|
||||
# Add form elements
|
||||
self._test_add_form_elements(create_form=True)
|
||||
self._test_add_form_handlers(create_form=False)
|
||||
|
||||
# self._sleep(wait)
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue