Contact Us button/smtplib forward details - html

I am using pythonanywhere to make a website. I have set up a contact us page, and I am attempting to take whatever a user submits as feedback and then forward the information to myself with smtplib. I asked about this on their forums, but they for some reason just deleted my post.
Here is my HTML code:
<title>Contact us!</title>
<link rel="stylesheet" href="{{ url_for('static', filename='css/contact.css') }}">
<div class="container">
<form action="contact">
<label for="report">Reason</label>
<select id="report" name="report">
<option value="Bug">Bug</option>
<option value="Suggestion">Suggestion</option>
<option value="Other">Other</option>
</select>
<label for="Subject">Subject</label>
<textarea id="Subject" name="Subject" placeholder="Write something.." style="height:200px"></textarea>
<input type="submit" value="Submit">
</form>
</div>
And here is the python code:
#app.route("/contact", methods=["GET", "POST"])
def feedback():
if request.method == 'GET':
return render_template("contact.html")
else:
result = "Thanks for the feedback!"
report = request.form['report']
Subject = request.form['Subject']
from email.mime.text import MIMEText
import smtplib
gmail_user = 'email#gmail.com'
gmail_password = 'password'
message = MIMEText(report)
message["Subject"] = Subject
message["From"] = gmail_user
message["To"] = gmail_user
server = smtplib.SMTP_SSL('smtp.gmail.com', 465)
server.ehlo()
server.login(gmail_user, gmail_password)
server.sendmail(gmail_user, gmail_user, message.as_string())
server.close()
return render_template('settlement_return.html',result = result)
EDIT: If I manually set report and subject to some misc text string it sends fine. But trying to get the information that someone submits is not giving any results.

As discussed in the comments above -- it looks like the problem was that you were missing the method="POST" in your form tag. That meant that the form was being submitted with the GET method, so the code in the first branch of the if statement in your view was being executed, which meant that no email was being sent.

Related

Online waiting: django submit form and display result in same page

