Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make send_mail fn customizable #1

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
39 changes: 37 additions & 2 deletions docs/customizing.rst
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ decorator like so::
send_security_email.delay(msg)

If factory method is going to be used for initialization, use ``_SecurityState``
object returned by ``init_app`` method to initialize Celery tasks intead of using
object returned by ``init_app`` method to initialize Celery tasks instead of using
``security.send_mail_task`` directly like so::

from flask import Flask
Expand Down Expand Up @@ -192,7 +192,7 @@ object returned by ``init_app`` method to initialize Celery tasks intead of usin
def delay_flask_security_mail(msg):
send_flask_mail.delay(msg)

# A shortcurt.
# A shortcut.
security_ctx.send_mail_task(send_flask_mail.delay)

return app
Expand All @@ -213,6 +213,41 @@ Celery. The practical way with custom serialization may look like so::
.. _Celery: http://www.celeryproject.org/


Custom send_mail method
-----------------------

It's also possible to completely override the ``security.send_mail`` method to
implement your own logic, like so:

from flask import Flask
from flask_mail import Mail
from flask_security import Security, SQLAlchemyUserDatastore
from celery import Celery

mail = Mail()
security = Security()
celery = Celery()

def create_app(config):
"""Initialize Flask instance."""

app = Flask(__name__)
app.config.from_object(config)

def custom_send_mail(subject, recipient, template, **context):
# implement your own logic here
pass

mail.init_app(app)
datastore = SQLAlchemyUserDatastore(db, User, Role)
security_ctx.send_mail = custom_send_mail

return app

Note that the above ``security.send_mail_task`` override will be useless if you
override the entire ``send_mail`` method.


Authorization with OAuth2
-------------------------

Expand Down
4 changes: 2 additions & 2 deletions flask_security/changeable.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
from werkzeug.local import LocalProxy

from .signals import password_changed
from .utils import config_value, hash_password, send_mail
from .utils import config_value, hash_password

# Convenient references
_security = LocalProxy(lambda: current_app.extensions['security'])
Expand All @@ -29,7 +29,7 @@ def send_password_changed_notice(user):
"""
if config_value('SEND_PASSWORD_CHANGE_EMAIL'):
subject = config_value('EMAIL_SUBJECT_PASSWORD_CHANGE_NOTICE')
send_mail(subject, user.email, 'change_notice', user=user)
_security.send_mail(subject, user.email, 'change_notice', user=user)


def change_user_password(user, password):
Expand Down
8 changes: 4 additions & 4 deletions flask_security/confirmable.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
from werkzeug.local import LocalProxy

from .signals import confirm_instructions_sent, user_confirmed
from .utils import config_value, get_token_status, hash_data, send_mail, \
from .utils import config_value, get_token_status, hash_data, \
url_for_security, verify_hash

# Convenient references
Expand All @@ -39,9 +39,9 @@ def send_confirmation_instructions(user):

confirmation_link, token = generate_confirmation_link(user)

send_mail(config_value('EMAIL_SUBJECT_CONFIRM'), user.email,
'confirmation_instructions', user=user,
confirmation_link=confirmation_link)
_security.send_mail(config_value('EMAIL_SUBJECT_CONFIRM'), user.email,
'confirmation_instructions', user=user,
confirmation_link=confirmation_link)

confirm_instructions_sent.send(app._get_current_object(), user=user,
token=token)
Expand Down
6 changes: 5 additions & 1 deletion flask_security/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
ResetPasswordForm, SendConfirmationForm
from .utils import config_value as cv
from .utils import _, get_config, hash_data, localize_callback, string_types, \
url_for_security, verify_hash
url_for_security, verify_hash, send_mail
from .views import create_blueprint

# Convenient references
Expand Down Expand Up @@ -539,6 +539,7 @@ def _register_i18n():
app.jinja_env.globals['_'] = state.i18n_domain.gettext

state.render_template = self.render_template
state.send_mail = self.send_mail
app.extensions['security'] = state

if hasattr(app, 'cli'):
Expand All @@ -553,5 +554,8 @@ def _register_i18n():
def render_template(self, *args, **kwargs):
return render_template(*args, **kwargs)

def send_mail(self, *args, **kwargs):
return send_mail(*args, **kwargs)

def __getattr__(self, name):
return getattr(self._state, name, None)
6 changes: 3 additions & 3 deletions flask_security/passwordless.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
from werkzeug.local import LocalProxy

from .signals import login_instructions_sent
from .utils import config_value, get_token_status, send_mail, url_for_security
from .utils import config_value, get_token_status, url_for_security

# Convenient references
_security = LocalProxy(lambda: app.extensions['security'])
Expand All @@ -30,8 +30,8 @@ def send_login_instructions(user):
token = generate_login_token(user)
login_link = url_for_security('token_login', token=token, _external=True)

send_mail(config_value('EMAIL_SUBJECT_PASSWORDLESS'), user.email,
'login_instructions', user=user, login_link=login_link)
_security.send_mail(config_value('EMAIL_SUBJECT_PASSWORDLESS'), user.email,
'login_instructions', user=user, login_link=login_link)

login_instructions_sent.send(app._get_current_object(), user=user,
login_token=token)
Expand Down
12 changes: 6 additions & 6 deletions flask_security/recoverable.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

from .signals import password_reset, reset_password_instructions_sent
from .utils import config_value, get_token_status, hash_data, hash_password, \
send_mail, url_for_security, verify_hash
url_for_security, verify_hash

# Convenient references
_security = LocalProxy(lambda: app.extensions['security'])
Expand All @@ -33,9 +33,9 @@ def send_reset_password_instructions(user):
)

if config_value('SEND_PASSWORD_RESET_EMAIL'):
send_mail(config_value('EMAIL_SUBJECT_PASSWORD_RESET'), user.email,
'reset_instructions',
user=user, reset_link=reset_link)
_security.send_mail(config_value('EMAIL_SUBJECT_PASSWORD_RESET'),
user.email, 'reset_instructions',
user=user, reset_link=reset_link)

reset_password_instructions_sent.send(
app._get_current_object(), user=user, token=token
Expand All @@ -48,8 +48,8 @@ def send_password_reset_notice(user):
:param user: The user to send the notice to
"""
if config_value('SEND_PASSWORD_RESET_NOTICE_EMAIL'):
send_mail(config_value('EMAIL_SUBJECT_PASSWORD_NOTICE'), user.email,
'reset_notice', user=user)
_security.send_mail(config_value('EMAIL_SUBJECT_PASSWORD_NOTICE'),
user.email, 'reset_notice', user=user)


def generate_reset_password_token(user):
Expand Down
8 changes: 4 additions & 4 deletions flask_security/registerable.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@

from .confirmable import generate_confirmation_link
from .signals import user_registered
from .utils import config_value, do_flash, get_message, hash_password, \
send_mail
from .utils import config_value, do_flash, get_message, hash_password

# Convenient references
_security = LocalProxy(lambda: app.extensions['security'])
Expand All @@ -37,7 +36,8 @@ def register_user(**kwargs):
user=user, confirm_token=token)

if config_value('SEND_REGISTER_EMAIL'):
send_mail(config_value('EMAIL_SUBJECT_REGISTER'), user.email,
'welcome', user=user, confirmation_link=confirmation_link)
_security.send_mail(config_value('EMAIL_SUBJECT_REGISTER'), user.email,
'welcome', user=user,
confirmation_link=confirmation_link)

return user