Flask Error, in Python script does not work - python

unfortunately my script no longer works in Flask. I don't know how to fix this. I would be very grateful if you could help me. Here are my codes:
#app.route("/register", methods=["GET", "POST"])
def register():
if request.method == "POST":
username = request.form["uname"]
password = request.form["passwd"]
with open("user.txt", "r") as file:
file.write(username + "\n" + password)
return render_template("register.html")
<form action="/register" method="POST">
<div class="container">
<label for="usm"><b>Username</b></label>
<input type="text" placeholder="Enter Username" name="usm" required>
<label for="pwd"><b>Password</b></label>
<input type="password" placeholder="Enter Password" name="pwd" required>
<button type="submit" name="login">Login</button>
</div>
</form>
This is my error:
werkzeug.exceptions.BadRequestKeyError
werkzeug.exceptions.BadRequestKeyError: 400 Bad Request: The browser (or proxy) sent a request that this server could not understand.
KeyError: 'uname'

Your form is sending a field named usm:
<input ... name="usm">
You're expecting a field named uname:
username = request.form["uname"]
The same stands for pwd/passwd.
Also, you can't .write() to a file opened with the "r" mode.

Related

How to put csrf_token inside django form view

I am new in django and have faced a strange problem. If I create django template and insert {% csrf_token %} inside, it works well, but if I put #csrf_protect decorator to view, it gives me Forbidden 403 (CSRF verification failed. Request aborted). As I understand from django documentation, I can`t use both CsrfViewMiddleware and #csrf_protect.
So here is the question:
Is it possible to do csrf verification inside a view or should I always write templates in such situations?
#csrf_protect
def create_group(request):
if request.method == "POST":
Group.objects.create(**{key: request.POST[key] for key in request.POST})
return HttpResponseRedirect(reverse("groups:groups"))
elif request.method == "GET":
pass
return HttpResponse(create_group_form)
create_group_form = """
<form method="POST">
<label for="course">Course:</label><br>
<input type="text" id="course" name="course"><br><br>
<label for="length_in_months">Length in months:</label><br>
<input type="number" id="length_in_months" name="length_in_months" min=1 max=12 required><br><br>
<label for="price">Price:</label><br>
<input type="number" id="price" name="price" min=1000 max=50000 required><br><br>
<label for="number_of_students">Number of students:</label><br>
<input type="number" id="number_of_students" name="number_of_students" min=3 max=30 required><br><br>
<label for="lesson_duration">Lesson duration:</label><br>
<input type="number" id="lesson_duration" name="lesson_duration" min=1 max=5 required><br><br>
<label for="website">Website:</label><br>
<input type="url" id="website" name="website"><br><br>
<input type="submit" value="Submit">
</form> """
It's better to use CsrfViewMiddleware as an overall protection. If you forget to add the decorator to your views, it'll create security issues. You must use it on the views that assign CSRF tokens to the output and the ones that accept data from the POST form. So, as the best practice its better to use CSRF token in template unless we have a specific requirement.

To and From return the same email id in django send_mail()

Views.py
def contact(request):
if request.method == 'POST':
message_name = request.POST['message-name']
message_email = request.POST['message-email']
message = request.POST['message']
# send an email
send_mail(
'Message from ' + message_name, # subject
message, # message
message_email, # from email
['myEmailId#gmail.com'], # to email
)
settings.py
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_PORT = 587
EMAIL_HOST_USER = 'myEmailId#gmail.com'
EMAIL_HOST_PASSWORD = '<myaccount app password>'
EMAIL_USE_TLS = True
contact.html
<form action="{% url 'contact' %}" method="POST" class="bg-light p-5 contact-form">
{% csrf_token %}
<div class="form-group">
<input type="text" name="message-name" class="form-control" placeholder="Your Name">
</div>
<div class="form-group">
<input type="email" name="message-email" class="form-control" placeholder="Your Email">
</div>
<div class="form-group">
<textarea name="message" id="" cols="30" rows="7" class="form-control" placeholder="Message">
</textarea>
</div>
<div class="form-group">
<input type="submit" value="Send Message" class="btn btn-primary py-3 px-5">
</div>
</form>
I have created this code for the contact-me page. Now when user Submits the Contact Form which has the fields message-name, message-email and message, I receive the email where FROM and TO are both my email-id.
It is not retrieving the users email. But rest of the fields are working fine.
Even Tested with DebuggingServer and that works as expected. Seems like I am missing something in the setting.py because that is the one file I have changed.
I don't understand where I am going wrong. Any help appreciated.
You should not be using user's email address in from field. It should be the address that is in your control. By using user's email in from field, it implies that the email was sent by the user which is not the case, and should never happen.
Moreover, gmail would not allow you to send email from anyone else's email address from your account.
I would suggest you to use your own email address and have user's email address in the message.

