Flask (parte 7): mail
Per notificare un evento ad uno User, utilizzeremo il pacchetto Flask-Mail,
che integra in maniera efficiente smtplib con flask.
Per installarlo:
(venv) >pip install flask-mail
flask-mail consente di connetterci ad un SMTP server in modo da passargli
le mail e far sì che vengano spedite.
Con la configurazione di default, Flask-Mail si connette tramite la porta
25 a localhost e spedisce mail senza bisogno di autenticazione.
Le chiavi che permettono di configurare Flask-Mail sono:
MAIL_SERVER : default “localhost”
MAIL_PORT : default 25
MAIL_USE_TLS : default False
MAIL_USE_SSL : default False
MAIL_DEBUG : default app.debug
MAIL_USERNAME : default None
MAIL_PASSWORD : default None
MAIL_DEFAULT_SENDER : default None
MAIL_MAX_EMAILS : default None
MAIL_SUPPRESS_SEND : default app.testing
MAIL_ASCII_ATTACHMENTS : default False
Nel caso specifico della nostra applicazione, dovremo inizializzare Flask-Mail
in app.__init__.py, creando una istanza di Mail, che gestirà le emails:
from flask.ext.mail import Mail ... mail = Mail() def create_app(config_name): ... mail.init_app(app) ...
I valori di configurazione sono già stati settati nel file config.py e
prevedono di spedire mail tramite account di posta gmail:
... class DevelopmentConfig(Config): DEBUG = True MAIL_SERVER = 'smtp.googlemail.com' MAIL_PORT = 587 MAIL_USE_TLS = True MAIL_USERNAME = os.environ.get('MAIL_USERNAME') MAIL_PASSWORD = os.environ.get('MAIL_PASSWORD') ...
i valori “MAIL_USERNAME” e “MAIL_PASSWORD” vengono settati per motivi di privacy
nel seguente modo per linux:
(venv) $ export MAIL_USERNAME=<Gmail username> (venv) $ export MAIL_PASSWORD=<Gmail password>
e nel seguente, per windows:
(venv) $ set MAIL_USERNAME=<Gmail username> (venv) $ set MAIL_PASSWORD=<Gmail password>
In questo modo, le nostre credenziali non appariranno nel codice, ma verranno prelevate dal dizionario
os.environ direttamente:
MAIL_USERNAME = os.environ.get('MAIL_USERNAME') MAIL_PASSWORD = os.environ.get('MAIL_PASSWORD')
(venv) >set [email protected] (venv) >set MAIL_PASSWORD=pippo (venv) >python manage.py shell >>> import os >>> os.environ.get("MAIL_USERNAME") '[email protected]' >>> os.environ.get("MAIL_PASSWORD") 'pippo'
ovviamente username e pw vanno sostituiti con qualcosa di esistente…
vediamo come mandare una mail dalla shell:
>>> import os >>> from flask import Flask >>> from flask_mail import Message >>> from flask_mail import Mail >>> app = Flask("test") >>> mail = Mail(app) >>> sender = os.environ.get("MAIL_USERNAME") >>> sender '[email protected]' >>> recipients = [sender] # mi auto spedisco una mail! >>> msg = Message("Test", sender=sender, recipients=recipients) >>> msg.recipients ['[email protected]'] >>> msg.add_recipient("[email protected]") # per aggiungere destinatari... >>> msg.recipients ['[email protected]', '[email protected]'] >>> msg.body = "text body" >>> msg.html = "<b>HTML</b> body" >>> with app.app_context(): ... mail.send(msg) ...
nota: il messaggio può avere un text body e/o uno html, pertanto li abbiamo aggiunti
entrambi.
Questo modo di mandare mail, non è comodissimo pertanto automatizziamo l’operazione di
spedizione mail, creando una funzione nell’apposito file app/email.py:
from threading import Thread from flask import current_app, render_template from flask.ext.mail import Message from . import mail def send_async_email(app, msg): with app.app_context(): mail.send(msg) def send_email(to, subject, template, **kwargs): app = current_app._get_current_object() msg = Message(app.config['FANTAMANAGER_MAIL_SUBJECT_PREFIX'] + ' ' + subject, sender=app.config['FANTAMANAGER_MAIL_SENDER'], recipients=[to]) msg.body = render_template(template + '.txt', **kwargs) msg.html = render_template(template + '.html', **kwargs) thr = Thread(target=send_async_email, args=[app, msg]) thr.start() return thr
La funzione mail.send() blocca l’applicazione durante l’operazione di spedizione.
Per questo l’operazione stessa viene delegata ad un thread che lavora in background,
evitando che il browser e tutta l’applicazione rimangano in attesa.
La template che si occupa della mail risiede in app/auth/templates/auth/email/confirm.txt
Dear {{ user.username }}, Welcome to Fantamanager! To confirm your account please click on the following link: {{ url_for('auth.confirm', token=token, _external=True) }} Sincerely, The Fantamanager Admin Note: replies to this email address are not monitored.
mentre il file html sarà:
<p>Dear {{ user.username }},</p> <p>Welcome to <b>Fantamanager</b>!</p> <p>To confirm your account please <a href= "{{ url_for('auth.confirm', token=token, _external=True) }}">click here</a>.</p> <p>Alternatively, you can paste the following link in your browser's address bar:</p> <p>{{ url_for('auth.confirm', token=token, _external=True) }}</p> <p>Sincerely,</p> <p>The Fantamanager Team</p> <p><small>Note: replies to this email address are not monitored.</small></p>
articoli successivi:
Flask (parte 8): registrare un nuovo user
articoli precedenti:
Flask (parte 1): virtualenv
Flask (parte 2): struttura progetto complesso
Flask (parte 3): database
Flask (parte 4): views e templates
Flask (parte 5): password security
Flask (parte 6): authentication
link utili:
“Flask Web Development” di Miguel Grinberg, fondamentale per calarsi nel mondo di Flask.
Altri link fondamentali:
Flask sito ufficiale
il blog dell’autore (Flask mega tutorial)
Commenti recenti