Django restframe work send email from posted data - python

I'm using Django rest framework, I have a contact us table.. in views, I use class based view i want to send email when user post data .. this's my function
def post(self, request):
return self.create(request)
return send_email(request)
def send_email(request):
if request.method == 'POST':
subject = request.POST.get('subject', '')
message = request.POST.get('message', '')
from_email = request.POST.get('email', '')
send_mail(subject, message, from_email, ['haguwanax#l0real.net'], fail_silently=False)
return Response (status=status.HTTP_200_OK)
it saves the data but there's nothing being sent.
this's my settings.py
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
EMAIL_PORT = 587
EMAIL_HOST_USER = '*****#gmail.com'
EMAIL_HOST_PASSWORD = '*******'
EMAIL_USE_TLS = True

You can not use two return at a time in a same block of code. Your second return statement will not execute.
I don't think your create method need return something. It's just storing some values.
And your send email might return true or false if email send is successful or not
Please use only one return statement in your post function.
You can rewrite the code following:
def post(self, request):
self.create(request)
check_mail=send_email(request)
if check_mail:
return Response (status=status.HTTP_200_OK)
def send_email(request):
if request.method == 'POST':
subject = request.POST.get('subject', '')
message = request.POST.get('message', '')
from_email = request.POST.get('email', '')
send_mail(subject, message, from_email, ['haguwanax#l0real.net'],
fail_silently=False)
return True

The send_email function is not being called because you're calling it after return self.create(request). Your code for send_email is hence unreachable.
Please use only one return statement in your post function.
You can call email method without the return statement and then call return self.create(request)
send_email(request)
return self.create(request)

Related

smtplib.SMTPAuthenticationError - Can't use Outlook SMTP for a forgot password feature in Flask

