Forgot password emails not sending in Django - python

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

Related

530, b'5.7.0 Authentication Required Error when using gmail to send emails through django

Im having problems with sending emails through gmail in Django. I have set up a app password and yet I cant seem to send emails through Django. My settings.py look like this
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_FROM_USER = 'ianis.donica#gmail.com'
EMAIL_HOST_PASSWORD = 'my app password'
EMAIL_PORT = 587
EMAIL_USE_TLS = True
EMAIL_USE_SSL = False
To my best of knowledge it isn't a gmail specific issue, as I had experienced the same problems across yahoo mail and Sendgrid, the function that's responsible for sending the email looks like this
def send_activation_email(user, request):
current_site = get_current_site(request)
email_subject = "Activation Email"
context = {"user": user,
"domain": current_site,
'uid': urlsafe_base64_encode(force_bytes(user.pk)),
'token': generate_token.make_token(user)
}
email_body = render_to_string('email/activate.html',context)
email = EmailMessage(subject=email_subject, body=email_body, from_email=settings.EMAIL_FROM_USER, to=[user.email])
email.send()
and the full error message is this
SMTPSenderRefused at /register/
(530, b'5.7.0 Authentication Required. Learn more at\n5.7.0 https://support.google.com/mail/?p=WantAuthError g9-20020a170906394900b00872a726783dsm9975622eje.217 - gsmtp', 'ianis.donica#gmail.com')
What I tried was changing to yahoo and SendGrid mail but the same issues occurred there, just with different names. I also tried changing some details but that shouldn't be the problem? Yet I cant seem to send an email anywhere. If anyone can help me I would really appreciate it
I also have IMAP enabled
The problem was with me using EMAIL_FROM_USER instead of EMAIL_HOST_USER, so I would need to change the code to this
settings.py
...
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_HOST_USER = 'ianis.donica#gmail.com'
EMAIL_HOST_PASSWORD = 'my app password'
...
views.py
...
email = EmailMessage(subject=email_subject, body=email_body, from_email=settings.EMAIL_HOST_USER, to=[user.email])
...
This is because without EMAIL_HOST_USER, Django won't try to authenticate

Django email backend and smtp configuration

I'm trying to use my Zoho account within my django project, in order to receive emails via contact forms.
I also followed this guide: https://www.zoho.com/mail/help/zoho-smtp.html
In the 'settings.py' file I wrote:
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'smtppro.zoho.eu'
EMAIL_PORT = 587
EMAIL_USE_TLS = True
EMAIL_HOST_USER = '<domain name email>'
EMAIL_HOST_PASSWORD = '<password>'
and in views.py:
def home(request):
allTemplates = AllTemplates.objects.all()
if request.method == 'POST':
form = forms.ContactForm(request.POST)
if form.is_valid():
body = {
'name': form.cleaned_data['name'],
'surname': form.cleaned_data['surname'],
'from_email': form.cleaned_data['from_email'],
'message': form.cleaned_data['message'],
}
mail_body = "\n".join(body.values())
try:
send_mail("Generic contact", mail_body, '<domain name email>',
['<domain name email>'], fail_silently=False)
except BadHeaderError:
return HttpResponse('Ops, qualcosa è andato storto')
form = forms.ContactForm
context = {'form': form, 'allTemplates': allTemplates,
'allTemplates_length': len(allTemplates)}
return render(request, 'home.html', context)
N.B. in 'send_email' I entered my email address twice to test
I also tried to use ssl
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'smtppro.zoho.eu'
EMAIL_PORT = 465
EMAIL_USE_SSL = True
EMAIL_HOST_USER = '<domain name email>'
EMAIL_HOST_PASSWORD = '<password>'
but nothing, I don't receive any email.
Is there anyone who has already gone through it or who can direct me towards some document or guide to study?
Thank you very much in advance.
I use
EMAIL_PORT = 587
EMAIL_USE_TLS = True
my biggest pain was that all emails went to spam folder and I did not realize that for 2 hours.
test with local output to terminal:
settings.py
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
test with local mail server to make sure the email is correctly created:
settings.py
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST='localhost'
EMAIL_PORT=1025
and start local test mail server parallel to runserver in terminal window:
python -m smtpd -n -c DebuggingServer localhost:1025