How to make a Django contact me form with send_mail?

I tried to use 6 different tutorials to get this done, but all of them gave different variations so I'm really frustrated at the pace I'm making...
I think I'm nearing the last few steps but I need some help. Here is the code I have in my Django project:
# -- settings.py--
EMAIL_BACKEND = 'django.core.mail.backends.stmp.EmailBackend'
EMAIL_HOST = 'http://smtp.gmail.com/'
EMAIL_HOST_USER = 'a spare Gmail I have'
EMAIL_HOST_PASSWORD = 'the password'
EMAIL_USE_TLS = False
EMAIL_PORT = 465
..
# -- views.py --
# (assumed relevant imports are imported)
class ContactView(FormView):
template_name = 'CONTACT.html'
form_class = ContactForm
success_url = 'Success!'
context_vars = {
'example_name_f': 'Adam',
'example_name_l': 'Smith',
'example_email': 'smith.a#gmail.com',
'example_subject': 'Sales proposal',
'example_text': 'Hi Mark, I have a sales proposal for you!',
}
def get(self, request):
return render(request, 'CONTACT.html', ContactView.context_vars)
def contact(self, request):
if request.method == 'POST':
form = self.form_class(data=request.POST)
if form.is_valid():
time = request.POST.get('time', '')
first_name = request.POST.get('first_name', '')
last_name = request.POST.get('last_name', '')
email_address = request.POST.get('email_address', '')
subject = request.POST.get('subject', '')
text = request.POST.get('text', '')
send_mail(subject, text, email_address,
['999#outlook.com'], fail_silently=False)
return redirect('CONTACT-done.html') # CONTACT-done is a temporary success screen
return render(request, 'CONTACT.html', ContactView.context_vars)
The relevant portion of HTML:
<div class="container-fluid" style="width: 100%; height: 100%">
<form action="" method="post">
<label for="first-name">First Name</label>
<input id="first-name" name="first-name" type="text" placeholder="{{ example_name_f }}">
<!-- Note: placeholder vs value attributes similar -->
<!-- id is for HTML, name is for views.py -->
<label for="last-name">Last Name</label>
<input id="last-name" name="last-name" type="text" placeholder="{{ example_name_l }}">
<!-- Its unnecessary to use context vars for placehoder text -->
<label for="email">Email Address</label>
<input id="email" name="email" type="email" placeholder="{{ example_email }}" required>
<label for="subject">Subject</label>
<input id="subject" name="subject" type="text" placeholder="{{ example_subject }}">
<label for="text">Message:</label>
<input id="text" name="text" type="text" placeholder="{{ example_text }}" required>
<input type="submit" value="Send">
</form>
</div>
Some tutorials recommended a {{ form.as_p }} approach in HTML but some just did the basic HTML style as I did above. Not sure what to do from here.
Clicking send on my website gives a 403 CSRF verification failed. Request aborted.
Please explain in as simple a way as possible, I'm not brand new to programming but I'm not a CS person either. Thanks.
you need the CSRF token:
<form ...>
{% csrf_token %}
...
</form>
As in this official documentation example:

BadHeaderError using Flask with FlaskMail and Postfix on Ubuntu server

