Sending Email with Flask-Mail - socket.gaierror

2.3k views Asked by At

I am building a simple contact page using Flask and Flask-Mail. I built the app following this tutorial - Add a contact page - and now when I try to send the message I receive the eror gaierror: [Errno -2] Name or service not known. I have been googling the error for a while and can't find any similar examples on line. I can't even figure out what name or service it can't find.

The traceback page will let me expand a row and execute some Python code. It provides a dump() function that will show me all the variables and can be called on objects to see their info if that will help.

routes.py :

from forms import ContactForm
from flask.ext.mail import Message, Mail


mail = Mail()
app = Flask(__name__)


app.secret_key = 'development key'

app.config['MAIL_SERVER'] = 'smtp.google.com'
app.config['MAIL_PORT'] = 465
app.config['MAIL_USE_SSL'] = True
app.config['MAIL_USERNAME'] = 'email'
app.config['MAIL_PASSWORD'] = 'email'

mail.init_app(app)
@app.route('/contact', methods=['GET', 'POST'])
def contact():
    form = ContactForm()

    if request.method == 'POST':
        if not form.validate():

the form:

from flask.ext.wtf import Form, validators
from wtforms.fields import TextField, TextAreaField, SubmitField
import wtforms


class ContactForm(Form):
    name = TextField("Name", [wtforms.validators.Required('Please enter your name')])
    email = TextField("Email", [wtforms.validators.Required('Please enter your email'), wtforms.validators.Email()])
    subject = TextField("Subject", [wtforms.validators.Required('Please enter a subject')])
    message = TextAreaField("Message", [wtforms.validators.Required('Please enter a message')])
    submit = SubmitField("Send")
            flash('All fields are required.')
            return render_template('contact.html', form=form)
        else:
            msg = Message(form.subject.data, sender='[email protected]', recipients=['[email protected]'])
            msg.body = """From: %s <%s> %s""" % (form.name.data, form.email.data, form.message.data)
            mail.send(msg)
            return render_template('contact.html', success=True)
    elif request.method == 'GET':
        return render_template('contact.html', form=form)

the traceback:

File "/home/ian/PycharmProjects/flaskapp/lib/python2.7/site-packages/flask/app.py", line 1836, in __call__

return self.wsgi_app(environ, start_response)

File "/home/ian/PycharmProjects/flaskapp/lib/python2.7/site-packages/flask/app.py", line 1820, in wsgi_app

response = self.make_response(self.handle_exception(e))

File "/home/ian/PycharmProjects/flaskapp/lib/python2.7/site-packages/flask/app.py", line 1403, in handle_exception

reraise(exc_type, exc_value, tb)

File "/home/ian/PycharmProjects/flaskapp/lib/python2.7/site-packages/flask/app.py", line 1817, in wsgi_app

response = self.full_dispatch_request()

File "/home/ian/PycharmProjects/flaskapp/lib/python2.7/site-packages/flask/app.py", line 1477, in full_dispatch_request

rv = self.handle_user_exception(e)

File "/home/ian/PycharmProjects/flaskapp/lib/python2.7/site-packages/flask/app.py", line 1381, in handle_user_exception

reraise(exc_type, exc_value, tb)

File "/home/ian/PycharmProjects/flaskapp/lib/python2.7/site-packages/flask/app.py", line 1475, in full_dispatch_request

rv = self.dispatch_request()

File "/home/ian/PycharmProjects/flaskapp/lib/python2.7/site-packages/flask/app.py", line 1461, in dispatch_request

return self.view_functions[rule.endpoint](**req.view_args)

File "/home/ian/PycharmProjects/flaskapp/app/routes.py", line 39, in contact

mail.send(msg)

File "/home/ian/PycharmProjects/flaskapp/lib/python2.7/site-packages/flask_mail.py", line 415, in send

with self.connect() as connection:

File "/home/ian/PycharmProjects/flaskapp/lib/python2.7/site-packages/flask_mail.py", line 123, in __enter__