I am implementing a feature where I can send a reset password email to someone in a Flask website. here's what I have in my init.py file:
app.config['MAIL_SERVER'] = 'smtp.office365.com'
app.config['MAIL_PORT'] = 587
app.config['MAIL_USE_TLS'] = True
app.config['MAIL_USERNAME'] = 'email#organisation.org'
app.config['MAIL_PASSWORD'] = 'password'
mail = Mail(app)
Here's what I have in my routes.py file:
def send_rp_email(user):
token = user.get_token()
mess = Message('Password Reset Request', sender="email#organisation.org", recipients=[user.email])
mess.body = f'''This email has been sent since you want to reset your password.
If you did not request to reset your password, please ignore this email.
{url_for('reset_token', token=token, _external=True)}'''
mail.send(mess)
#app.route('/requestpass', methods=['GET', 'POST'])
def reset_request():
check = check_user()
form = RequestResetPass()
if form.validate_on_submit():
email = Users.query.filter_by(email=form.email.data).first()
send_rp_email(email)
flash('An email has been sent to your email address.', 'info')
return redirect(url_for('login'))
return render_template('requestrp.html', form=form)
#app.route('/resetpass/<token>', methods=['GET', 'POST'])
def reset_token(token):
user = Users.verify_token(token)
if user is None:
flash('Invalid token', 'warning')
return redirect(url_for('reset_request'))
form = ResetPass()
if form.validate_on_submit():
hashed_pass = bcrypt.generate_password_hash(form.password.data).decode('utf-8')
user.password = hashed_pass
user = Users.query.filter(Users.id == current_user.id)
user.update({
"password": hashed_pass
})
db.session.commit()
return redirect(url_for('login'))
return render_template('resetpass.html', form=form)
I am getting this error whenever I submit an email address to send the email through:
smtplib.SMTPAuthenticationError: (535, b'5.7.139 Authentication unsuccessful, the request did not meet the criteria to be authenticated successfully. Contact your administrator.

How to merge a function into another

Sorry for asking a basic thing. new to Python and Django ,
I want to resend email if the OTP from PUT request is incorrect.
I have a function which send email with otp automatically on Register.
But if user PUT incorrect OTP I want to resend that email with new otp, So I want to merge sent_email_otp into verifyEmail function.
So how could I achieve that?
#receiver(post_save, sender=CustomUser)
def send_email_otp(sender, instance, created, **kwargs):
if created:
try:
subject = "Your email needs to be verified to use site"
message = f'Hi, Dear {instance.name} use this following OTP to Get verified your email : OTP({instance.otpForEmail})'
email_from = settings.EMAIL_HOST_USER
recipient_list = [instance.email]
send_mail(subject, message, email_from, recipient_list)
print(f"Email Sent to {instance.email}")
except Exception as e:
print(e)
print("Something Wrong at send_email_otp")
#api_view(['PUT'])
#permission_classes([IsAuthenticated])
def verifyEmail(request, pk):
user = CustomUser.objects.get(id=pk)
data = request.data
otp_to_verify = data['otpForEmail']
if otp_to_verify == user.otpForEmail:
user.isEmailVerified = True
user.save()
message = {'detail': 'Your email is now verified'}
return Response(message, status=status.HTTP_400_BAD_REQUEST)
else:
message = {
'detail': 'OTP is not valid and expired, Use New OTP which we have sent you on the email'}
return Response(message, status=status.HTTP_400_BAD_REQUEST)
Edit:
If I simply call the send_email_otp() inside else statement of verifyEmail then this error comes :
TypeError: send_email_otp() missing 3 required positional arguments: 'sender', 'instance', and 'created'
You cant call the signal directly unless you provide it the expected input.
You will need to create another function for sending the otp. and call it in the post_save signal and in the view
def send_otp(name, email, otpForEmail):
subject = "Your email needs to be verified to use site"
message = f'Hi, Dear {name} use this following OTP to Get verified your email : OTP({otpForEmail})'
email_from = settings.EMAIL_HOST_USER
recipient_list = [email]
send_mail(subject, message, email_from, recipient_list)
print(f"Email Sent to {email}")
#receiver(post_save, sender=CustomUser)
def send_email_otp_on_post_save(sender, instance, created, **kwargs):
if created:
try:
send_otp(instance.name, instance.email, instance.otpForMail)
except Exception as e:
print(e)
print("Something Wrong at send_email_otp")
#api_view(['PUT'])
#permission_classes([IsAuthenticated])
def verifyEmail(request, pk):
user = CustomUser.objects.get(id=pk)
data = request.data
otp_to_verify = data['otpForEmail']
if otp_to_verify == user.otpForEmail:
user.isEmailVerified = True
user.save()
message = {'detail': 'Your email is now verified'}
return Response(message, status=status.HTTP_400_BAD_REQUEST)
else:
message = {
'detail': 'OTP is not valid and expired, Use New OTP which we have sent you on the email'}
send_otp(user.name, user.email, user.otpForEmail)
return Response(message, status=status.HTTP_400_BAD_REQUEST)
It would be hard for you to configure the same function to send_mail again to send OTP, as you said this sends the email when the user gets registered. So why not modify the verifyEmail itself.
First, you don't need a user instance here as the user is already authenticated and you already have the User Id.
So in the else statement of verifyEmail, you can send_email without calling send_email_otp() function.
Update the verifyEmail to.
#api_view(['PUT'])
#permission_classes([IsAuthenticated])
def verifyEmail(request, pk):
user = CustomUser.objects.get(id=pk)
data = request.data
otp_to_verify = data['otpForEmail']
if otp_to_verify == user.otpForEmail:
user.isEmailVerified = True
user.save()
message = {'detail': 'Your email is now verified'}
return Response(message, status=status.HTTP_400_BAD_REQUEST)
else:
subject = "Your email needs to be verified to use site "
message = f'Hi, Dear {user.name} use this following OTP to Get verified your email : OTP({user.otpForEmail})'
email_from = settings.EMAIL_HOST_USER
recipient_list = [user.email]
send_mail(subject, message, email_from, recipient_list)
print(f"Email Sent to {user.email}")
message = {
'detail': 'OTP is not valid and expired, Use New OTP which we have sent you on the email'}
return Response(message, status=status.HTTP_400_BAD_REQUEST)

How to send a reset password email in Django on User creation?

I want to be able to let an admin create user accounts and then, instead of setting up a password for the user, the user would automatically receive a reset password email.
The view for the user creation, which also includes a Member model, is the following:
def newmember(request):
if request.method == 'POST':
nu_form = NewUser(request.POST)
nm_form = NewMember(request.POST)
if nu_form.is_valid() and nm_form.is_valid():
nusave = nu_form.save()
nmsave = nm_form.save(commit = False)
nmsave.user = nusave
nmsave.save()
return redirect(members)
else:
print(nu_form.errors)
print(nm_form.errors)
else:
nu_form = NewUser()
nm_form = NewMember()
context = {
'nu_form': nu_form,
'nm_form': nm_form}
return render(request, 'web/newmember.html', context)
How can I make so that upon creation of a new user, Django automatically sends an email to that new user requestion a password reset?
In order to send an email on user creation you need to define a method which shoot an email like below :-
Create a text file name such as 'email_content.txt'
Please reset password for your profile {{username}}
Click Here
Update the newmember method and add below code into it :-
template = get_template('email_content.txt')
context = {"usename": nmsave.user.username}
content = template.render(context)
email = EmailMessage(
"Congratulation, please reset your account password", content, 'App Name' <sender_email>
)
email.content_subtype = "html"
email.send()
add above code in try catch block
In your models.py:
def save(self, *args, **kwargs):
send_mail('subject', 'message', 'your email', 'user email')
return super().save(*args, **kwargs)

Send email to address getting from HTML input via Django

I'm searching for solution to this problem for many hours but can't find anything related. I want to get user's email from input and send mail from admin to that email address. Here are my codes:
views.py:
def index(request):
context = {
'questions': Question.objects.all(),
'applicants': Applicant.objects.filter(status=1),
'empty_cards': range(4 - Applicant.objects.filter(status=1).count())
}
if request.method == "POST":
if request.POST.get('message_text'):
Message.objects.create(
sender_name = request.POST.get('sender_name'),
sender_email = request.POST.get('sender_email'),
message_text = request.POST.get('message_text'))
if request.method == 'POST':
subject = 'Welcome !'
message = 'We will back to you.'
from_email = settings.EMAIL_HOST_USER
recipient_list = 'don't know how to get email'
send_mail(subject, message, from_email, recipient_list)
return render(request, 'index.html', context)
from your code I assume that you already have access to the user's mail
inside the request.
so you can try this:
sender_email = sender_request.POST.get('sender_email')
recipient_list = [sender_email]

Forgot password emails not sending in Django

I am trying to implement password reset functionality.
My urls contains:
url(r'^password_reset/$','django.contrib.auth.views.password_reset', {'template_name': 'resetpassword.html', 'post_reset_redirect' : '/password_reset/mailed/'},
name="password_reset"),
url(r'^password_reset/mailed/$',
'django.contrib.auth.views.password_reset_done',{'template_name': 'resetpassword_mailed.html'}),
url(r'^password_reset/(?P<uidb36>[0-9A-Za-z]{1,13})-(?P<token>[0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,20})/$',
'django.contrib.auth.views.password_reset_confirm',
{'post_reset_redirect' : '/password_reset/complete/'}),
url(r'^password_reset/complete/$',
'django.contrib.auth.views.password_reset_complete',{'template_name': 'resetpassword_complete.html'}),
and settings.py:
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'smtp.mail.ru'
EMAIL_HOST_USER = 'noreply#mysite.com'
DEFAULT_FROM_EMAIL = 'noreply#mysite.com'
EMAIL_HOST_PASSWORD = 'password'
EMAIL_PORT = 587
EMAIL_USE_TLS = True
URL routing works just fine, however email are not being sent.
If I try to use Django shell and test sending:
email = EmailMessage('Subject', 'Body', to=['test#email.com'])
email.send()
And it works just fine as well.
How could I fix this? I don't get any error messages and don't know how could I debug this.
UPD
I have found out that in django/contrib/auth/views.py: password_reset method I always go to
else:
post_reset_redirect = resolve_url(post_reset_redirect)
part and never to actually sending email. How's that?
if post_reset_redirect is None:
post_reset_redirect = reverse('password_reset_done')
else:
post_reset_redirect = resolve_url(post_reset_redirect)
if request.method == "POST":
form = password_reset_form(request.POST)
if form.is_valid():
print 'reset form valid'
opts = {
'use_https': request.is_secure(),
'token_generator': token_generator,
'from_email': from_email,
'email_template_name': email_template_name,
'subject_template_name': subject_template_name,
'request': request,
'html_email_template_name': html_email_template_name,
}
if is_admin_site:
opts = dict(opts, domain_override=request.get_host())
form.save(**opts)
return HttpResponseRedirect(post_reset_redirect)
If the user has no password (e.g. created with create_user()), the password reset won't send anything! Make sure you create a password as well via:
password = User.objects.make_random_password()
Then, you also need to set the password and save, for example
user.set_password(password)
user.save()
Could be a trivial question but the user you are using to test has a valid email set? If it's empty will not send the email neither raise an exception.
Check the send method source code.
Other way to see if the email is being generated is use the console backend:
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
and look at the console because the email should appears there.
Thanks

Categories

Resources