Flask-Mail not sending email - flask

I want to receive an email when users fill out a contact form and submit it but instead of sending the email it just displays the email as part of the URL. I have tried several methods but it's not working at all and even in the code, it does not show any errors.
This is my code for the function
from app import app, mail
from flask import render_template, request
from flask_mail import Message
def send_mail(contactform):
msg = Message('Porfolio Contact Applicant',
recipients=['rynato#kellychibale-researchgroup-uct.com'],
sender='Portfolio-Maxwell#portfoliomaxwell.co.ke')
msg.body = '''
Hello there,
You have just received contact details form from your portfolio
Name: {}
Email: {}
Message: {}
'''.format(contactform['name'], contactform['email'], contactform['message'] )
mail.send(msg)
#app.route('/')
def index():
if request.method == 'POST':
contactform = request.form
contactform = {}
contactform['name'] = request.form['name']
contactform['email ']= request.form['email'].repalces(' ','').lower()
contactform['message ']= request.form['message']
send_mail(contactform)
return render_template('index.html', **locals())
else:
return render_template('index.html', **locals())
#app.route('/privacy')
def privacy():
return render_template('privacy.html')
so does anyone have a clue as what do or go about it?

The answer(s) might depend on the type of email you want to sent, and how you have to connect to your preferred service provider.
Here's one example.
In Forms.py
class SendEmailForm(FlaskForm):
confirmed = BooleanField('confirmed')
to = StringField("to", validators=[DataRequired("Please enter the email address you want to send to")])
subject = StringField("subject", [validators.DataRequired(), validators.Length(min=1, max=80)])
message_text = TextAreaField('message_text', [validators.DataRequired()] , render_kw={"rows": 10, "cols": 60} )
submit = SubmitField("submit")
In Models.py
import smtplib, ssl
from email.message import EmailMessage
def SendEmailMessage(to, subject, messagetext, messagehtml, cc):
context = ssl.create_default_context()
msg = EmailMessage()
sender = app.config['MAIL_ADMIN_NAME']
msg['From'] = sender
msg['To'] = to
msg['Subject'] = subject
msg.set_content(messagetext)
# Try to log in to server and send email
try:
server = smtplib.SMTP(app.config['MAIL_SERVER'],app.config['MAIL_PORT'])
server.ehlo() # Can be omitted
server.starttls(context=context) # Secure the connection
server.ehlo() # Can be omitted
server.login(app.config['MAIL_ADMIN_NAME'], app.config['MAIL_ADMIN_PSSWRD'])
server.send_message(msg)
except Exception as e:
# Print any error messages to stdout
print(e)
finally:
server.quit()
In Views:
#app.route('/send_email', methods=['GET', 'POST'])
def send_email():
form = SendEmailForm()
sender = app.config['MAIL_ADMIN_NAME']
if form.validate_on_submit():
flash('email requested to {}, confirmed={}'.format(
form.to.data, form.confirmed.data))
to = form.to.data
subject = form.subject.data
message_text = form.message_text.data
confirmed = form.confirmed.data
if confirmed == True:
cc = ""
SendEmailMessage(to, subject, message_text, message_text, cc)
flash('Please check your email inbox.')
else:
print("Not validated")
return render_template("send_email.html",
title='Send an email',
sender=sender,
form=form,
footer_text=footer_text)
In send_email.html
<p>
Hello "{{ sender }}".
</p>
<div>
<form action="" method="post">
{{ form.hidden_tag() }}
<p>
Please tick the checkbox if you would to send your email.
</p>
<p>Confirmed :
<input type="checkbox" name="confirmed"/>
</p>
<p>
Send to: <br>
{{ form.to }}<br>
{% for error in form.to.errors %}
<span style="color: red;">[{{ error }}]</span>
{% endfor %}
</p>
<p>Subject of email: <br>
<input type="textbox" name="subject"/><br>
{% for error in form.subject.errors %}
<span style="color: red;">[{{ error }}]</span>
{% endfor %}
</p>
<p>Email message<br>
<textarea cols="70" id="message_text" name="message_text" required rows="10" size="2400"></textarea><br>
{% for error in form.message_text.errors %}
<span style="color: red;">[{{ error }}]</span>
{% endfor %}
</p>
<p>
<input type="submit" value="Continue">
</p>
</form>
</div>

Related

How to send email with attachment from form?