I'm running a fullstack website with Flask and SQLite. On the page I have a contact-section to let visitors send me an email. The contact-section consists of an HTML form which sends the information to the webserver via HTTP POST. The server itself uses the FlaskMail plugin to create the message and send it to the mail-server (in this case a postfix server I set up on the same server).
However, I'm getting a BadHeaderError every time I click submit.
I already looked for existing fixes and found an existing Stackoverflow question here. However, the solution there seems to be unrelated to my issue.
Relevant code from webserver.py (Flask python file):
app = Flask(__name__)
app.debug = True
app.config['MAIL_USERNAME'] = 'admin'
app.config['MAIL_PASSWORD'] = 'password'
app.config['MAIL_USE_TLS'] = True
mail = Mail(app)
#app.route('/contact', methods=['GET', 'POST'])
def contact():
lang = get_lang(request.headers)
if request.method == 'GET':
if lang == 'de':
return render_template('contact.html', lang=lang, title=title_de, descriptio$
else:
return render_template('contact.html', lang=lang, title=title_en, descriptio$
elif request.method == 'POST':
name = request.form['name']
email = request.form['email']
company = request.form['company']
message = request.form['message']
if not name:
flash('Please enter your name')
return redirect(url_for('contact'))
if not email:
flash('Please enter your e-mail address')
return redirect(url_for('contact'))
if not message:
flash('Please enter a message')
return redirect(url_for('contact'))
message += '\n\n'
message += ('Name: ' + name)
message += '\n\n'
message += ('Company: ' + company)
msg = Message(message, sender=email, recipients=['pawelczyk.johannes#gmail.com'])
mail.send(msg)
flash('You will receive an automatic confirmation mail')
return redirect(url_for('index'))
else:
flash('Bad request')
return redirect(url_for('index'))
Apache error log: pastebin
HTML:
<div id="contact-form-container">
<form id="contact-form" action="{{ url_for('contact') }}" method="post">
<div>
<div class="contact-form-row">
<h3 class="to-left">Name:</h3>
<input class="to-right" type="text" name="name" placeholder="Name">
</div>
<div class="contact-form-row">
<h3 class="to-left">E-Mail:</h3>
<input class="to-right" type="text" name="email" placeholder="E-Mail">
</div>
<div class="contact-form-row">
<h3 class="to-left">Firma (optional):</h3>
<input class="to-right" type="text" name="company" placeholder="Firma">
</div>
<h3 class="gap-over">Ihre Nachricht:</h3>
<textarea cols="40" rows="10" name="message"></textarea></br>
</div>
<div class="middle">
<input class="button" type="submit" value="Senden">
</div>
</form>
</div>

Post values from an HTML form and access them in a Flask view

I have an HTML form that gets posted to a Flask route. However, request.form is empty. If I try to access one of the values by id, I get a 400 error. How do I post values from an HTML form and access them in Flask?
<form method="POST">
<input id="my_input" type="text" value="{{ email }}">
<input id="my_submit" type="submit" value="Submit">
</form>
#app.route('/page', methods=['POST', 'GET'])
def get_page():
if request.method == 'POST':
print(request.form) # prints ImmutableMultiDict([])
print(request.form['my_input']) # raises 400 error
return render_template('page.html')
Your input doesn't have a name attribute. That is what the client will pass along to the server. Flask will raise a 400 error if you access a form key that wasn't submitted.
<input name="my_input" id="my_input" type="text" value="{{ email }}">
You need to Specify the form Action method in the Html page, and then mention the HTML Text box name inside the Tag.
<form method="POST" action="/PythonFunctionName">
<input id="my_input" type="text" name="HTMLControlName" value="{{ email }}">
<input id="my_submit" type="submit" value="Submit">
</form>
And inside the .py module access the element using the name specified in the HTML tag.
#app.route('/PythonFunctionName', methods=['POST', 'GET'])
def getPage():
if request.method == 'POST':
strTextBoxVal= request.form['HTMLControlName'])
Print(strTextBoxVal)
return render_template('page.html')

Categories