2017-07-20 4 views
2

J'expérimente Flask-Security et j'avais des problèmes pour envoyer l'e-mail de confirmation. Je l'ai finalement corrigé en supprimant une ligne dans flask_security/utils.py. J'ai supprimé la ligne 387, forçant flask-mail à utiliser l'expéditeur du courrier app.config.Flask-Confirmation de l'e-mail de sécurité (Flask-Mail) Echec de l'envoi sans modifier flask_security/utils.py

386: msg = Message(subject, 
387:    sender=_security.email_sender, 
388:    recipients=[recipient]) 

Avant le retrait, le code échouerait à flask_mail.py, ligne @ 105 (dans la méthode de sanatize_address), parce que l'adr entrant était une seule chaîne, pas un tuple.

102: def sanitize_address(addr, encoding='utf-8'): 
103:  if isinstance(addr, string_types): 
104:   addr = parseaddr(force_text(addr)) 
105:  nm, addr = addr 

Je voudrais être en mesure d'exécuter mon code sans avoir à modifier flask_security/utils.py chaque fois que j'installer. Aucune suggestion? C'est probablement une étape de ma configuration qui me manque, mais je ne peux pas le dire à partir des docs de flask-security (ils sont un peu limités).

Merci pour l'aide, ci-dessous est mon exemple d'application.

from flask import Flask 
from flask_sqlalchemy import SQLAlchemy 
from flask_security import Security, SQLAlchemyUserDatastore, \ 
    UserMixin, RoleMixin, login_required 
import flask_security.utils 
import flask_mail 

# Create app 
app = Flask(__name__) 
app.config['DEBUG'] = True 
app.config['SECRET_KEY'] = 'super-secret' 
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///db.sqlite' 

# Flask-Security Config 
app.config['SECURITY_PASSWORD_SALT'] = 'super_secret' 
app.config['SECURITY_REGISTERABLE'] = True 
app.config['SECURITY_TRACKABLE'] = True 
app.config['SECURITY_CONFIRMABLE'] = True 
app.config['SECURITY_RECOVERABLE'] = True 

# Mail Config 
app.config['MAIL_SERVER'] = 'smtp.googlemail.com' 
app.config['MAIL_PORT'] = 465 
app.config['MAIL_USE_TLS'] = False 
app.config['MAIL_USE_SSL'] = True 
app.config['MAIL_USERNAME'] = '[email protected]' 
app.config['MAIL_PASSWORD'] = 'password' 
app.config['MAIL_DEFAULT_SENDER'] = app.config['MAIL_USERNAME'] 

mail = flask_mail.Mail(app) 

# Create database connection object 
db = SQLAlchemy(app) 

# Define models 
roles_users = db.Table('roles_users', 
     db.Column('user_id', db.Integer(), db.ForeignKey('user.id')), 
     db.Column('role_id', db.Integer(), db.ForeignKey('role.id'))) 

class Role(db.Model, RoleMixin): 
    id = db.Column(db.Integer(), primary_key=True) 
    name = db.Column(db.String(80), unique=True) 
    description = db.Column(db.String(255)) 

class User(db.Model, UserMixin): 
    id = db.Column(db.Integer, primary_key=True) 
    email = db.Column(db.String(255), unique=True) 
    username = db.Column(db.String(255)) 
    password = db.Column(db.String(255)) 
    last_login_at = db.Column(db.DateTime()) 
    current_login_at = db.Column(db.DateTime()) 
    last_login_ip = db.Column(db.String(100)) 
    current_login_ip = db.Column(db.String(100)) 
    login_count = db.Column(db.Integer) 
    active = db.Column(db.Boolean()) 
    confirmed_at = db.Column(db.DateTime()) 
    roles = db.relationship('Role', secondary='roles_users', 
         backref=db.backref('users', lazy='dynamic')) 

# Setup Flask-Security 
user_datastore = SQLAlchemyUserDatastore(db, User, Role) 
security = Security(app, user_datastore) 

# Create a user to test with 
@app.before_first_request 
def create_user(): 
    db.create_all() 
    user_datastore.create_user(email='[email protected]', password=flask_security.utils.hash_password('password')) 
    db.session.commit() 

# Views 
@app.route('/') 
@login_required 
def home(): 
    return('Here you go!') 

if __name__ == '__main__': 
    app.run() 

Répondre

3

Je trouve aussi cela récemment. Après vérification du code source, je trouve la raison. ps: Je suis un nouvel apprenant en python, donc peut-être, ce qui suit est faux.

Dans votre code, app.config['MAIL_DEFAULT_SENDER'] = app.config['MAIL_USERNAME']. Donc, vérifions le code source pour trouver comment flask-security utilise cette configuration.

Dans flacon-sécurité/core.py:

41: _default_config = { 
... 
87:  'EMAIL_SENDER': LocalProxy(lambda: current_app.config.get(
88:   'MAIL_DEFAULT_SENDER', '[email protected]' 
89: )), 

sinon définir la configuration SECURITY_EMAIL_SENDER, flacon-sécurité utilise un proxy de lambda: current_app.config.get('MAIL_DEFAULT_SENDER', '[email protected]') pour définir SECURITY_EMAIL_SENDER. Attention: SECURITY_EMAIL_SENDER est maintenant une instance LocalProxy.

386: msg = Message(subject, 
387:    sender=_security.email_sender, 
388:    recipients=[recipient]) 

_security.email_sender est une instance LocalProxy.

102: def sanitize_address(addr, encoding='utf-8'): 
103:  if isinstance(addr, string_types): 
104:   addr = parseaddr(force_text(addr)) 
105:  nm, addr = addr 

addr est une instance LocalProxy. Donc isinstance(addr, string_types) est False, nm, addr = addr se passe mal.

Donc, configurez la configuration SECURITY_EMAIL_SENDER pour éviter cette erreur si vous utilisez flask-security.

+0

Merci, qui l'a résolu! Je viens d'ajouter: 'app.config ['SECURITY_EMAIL_SENDER'] = 'example @ gmail.com'' à ma config et ça s'est passé sans problème! –