I've been trying different ways to send an attachment from a submitted form but I'm not able to get it right.
my model:
from django.db import models
class Document(models.Model):
description = models.CharField(max_length=255, blank=True)
document = models.FileField()
uploaded_at = models.DateTimeField(auto_now_add=True)
views.py
from django.shortcuts import render, redirect
from django.core.mail import EmailMessage
from decouple import config
from .forms import ContactForm
def contact(request):
contact_form = ContactForm()
if request.method == "POST":
contact_form = ContactForm(request.POST, request.FILES)
if contact_form.is_valid():
name = request.POST.get("name")
email = request.POST.get("email")
subject = request.POST.get("subject")
message = request.POST.get("message")
upload = request.POST.get("upload")
email_content= EmailMessage("Message from django-structure project",
f"The user with name {name}, with the email {email},"
f" write the following: \n Subject: {subject} \n File{upload} \n\n Message: {message}",
"", [config('EMAIL_TO')], reply_to=[email])
try:
email_content.send()
return redirect("/contact/?valid")
except:
return redirect("/contact/?invalid")
return render(request, "contact.html", {"form": contact_form})
contact.html
<div class="row">
<div class="col">
<div class="form-group">
{% if "valid" in request.GET %}
<p style="color: blue;">Information sent successfully </p>
{% endif %}
<form action="" method="POST" enctype="multipart/form-data" style="text-align: center;">
{% csrf_token %}
<table style="color: dark; margin:20px auto;">{{form.as_table}}</table>
<input type="submit" value="Send" style="width: 150px;">
</form>
</div>
When I submit the form, I receive the message but in the content of the File, just the following string: "FleNone". (I have attached a pdf)

wtforms will not return form.validate() as true [duplicate]

This question already has an answer here:
Form is never valid with WTForms
(1 answer)
Closed 3 years ago.
I'm trying to validate inputs for a contact form loosely following Lalith Polepeddi's tutorial. I have used this tutorial before with slight adjustments, but this time the inputs will not validate no matter what I try.
if form.validate() in my routes.py always returns false. I uploaded the (entire venv to github with only the offending code)https://github.com/1988mazdab2000/wtfwtf.git
forms.py file:
class ContactForm(Form):
name = TextField("Name", [validators.Required("Please enter your name.")])
email = TextField("Email", [validators.Required("Please enter your email address."), validators.Email("Please enter your email address.")])
subject = TextField("Subject", [validators.Required("Please enter a subject.")])
message = TextAreaField("Message", [validators.Required("Please enter a message.")])
submit = SubmitField("Send")
my routes.py file:
from flask import render_template, request, flash
from forms import ContactForm
from flask_mail import Message, Mail
mail = Mail()
#app.route('/')
def home():
return render_template('home.html')
#app.route('/about')
def about():
return render_template('about.html')
#app.route('/contact', methods=['GET', 'POST'])
def contact():
form = ContactForm()
if request.method == 'POST':
if form.validate() == False:
flash('All fields are required.')
return render_template('contact.html', form=form)
else:
msg = Message(form.subject.data, sender='contact#example.com', recipients=['your_email#example.com'])
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)
any help with this would be greatly appreciated. I have used identical code to do this in the last three months and I'm stuck.
I've tried using different validators and started with a fresh install of raspbian on two different Pis.
I'd like for the form validators to work properly.
As #VillageMonkey said, use validate_on_submit. More can be found in official documentation.
Here is an example of using form validation using Flask-WTF. In this example, the login form requires a valid email address and a password with at least 6 and at most 35 characters long.
app.py:
from flask import render_template, url_for, request, redirect, flash, Flask
from forms import LoginForm
app = Flask(__name__)
app.secret_key = 'secret key'
#app.route("/login", methods=['GET', 'POST'])
def login():
form = LoginForm()
if request.method == 'POST':
if form.validate_on_submit() == False:
flash('Form validation failed')
return render_template('login.html', form=form)
user_email = form.email.data
user_password = form.password.data
if user_email and user_password:
return "{} - {}".format(user_email, user_password)
return render_template('login.html', form=form)
if __name__ == '__main__':
app.run(debug=True)
forms.py:
from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, SubmitField, BooleanField
from wtforms.validators import DataRequired, Length, Email, EqualTo
class LoginForm(FlaskForm):
email = StringField('Email', validators=[DataRequired(), Email()])
password = PasswordField('Password', validators=[DataRequired(), Length(min=6, max=35)])
submit = SubmitField('Login')
login.html:
<!DOCTYPE html>
<html>
<head>
<title>Login</title>
</head>
<body>
{% with messages = get_flashed_messages() %}
{% if messages %}
<ul class=flashes>
{% for message in messages %}
<li>{{ message }}</li>
{% endfor %}
</ul>
{% endif %}
{% endwith %}
<form method="POST" action="">
{{ form.csrf_token }}
<div>
{{ form.email.label }} {{ form.email }}
{% if form.email.errors %}
<ul style="color: red;">
{% for error in form.email.errors %}
<li>{{ error }}</li>
{% endfor %}
</ul>
{% endif %}
</div>
<div>
{{ form.password.label }} {{ form.password }}
{% if form.password.errors %}
<ul style="color: red;">
{% for error in form.password.errors %}
<li>{{ error }}</li>
{% endfor %}
</ul>
{% endif %}
</div>
<div>
{{ form.submit }}
</div>
</form>
</body>
</html>
Directory structure:
.
├── app.py
├── forms.py
└── templates
└── login.html
requirements.txt:
Click==7.0
Flask==1.0.2
Flask-WTF==0.14.2
itsdangerous==1.1.0
Jinja2==2.10
MarkupSafe==1.1.1
Werkzeug==0.15.0
WTForms==2.2.1
Output:
Get request of login route:
Post request of login route (failed validation):
Post request of login route (after successful validation):
In the template use {{ form.hidden_tag() }} for csrf protection.
<form action="{{ url_for('contact') }}" method="post">
{{ form.hidden_tag() }}
</form>