self.host = self.configure_host()

File "/home/ian/PycharmProjects/flaskapp/lib/python2.7/site-packages/flask_mail.py", line 135, in configure_host

host = smtplib.SMTP_SSL(self.mail.server, self.mail.port)

File "/usr/lib/python2.7/smtplib.py", line 776, in __init__

SMTP.__init__(self, host, port, local_hostname, timeout)

File "/usr/lib/python2.7/smtplib.py", line 249, in __init__

(code, msg) = self.connect(host, port)

File "/usr/lib/python2.7/smtplib.py", line 309, in connect

self.sock = self._get_socket(host, port, self.timeout)

File "/usr/lib/python2.7/smtplib.py", line 781, in _get_socket

new_socket = socket.create_connection((host, port), timeout)

File "/usr/lib/python2.7/socket.py", line 553, in create_connection

for res in getaddrinfo(host, port, 0, SOCK_STREAM):

gaierror: [Errno -2] Name or service not known
2

There are 2 answers

1
makkasi On

OK. I know that this question is 4 years old, but here is my solution. There is a BUG. You just need to have the configuration parameters added to the flask app after app.config.from_object.

from config import config
app.config.from_object(config[config_name])
config[config_name].init_app(app)
app.config.update( DEBUG=True, MAIL_SERVER='smtp.gmail.com',
                   MAIL_PORT=587, MAIL_USE_SSL=False, MAIL_USE_TLS=True, MAIL_USERNAME = '[email protected]')

inside config.py I have these two parameters:

MAIL_PASSWORD = 'password'
MAIL_DEFAULT_SENDER = '[email protected]'
# IMPORTANT - the rest of the mail parameters are set inside the __init__.py because they don't work here -> BUG

If someone has time to find out, which parameters don't work with app.config.from_object( .. ), he can add an other answer.

And don't forget to switch the google security to accept less secure apps. Otherwise it won't work. Regards

0
MCrolio On

My first attempt on here but just picking out what i can see. Im assuming that you have copied your entire code from each file. Correct me if im wrong.

Ensure routes.py imports the necessary classes from flask ("request" is imperative for submitting the form as it determines if the request method is a GET or POST:

from flask import Flask, render_template, request, flash

And your Forms.py... note: you don't actually need to import the entire wtforms module...

from flask.ext.wtf import Form
from wtforms import TextField, SubmitField, TextAreaField, validators, ValidationError

In your routes.py code there is an unnecessary boolean operator if "not" statement:

if request.method == 'POST':
    if not form.validate():

It should be contain a comparative operator and boolean as it is in Lalith's Post:

if form.validate() == False:
    flash("All fields...

Your forms.py shouldnt contain any of this:

flash('All fields are required.')
        return render_template('contact.html', form=form)
    else:
        msg = Message(form.subject.data, sender='[email protected]', recipients=['[email protected]'])
        msg.body = """From: %s <%s> %s""" % (form.name.data, form.email.data, form.message.data)
        mail.send(msg)
        return render_template('contact.html', success=True)
elif request.method == 'GET':
    return render_template('contact.html', form=form)

It should all be contained within the contact function in routes.py like this:

def contact():
form = ContactForm()

if request.method == 'POST':
    if not form.validate():
        flash('All fields are required.')
        return render_template('contact.html', form=form)
    else:
        msg = Message(form.subject.data, sender='[email protected]', recipients=['[email protected]'])
        msg.body = """From: %s <%s> %s""" % (form.name.data, form.email.data, form.message.data)
        mail.send(msg)
        return render_template('contact.html', success=True)
elif request.method == 'GET':
    return render_template('contact.html', form=form)

Lastly I know this may seem really obvious but make sure you replace "email" with your real email and password here:

app.config['MAIL_USERNAME'] = 'email' 
app.config['MAIL_PASSWORD'] = 'email'

Good luck. Hope this helps.