Django Password Reset Multiple

Hello I am trying to create password reset view in Django. I have set up the mail backend and urls and templates. Everything looks fine but when I try to send mail to reset password Django is sending multiple emails. For example 7 or 11 password reset email at the same time. How can I make it just one email for each time.
Thanks a lot
This is What I did:
setting.py:
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST_USER = "my_email"
EMAIL_HOST_PASSWORD = "my_password"
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_PORT = 587
EMAIL_USE_TLS = True
urls.py
path('password-reset/',
auth_views.PasswordResetView.as_view(template_name='accounts/password_reset.html'),
name='password_reset'),
path('password-reset/done/',
auth_views.PasswordResetDoneView.as_view(template_name='accounts/password_reset_done.html'),
name='password_reset_done'),
path('password-set-confirm/<uidb64>/<token>/',
auth_views.PasswordResetConfirmView.as_view(template_name='accounts/password_reset_confirm.html'),
name='password_reset_confirm'),
path('password-set-complete/',
auth_views.PasswordResetCompleteView.as_view(template_name='accounts/password_reset_complete.html'),
name='password_reset_complete'),
Also, I set the templates for each view.
IF this is still a problem... If you have multiple "test users" and you created them with the same email address that is probably causing your problme
It sometimes helps to check the Django source code itself, so always dive into that if you don't understand what's happening.
If you look at PasswordResetForm's save() method in django.contrib.auth.forms, you'll see that it loops through self.get_users(email) and then sends one (and only one) email for each user.
So the only way multiple emails can be sent is if there are multiple users with the same email.
I don't think their is any setting for the same you may be end up calling same URL multiple time might be a logic issue.
Try to use debug mode or with the help of print statements.
PasswordResetForm has get_users() method which returns all active usernames in an email. We can overwrite that method to return just 1 user which is passed to it. This way password reset email will be sent to only 1 user that we choose.
from django.contrib.auth.forms import PasswordResetForm
class MyPasswordResetFormSpecificUser(PasswordResetForm):
"""
Send password reset email to specific user and not all active
users in an email.
"""
user = None
def get_users(self, email):
"""
Instead of getting all users in an email,
just sent the user that we want to reset password for.
"""
return [self.user]
Then you can use this new form class into your views as shown below:
email = 'your email here'
form = MyPasswordResetFormSpecificUser({'email': email})
assert form.is_valid()
form.user = 'User object who needs password reset'
# use https only when running on GAE
form.save(
request=self.request,
use_https=False # True if you are deploying to https url
)

How to use AWS Simple Email Service (SES) in Django?

I'm trying to use this library to integrate my Django project with AWS SES.
settings.py
EMAIL_BACKEND = 'django_ses.SESBackend'
AWS_ACCESS_KEY_ID = 'my_aws_access_key'
AWS_SECRET_ACCESS_KEY = 'my_aws_secret_access_key'
AWS_SES_REGION_NAME = 'us-west-2'
AWS_SES_REGION_ENDPOINT = 'email.us-west-2.amazonaws.com'
It throws the following error
SESAddressNotVerifiedError: 400 Email address is not verified.
<ErrorResponse xmlns="http://ses.amazonaws.com/doc/2010-12-01/">
<Error>
<Type>Sender</Type>
<Code>MessageRejected</Code>
<Message>Email address is not verified. The following identities failed the check in region US-WEST-2: jpark1320#gmail.com, webmaster#localhost</Message>
</Error>
<RequestId>0220c0a0-741b-11e8-a153-475b5dfc6545</RequestId>
</ErrorResponse>
I can't even guess why is wrong on my codes. But, one thing might be a problem is send_mail(). I'm using trying to send an email to a user for sign-up confirmation. I put the codes for sending email below.
SMTP settings
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_HOST_USER = 'my_google_email#gmail.com'
EMAIL_HOST_PASSWORD = 'my_google_email_password'
EMAIL_PORT = 587
EMAIL_USE_TLS = True
DEFAULT_FROM_EMAIL = 'My Team Name <noreply#gmail.com>'
Update
views.py
def signup(request):
if request.method == 'POST':
form = SignupForm(request.POST)
if form.is_valid():
# Create a user object to set email to be username before passing it to db
user = form.save(commit=False)
user.is_active = False
user.email = form.cleaned_data['username']
user.save()
current_site = get_current_site(request)
mail_subject = "[Modvisor] Please verify your email address."
message = render_to_string('accounts/account_active_email.html', {
'user': user,
'domain': current_site.domain,
'uid': urlsafe_base64_encode(force_bytes(user.pk)),
'token': account_activation_token.make_token(user),
})
to_email = user.email
email = EmailMessage(
mail_subject, message, to=[to_email]
)
email.send()
return redirect('signup_confirm')
else:
form = SignupForm()
return render(request, 'accounts/register.html', {'form': form})
The relevant part of the error is "Email address is not verified". By default SES is in sandbox mode where it won't let you use From or To addresses that you have not previously verified. You need to verify the addresses in the SES console or open a support request to leave sandbox.
Verifying Email Addresses in Amazon SES
To verify an address go to the SES console. On the left side select Email Addresses and then click Verify New Email Address. You will need to have access to the email address so you can click the link that will be sent to it.
Moving Out of the Amazon SES Sandbox
To move out of the sandbox simply open a support request, describe your use case and wait a few days.