Django forms validation is not showing up in the template

My problem is, when I validate forms for errors, some text with warning would show up, But id does not. I was searching for some good answers and I tried also everything.
I was trying to implement validation in my register subpage so....
First is my model.py for registration
from django.db import models
class User(models.Model):
name = models.CharField(max_length=30)
email = models.EmailField(max_length=30)
password = models.CharField(max_length=30)
def __str__(self):
return "Login: " + self.name + \
" | e-mail: " + self.email + \
" | password: " + self.password
Second is my inputForms.py with simple validation
from django import forms
from django.contrib.auth.models import User
from django.contrib import messages
from .models import User
class NewUser(forms.Form):
name = forms.CharField(required=True)
email = forms.EmailField(required=True)
password = forms.CharField(widget=forms.PasswordInput, required=True)
pic1 = forms.CharField(required=True)
pic2 = forms.CharField(required=True)
pic3 = forms.CharField(required=True)
pic4 = forms.CharField(required=True)
pic5 = forms.CharField(required=True)
class Meta:
model = User
fields = ('name', 'email', 'password')
def clean_email(self):
email_passed = self.cleaned_data.get('email')
email_req = "yourdomain.com"
if not email_req in email_passed:
raise forms.ValidationError("Not a valid email. Please try again")
return email_passed
Third is my view.py
from django.http import HttpResponseRedirect
from django.shortcuts import render
from definitions import SITE_ROOT
from .models import User
from . import inputForms
from threading import Thread
import base64
import re
import os
def index(request):
if request.method == 'GET':
return render(request, 'register.html', {'NewUser': inputForms.NewUser})
else:
return HttpResponseRedirect('/Kniznica')
def new_user(request):
if request.method == 'POST':
form = inputForms.NewUser(request.POST)
if form.is_valid():
user_name = form.cleaned_data['name']
user_email = form.cleaned_data['email']
user_password = form.cleaned_data['password']
thread = Thread(target=save_user, args=(form, user_name, user_email, user_password, ))
thread.start()
return HttpResponseRedirect('/Kniznica')
else:
return render(request, "register.html", {'NewUser': inputForms.NewUser})
def save_user(form, user_name, user_email, user_password):
base_to_png(form.cleaned_data['pic1'], user_name, "face1.png")
base_to_png(form.cleaned_data['pic2'], user_name, "face2.png")
base_to_png(form.cleaned_data['pic3'], user_name, "face3.png")
base_to_png(form.cleaned_data['pic4'], user_name, "face4.png")
base_to_png(form.cleaned_data['pic5'], user_name, "face5.png")
user_instance = User.objects.create(name=user_name, email=user_email, password=user_password)
user_instance.save()
def base_to_png(base64_string, name, image_name):
string_without_header = re.sub('^data:image/.+;base64,', '', base64_string)
img_data = base64.b64decode(string_without_header)
if not os.path.exists(SITE_ROOT + "/faceId/" + name):
os.makedirs(SITE_ROOT + "/faceId/" + name)
filename = SITE_ROOT + "/faceId/" + name + "/" + image_name
with open(filename, 'wb') as f:
f.write(img_data)
os.chdir(SITE_ROOT + "\static\scripts")
os.system("node face-detection.js " + name + " " + image_name)
And fourth is my template.html for registration
<div>
<form action="newUser" method="post" novalidate>
{% csrf_token %}
{{ form.non_field_errors }}
{{ form.username.errors }}
{% if form.errors %}
{% for field in form %}
{% for error in field.errors %}
<p> {{ errors }} </p>
{% endfor %}
{% endfor %}
{% endif %}
<div style="display: inline-block">
Meno:{{ NewUser.name }}
</div>
<div style="display: inline-block">
Email:{{ NewUser.email }}
</div>
<div style="display: inline-block">
Heslo:{{ NewUser.password }}
</div>
<div hidden>
{{ NewUser.pic1 }}
{{ NewUser.pic2 }}
{{ NewUser.pic3 }}
{{ NewUser.pic4 }}
{{ NewUser.pic5 }}
</div>
<div>
<video id="video" width="300" height="300" autoplay></video>
</div>
<div>
<p id="counter"></p>
<button type="button" id="snap">Snap Photo</button>
<button type="submit" id="save" name="register">Registrácia</button>
</div>
<canvas hidden id="canvas" width="640" height="480"></canvas>
</form>
</div>
You have an unusual view structure here - normally you would use the same view for displaying the initial form as you would for processing the submission and displaying errors.
But nevertheless, you do have a couple of obvious issues. Firstly, in your new_user view, when the form is not valid you don't send that invalid form back, but instead send the form class itself. You should always send an instance of the form anyway, and in this case you should send back the same instance you have already validated, because that's the thing with the errors:
return render(request, "register.html", {'NewUser': form})
Secondly, in your template, you are inconsistent about what you call the form. When you render the fields, you access it via NewUser. But in trying to display the errors, for some reason you call it form. As you have used the name NewUser when you send it from the view, you should use that to display the errors:
{{ NewUser.errors }}