I have an emergent task to make a web page which allow user to input some data and the backend do some calculation and the result needs to be displayed in the same page just below the input field (like air ticket online price check).
I am new to django and html. below is my first test web page of a simple online calculator to try to figure out how to make such web service.
I found a problem that when clicking the "submit" button, it tends to jump to a new web page or a new web tab. this is not what I want. Once the user input the data and click "submit" button, I want the "result" field on the page directly show the result (i.e. partially update only this field) without refresh/jump to the new page. Also I want the user input data kept in the same page after clicking "submit".
I saw there might be several different ways to do this work, iframe/AJAX. However, I have been searching/trying for answers and solutions for several days and none of the answers really work for this very basic simple question!!
html:
<form method="POST">
{% csrf_token %}
<div>
<label>num_1:</label>
<input type="text" name="num_1" value="1" placeholder="Enter value" />
</div>
<div>
<label>num_2:</label>
<input type="text" name="num_2" value="2" placeholder="Enter value" />
</div>
<br />
<div>{{ result }}</div>
<button type="submit">Submit</button>
</form>
view.py
def post_list(request):
result = 0
if request.method == "POST":
num1 = request.POST.get('num_1')
num2 = request.POST.get('num_2')
result = int(num1) + int(num2)
print(request.POST)
print(result)
context = {
'result': result
}
return render(request, 'blog/post_list.html', context)
I would suggest taking a look at htmx.org which makes this really simple without having to write any actual JS.
For your example:
(1) You add the htmx JS (which is only about 10k) to your HTML, and use hx-post and hx-target to trigger the ajax calls on your form. With these the form will fire an AJAX request, and the hx-target tells htmx to take the response (which you want to be only the result of your calculation) and put it in the div without refreshing the whole page.
See docs for more details on this.
Note also I gave an id to the div containing the result.
You will need to replace hx-post="{% url 'blog:post_list' %}" with the correct name to your view (which we don't know as you didn't post your urls.py).
<html>
<body>
<form method="POST" hx-post="{% url 'blog:post_list' %}" hx-target="#result">
{% csrf_token %}
<div>
<label>num_1:</label>
<input type="text" name="num_1" value="1" placeholder="Enter value" />
</div>
<div>
<label>num_2:</label>
<input type="text" name="num_2" value="2" placeholder="Enter value" />
</div>
<br />
<div id="result">{{ result }}</div>
<button type="submit">Submit</button>
</form>
<script src="https://unpkg.com/htmx.org#1.6.1"></script>
</body>
</html>
(2) In your view then you determine if the request is an AJAX request from htmx by checking the headers, in which case you want to only return the result. There are easier or elegant ways to do this (eg. check django-htmx, but just to keep it simple:
from django.http.response import HttpResponse
from django.shortcuts import render
# Create your views here.
def post_list(request):
result = 0
if request.method == "POST":
num1 = request.POST.get('num_1')
num2 = request.POST.get('num_2')
result = int(num1) + int(num2)
if request.headers.get('Hx-Request') == 'true':
# return only the result to be replaced
return HttpResponse(str(result))
else:
return render(request, 'blog/post_list.html', {'result': result})

CSRF verification failed. Request aborted [New] 2021

I am completely tired with the csrf issue. I have created a sign in form and register form.
I am able to login and logout, even register a user.
The main problem I am facing is the refresh-after-signin.
After signing in, if I refresh the page it simply gives a csrf verification failed error.
I have literally searched for it since past two days with no solution, all the answers are almost 4-5 years older, which are not helping.
This is the views.py signin function.
def signin(request):
if request.method=="POST":
username = request.POST.get('username')
password = request.POST.get('password')
user = authenticate(username=username,password=password)
if user is not None:
login(request,user)
messages.success(request,"Logged in Successfully!")
return render(request,'authtest/index.html')
else:
messages.error(request,"Bad Credentials")
return redirect('index')
return render(request,'authtest/signin.html')
This is the HTML form that is returning POST request
<form action="{% url 'signin' %}" method="POST">
<!-- I have no idea what this thing does -->
{% csrf_token %}
<!-- I have no idea what this thing does end -->
<input type="hidden" id="csrf_token" value='{"csrfmiddlewaretoken": "{{ csrf_token }}"}'>
<label for="username">UserName</label>
<input type="text" name="username" id="username" required>
<label for="password">Password</label>
<input type="password" name="password" id="password" required>
<button type="submit">SignIn</button>
</form>
Due to some security issues to keep each user's session safe, it is not possible to authenticate and render the url in the same view functions.
Therefore, you must perform the rendering operation in another URL after redirecting
something like this
def signin(request):
if request.method=="POST":
........
if user is not None:
..........
return redirect ('dashboard')\
and that dashboard func is like this
def dashboard(request):
.......
return redirect ('dashboard')

How to construct url suitable for django from html form action

I have django site which I can query with various combinations of parameters. I am trying to write a html form for selecting the various combinations like so :
<form action="http://mydjangosite.com/summaryReports/" target="_blank">
<input type="radio" name="reportType" value="messageSummary" checked> messageSummary<br>
<input type="radio" name="reportType" value="countSummary"> countSummary<br>
<select name="period">
<option value="today">Today</option>
<option value="yesterday">Yesterday</option>
<option value="thisWeek">This Week</option>
<option value="lastWeek">Last Week</option>
<option value="thisMonth">This Month</option>
<option value="lastMonth">Last Month</option>
</select>
<br>
<input type="radio" name="reportFormat" value="html" checked> html<br>
<input type="radio" name="reportFormat" value="pdf"> pdf<br>
<input type="radio" name="reportFormat" value="csv"> csv<br>
<input type="radio" name="reportFormat" value="email"> email<br>
<input type="radio" name="reportFormat" value="debug"> debug<br>
<input type="submit" value="Submit">
</form>
When I press button the url generated is :
mydjangosite.com/summaryReports/?reportType=messageSummary&period=today&reportFormat=html
whereas what I require is :
mydjangosite.com/summaryReports/messageSummary/today/html
How to do it?
Thanks in advance
For this to work, you'd need a view that would process the options selected, and an url that would react to the pattern, so, your view, which should be the one associated to /summaryReports/ will do something like this:
from django.shortcuts import redirect
def rewrite_the_url(request):
return redirect('your_app:actual_reports', **request.GET.dict())
now, the url definition here is important, as your view up there will pass all the parameters to it, so you'd want:
url(r'/summaryReports/(?P<reportType>[^./]+)/(?P<period>[^./]+)/(?P<reportFormat>[^./]+)/', views.actual_reports, name='actual_reports')
Then, actual_reports should be declared as:
def actual_reports(request, reportType, period, reportFormat):
#return something
Remember that an URL represents an state of your application, it's not a decorative measure, an user can simply change the parameter of your URL and expect things to change, what we're doing here is rewriting an URL to change what we get as a query string to an URL, as Django or the UWSGI server of your choice don't have any concern over the rewriting, as you would expect with systems that user Apache + mod_rewrite, which is server tech, not an application framework.
from django.conf.urls import url, include
from sellerProfile import views
urlpatterns = [
url(r'^summaryReports'+'/(?P<reportType>[\w\-]+)'+'/(?P<period>[\w\-]+)'+'/(?P<reportFormat>[\w\-]+)/$', views.summaryReportHtml, name="summaryReports")
]
you have to create urlpattern in urls.py and in view.py file you have to get values like.
#csrf_exempt
#token_required
def summaryReports(request, reportType, period, reportFormat):
if request.method == 'GET':
print(reportType, period, reportFormat)
I did something like this:
def reportGenerator(request):
if request.method == 'GET':
QryDict = request.GET
else:
QryDict = request.POST
reportType = QryDict.get('reportType', 'rawRecords')
period = QryDict.get('period', 'today')
reportFormat = QryDict.get('reportFormat','html')
newURL = '/summaryReports/' + reportType + '/' + period + '/' + reportFormat + '/'
return redirect( newURL )
`

Passing variable through response object in Flask framework

I need to pass a variable along with response object while complete signup process and display the success message on the same page. I tried so many ways but I couldn't find any idea how to do that. Please look at this scenario and help me out.
#app.route('/signup', methods=['POST', 'GET'])
def signup():
message = ''
email = ''
password = ''
resp = app.make_response(render_template('signup.html'))
if request.method == 'POST':
import datetime
email = request.form['emailInput']
password = request.form['pswdInput']
if len(password) < 3:
message = Markup("<p style='color:red;'> Password Length Should Be More Than 3 Character </p> ")
return render_template('signup.html', message = message)
expire_date = datetime.datetime.now()
expire_date = expire_date + datetime.timedelta(hours=1)
resp.set_cookie('userEmail', email, expires=expire_date)
resp.set_cookie('userPassword', password, expires=expire_date)
message = Markup("<h1> Registration successfull! </h1>")
resp.headers.set('message', message)
return resp
return render_template('signup.html', message = message)
HTML :
<div class="container">
Home
<form id="signup" method="POST" action="{{url_for('signup')}}">
<div class="header">
<h3>Sign Up</h3>
<p>You want to fill out this form</p>
</div>
<div class="sep"></div>
<div class="">
<input type="email" name="emailInput" placeholder="e-mail" autofocus />
<input type="password" name="pswdInput" placeholder="Password" />
<div class="">
<input name="joinCheck" name="joinCheck" value="1" type="checkbox" /><label class="terms">I accept the terms of use</label>
</div>
<input type="submit" id="submitBtn" value="Submit">SIGN UP FOR INVITE NOW</a>
</div>
<div>
{{message}}
</div>
</form>
</div>
resp = app.make_response(render_template('signup.html'))
This is missing your message keyword. Change it to:
resp = app.make_response(render_template('signup.html', message=message))
You need to move this code down also, because to it, it sees the message variable directly above as the empty string and assigns that to its keyword. I would place it right above your resp.set_cookie() code.
Finally, move this:
message = Markup("<h1> Registration successfull! </h1>")
Above the app.make_response() code you just moved. Your message variable needs to be set before the response code is initialized.
Just a small tip: I would change message = " " to message = None. Otherwise, in the compiled HTML, it just looks like there's an empty div. This won't be too detrimental in this small case, but I'd definitely make it a rule of thumb in future, larger projects. Then, in your HTML:
{% if message %}
<div>
{{message}}
</div>
{% endif %}
Cheers.

Email sending in django code is not working

Email sending in django code is not working,
it display error "[Errno 10061] No connection could be made because the target machine actively refused it"
these are my VIEWS.PY
def send_email(request):
username = request.POST.get('username', '')
from_email = request.POST.get('from_email', '')
message = request.POST.get('message', '')
if username and message and from_email:
try:
send_mail(username, from_email, message, ['canonizadocharm#ymail.com'])
except BadHeaderError:
return HttpResponse('Invalid header found.')
return HttpResponseRedirect('/contact/thanks/')
else:
# In reality we'd use a form class
# to get proper validation errors.
return HttpResponse('Make sure all fields are entered and valid.')
these are my contact.html
<FORM METHOD="POST" ACTION="/send_email/" >
{% csrf_token %}
Name: <INPUT TYPE="text" NAME="username"><BR>
Email: <INPUT TYPE="text" NAME="from_email"><BR>
Message: <BR>
<TEXTAREA NAME="message" ROWS="10" WRAP="hard">
</TEXTAREA>
<INPUT NAME="redirect" TYPE="hidden">
<INPUT NAME="NEXT_URL" TYPE="hidden">
<BR>
<INPUT TYPE="submit" VALUE="Send">
<INPUT TYPE="reset" VALUE="Clear">
</FORM>
these are my URLS.PY
url(r'^send_email/', views.send_email),
url(r'^contact/', views.contact),
url(r'^thanks/', views.thanks),
and my SETTINGS.PY
EMAIL_HOST = 'localhost'
EMAIL_HOST_USER = ''
EMAIL_HOST_PASSWORD = ''
EMAIL_PORT = 25
EMAIL_USE_TLS = True
Your action value of form must direct to view's url, mailto:canonizadocharm#ymail.com is not a valid path on your server.
UPDATED:
For example, add a new rule to urls.py like,
url(r'^mail/', views.send_mail),
Then change action value to mail.
Have your action value point to a URL, which in turn points to one of your views. For instance, your urls.py can do this.
url(r'^email/', 'project.views.send_email')
This will route your contact form to your send_mail view.
Your form in the templates has no csrf that's why you get an error of "CSRF verification failed".
<FORM METHOD=POST ACTION="/send_email/" ENCTYPE="text/plain">{% csrf_token %}
...........
</FORM>
If you want to know what is csrf just go to this link:
https://docs.djangoproject.com/en/dev/ref/contrib/csrf/
Create email setting in your settings.py, like this for example:
settings.py
# Sending mail
EMAIL_USE_TLS = True
EMAIL_HOST='smtp.gmail.com'
EMAIL_PORT=587
EMAIL_HOST_USER='your gmail account'
EMAIL_HOST_PASSWORD='your gmail password'
views.py
from django.core.mail import send_mail
def send_email(request):
if request.method == 'POST':
username = request.POST.get('username')
message = request.POST.get('message')
from_email = request.POST.get('from_email')
send_mail(username, message, from_email, ['canonizadocharm#ymail.com',])
return HttpResponseRedirect('/contact/thanks/')
else:
return HttpResponse('Make sure all fields are entered and valid.')