Sending email from webserver - django python

I am having difficulties in configuring my settings.py so that I can send email from a webserver with any sender name
This is what I have done:
EMAIL_USE_TLS = True
EMAIL_HOST = 'mail.wservices.ch'
HOSTNAME = 'localhost'
DEFAULT_FROM_EMAIL = 'info#domain.com'
And sending email like this:
html_content = render_to_string('htmlmail.html', {})
text_content = strip_tags(html_content)
msg = EmailMultiAlternatives('subject!',text_content,'info#domain.com',['to#domain.com'])
msg.attach_alternative(html_content, "text/html")
msg.send()
But I am getting:
{('to#domain.com': (554, '5.7.1 <to#domain.com>: Relay access denied')}
In one function, I have two msg.send() calls, BTW.
What am I doing wrong?
this is the answer webmaster when i asked how to send mails from webserver programmatically:
It is possible to send mails from E-Mail-Server "mail.wservices.ch".I suggest to
use the local installed Mail-Server. Hostname: localhost
There you can set any sender name, they just have to exist.
https://docs.djangoproject.com/en/dev/ref/settings/#default-from-email
Make sure first you have properly install django-sendmail
$ sudo apt-get install sendmail
in the settings.py :
from django.core.mail import send_mail
DEFAULT_FROM_EMAIL='webmaster#localhost'
SERVER_EMAIL='root#localhost'
EMAIL_HOST = 'localhost'
EMAIL_HOST_USER=''
EMAIL_BACKEND ='django.core.mail.backends.smtp.EmailBackend'
EMAIL_PORT = 25 #587
EMAIL_USE_TLS = False
in views.py:
from project.apps.contact import ContactForm
def contactnote(request):
if request.method=='POST':
form =ContactForm(request.POST)
if form.is_valid():
topic=form.cleaned_data['topic']
message=form.cleaned_data['message']
sender=form.cleaned_data.get('sender','email_address')
send_mail(
topic,
message,
sender,
['myaddress#gmail.com'],fail_silently=False
)
#return HttpResponseRedirect(reverse('games.views.thanks', {},RequestContext(request)))
return render_to_response('contact/thanks.html', {},RequestContext(request)) #good for the reverse method
else:
form=ContactForm()
return render_to_response('contact.html',{'form':form},RequestContext(request))
contact.py:
from django import forms as forms
from django.forms import Form
TOPIC_CHOICES=(
('general', 'General enquiry'),
('Gamebling problem','Gamebling problem'),
('suggestion','Suggestion'),
)
class ContactForm(forms.Form):
topic=forms.ChoiceField(choices=TOPIC_CHOICES)
sender=forms.EmailField(required=False)
message=forms.CharField(widget=forms.Textarea)
#the widget here would specify a form with a comment that uses a larger Textarea widget, rather than the default TextInput widget.
def clean_message(self):
message=self.cleaned_data.get('message','')
num_words=len(message.split())
if num_words <4:
raise forms.ValidationError("Not enough words!")
return message
Try it , this is a whole working example apps, modify it
to be send to to mailserver like a reply when it got an mail, very simple to modify it

Categories

Resources