Django Forms custom error message in views

This is my view:
if request.method == 'POST':
form = TeacherRegister(request.POST)
#Gets school object from email domain.
email = form['email'].value().split('#')[1]
try:
school = School.objects.get(email_domain = email)
except ObjectDoesNotExist:
#add custom error message here
if form.is_valid():
user, Teacher = form.save()
Teacher.school = school
Teacher.save()
user.groups.add(Group.objects.get(name='Teacher'))
#user.is_active to stop users logging in without confirming their emails
user.is_active = False
user.save()
#Sends confirmation link.
send_confirmation_email(request, user)
args = {'email': user.email,
'link': user.Teacher.school.email_website}
return render(request, 'email/token_sent.html', args)
else:
args = {'form': form,}
return render(request, 'users/teachers.html', args)
These lines are what I am trying to work with:
email = form['email'].value().split('#')[1]
try:
school = School.objects.get(email_domain = email)
except ObjectDoesNotExist:
#add custom error message here
This is the HTML I have for the email field:
<div class="required field" >
{{ form.email.label }}
{{ form.email }}
{{ form.email.help_text }}
<!-- <label>Email</label>
<input placeholder="Email" type="email" name="email" autofocus="" required="" id="id_email"> -->
</div>
How can I get it to say, if no school object is returned, something along the lines of 'School not found, check your email'?
Thanks
You need to perform validation on the form side.
Implement clean_email method in the form:
def clean_email(self):
email = self.cleaned_data.get('email')
email = email.split('#')[1]
try:
school = School.objects.get(email_domain = email)
except ObjectDoesNotExist:
raise forms.ValidationError(''School not found, check your email')
return email
Now in template you can show this error right after email field:
{{ form.email.label }}
{{ form.email }}
{{ form.email.errrors }}
{{ form.email.help_text }}
You can try Django's built-in messages framework. Try this:
try:
school = School.objects.get(email_domain = email)
except ObjectDoesNotExist:
messages.error(request, 'School not found, check your email')
And then somewhere above your form, add this:
{% if messages %}
{% for message in messages %}
<div class="alert {% if message.tags %} alert-{{ message.tags }}{% endif %}">{{ message|safe }}</div>
{% endfor %}
{% endif %}
Hope it helps!

Django modelform is submitted, but data is not saved?

Okay Guys, I have a custom User Registration form, whenever the form is submitted a browser alert pops up saying "The Page at 127.0.0.1:8000 says: Submitted!" and nothing happens. No data is saved. Following is the code of the Index view where i am trying to save the form:
def Index(request):
"""View to serve the index page."""
regform = models.RegistrationForm()
loginform = models.LoginForm()
if request.method == 'POST':
if 'signup' in request.POST:
form = models.RegistrationForm(request.POST)
if form.is_valid():
form.save()
message = 'Your Account has been created. You may login now.'
return shortcuts.render_to_response(
'index.html', {'message' : message, 'regform' : regform, 'loginform' : loginform})
else:
message = 'Error: Please fill in all the fields and try again'
return shortcuts.render_to_response(
'index.html', {'regform' : regform, 'message' : message, 'loginform' : loginform})
elif 'login' in request.POST:
requser = request.POST['loginemail']
reqpass = request.POST['loginpass']
'''check if email exists'''
emailexist = models.member.objects.filter(Email=requser).count()
if emailexist == 1:
exists = True
else:
exists = False
'''if email exists check for password'''
if exists == True:
mem = models.member.objects.get(Email=requser)
if reqpass == mem.Password:
request.session['member_id'] = mem.id
return shortcuts.render_to_response(
'login.html')
else:
error = 'You entered an invalid Password, Please try again.'
return shortcuts.render_to_response(
'index.html', {'error' : error, 'regform' : regform, 'loginform' : loginform})
else:
error = 'That E-mail Address is Not Registered, Please Check the spelling and try again.'
return shortcuts.render_to_response(
'index.html', {'regform' : regform, 'loginform' : loginform, 'error' : error})
else:
return shortcuts.render_to_response(
'index.html', {'regform' : regform, 'loginform' : loginform})
Sorry, Here's the Code to the model and registration form
Model:
class member(models.Model):
"""Model to represent a User."""
First_Name = models.CharField(max_length=100, blank=False)
Last_Name = models.CharField(max_length=100, blank=False)
Stage_Name = models.CharField(max_length=100, unique=True, blank=False)
Account_Type = models.CharField(max_length=200, choices=USERTYPE_CHOICES, blank=False)
Password = models.CharField(max_length=100, blank=False)
Email = models.EmailField(max_length=100, blank=False)
Sex = models.CharField(max_length=1, choices=GENDER_CHOICES, blank=False)
Birthday = models.CharField(max_length=2, blank=False)
def __unicode__(self):
return self.Email
Registration Form:
class RegistrationForm(forms.ModelForm):
Stage_Name = forms.CharField(label='Username')
Email = forms.CharField(initial='you#example.com')
Birthday = forms.CharField(initial='dd/mm/yyyy')
Password = forms.CharField(widget=forms.PasswordInput)
class Meta:
model=member
And here is the template :::::
{% extends 'base.html' %}
{% load login_checkbox %}
{% block topbar %}
<head>
</head>
<body>
<div id="logo" class="left"><img src="/static/images/logo.png" alt="Muzikube" width="200" height="52" border="0"/></div>
<div id="login" class="right">
<form id="loginform" action="." method="post">
{% for field in loginform %}
{% if field.field.widget|is_checkbox %}
<div class="checkbox">{{field}}{{field.label_tag}}<span id="forgotpass">Can't Sign In?</span></div>
{% else %}
{{field.label_tag}}{{field}}
{% endif %}
{% endfor %}
<input id="submit" class="submit" "type="submit" name="login" value="In!" />
</form>
{% if error %}
{{error}}
{% endif %}
</div>
<div class="clear"></div>
</body>
{% endblock topbar %}
{% block content %}
<body>
<div class="left">
<div id="heading">Connect To Other Musicians</div>
<div class="subheading">Upload your music, Share Pictures, Share Videos, Make Friends, Get Known !</div>
<div id="homepageimage"><img src="/static/images/comm.png" alt="Connect to other Musicians Around the world!" width="450" height=""/></div>
<div class="subheading">Muzikube let's you connect to other people around the world that share same interests as you !</div>
</div>
<div id="registrationform" class="right">
<div id="form-title">Sign Up, It's Free !</div>
<div id="form-subtitle">Connect to other musicians around the world.</div>
<div class="border"></div>
<div class="error">
{% if message %}
{{message}}
{% endif %}
</div>
<form id="regform" action="." method="post">
<table>
{{ regform.as_table }}
</table>
<input id="register-submit" class="submit" type="submit" name="signup" value="Sign Up" />
</form>
<div class="border"></div>
</div>
<div class="clear"></div>
</body>
{% endblock content %}
It's a little hard to tell from the code above, but I would guess that you get a POST that doesn't have 'login' or 'signup' in (I can't see why it would have those parameters from the code, maybe it's in the html?) - and so nothing is saved or returned from the post request.