dont freeze on sending mail django - django

When django sends an email, it takes from a few milli-seconds to a few seconds depending upon the smtp server. So the problem that i am facing is when django starts sending email it freezes there. The user would have to wait till the mail has been sent. I was wondering if i could simply return the html page and in the background the email could be sent without making the user wait for it.
skeleton is that right before the page is being rendered, email is being sent. So, I want to render the page first and then send the email in the background.

I have done something like this in my project that uses threads:
class EmailThread(Thread):
def __init__(self, myemail):
self.myemail = myemail
Thread.__init__(self)
def run(self):
self.myemail.send()
class MyEmailMessage(EmailMessage):
def send_async(self, fail_silently=False):
thread = EmailThread(self)
thread.start()
# send email
email = MyEmailMessage(...)
email.send_async()

There is also a nice project called django-mailer.
It saves the mails in your database and you send them asynchronously via crontab or celery.

Related

Send mail *without* mail queue in Django

Im using django_yubin to send mails via its mail queue.
However, there are a few instances where I want to send the mail immediately without putting it on the queue.
For example, when a user registers or resets their password. Or certain admin emails.
I tried using Django's built in email system by
from django.core.mail import send_mail as send_mail_core
and then using the send_mail_core() function.
This didnt work - looks like the send_mail in django.core.mail gets overridden by yubin
Thanks for your help
Why would you even try to use send_mail_core if you can select the mail backend inside of send_mail function
def send_mail(subject, message, from_email, recipient_list,
fail_silently=False, auth_user=None, auth_password=None,
connection=None, html_message=None):
connection: The optional email backend to use to send the mail. If
unspecified, an instance of the default backend will be used. See the
documentation on Email backends for more details.

Tornado with Django authentication

Here's my idea:
have a Django Website that receives / send JSON information so that I can create a JavaScript client for a Webbrowser, or a Unity / UE client
I want a new functionality only for Unity / UE client: realtime chat.
I'd like to use a tornado server on a specific port, let's say 8666.
Here's what I've done so far:
authenticate on the Django web site
make everything work on the Django web site
Now I'd like the client to connect to the port 8666 (pure TCP) and to send something (maybe his session cookie or something else) so that I can see on the tornado web server whether the client is authenticated, and look in the database to find out which other mates are connected too on the tornado webserver, so that when this client writes something, I can dispatch his message to all other "concerned" connected clients.
I didn't find any documentation about that. Do you know how to handle this? Any example, or if I'm not on the right track what should I do then?
If your Tornado process runs on the same domain as your Django application, the session cookie will be sent by the browser upon websocket handshake, and accessible through the WebSocketHandler.get_cookie() method.
Here is an example, assuming a global variable CLIENTS keeping track of connected authentified clients:
def open(self):
"""Authenticate client based on session cookie, add broadcast notification"""
session_id = self.get_cookie('sessionid')
if not session_id:
self.close()
self.authenticate_user(session_id)
if self.user is None:
self.close()
self.CLIENTS.append(self)
self.notify_all_clients()
def authenticate_user(self, session_id):
"""Retrieve User instance associated to the session key."""
session = SessionStore(session_key=session_id)
user_id = session.get('_auth_user_id')
if user_id is None:
return
try:
user = User.objects.get(pk=user_id)
except User.DoesNotExist:
self.close()
else:
self.user = user
Hope this helps!
Edit:
Note that to be able to use the Django ORM, you must set the DJANGO_SETTINGS_MODULE environment variable to your app's settings module path (e.g. 'myapp.settings', making sure it can be found through sys.path) and then call setup() as explained in the Django docs.

Sending Bulk email in Django

I have to send bulk email in django, the email template will be will be customized and the some data in the template will be coming from db. i twas using django notification but it can only send email to the registered users. I have to send emails to the non-registered users. there will be five email template the user can select any one and the email has to be sent.
For ex. An invitation to the event to the group of non-registered users. user will enter email ids, and will do a bulk send. which django package can i use to achieve the same.
You can use django's default sending multiple email system. From here: https://docs.djangoproject.com/en/dev/topics/email/#sending-multiple-emails
You can try like this:
from django.core import mail
connection = mail.get_connection()
connection.open()
reciever_list= ['aa#bb.cc', 'dd#ee.ff'] #extend this list according to your requirement
email1 = mail.EmailMessage('Hello', 'Body goes here', 'from#example.com',
reciever_list, connection=connection)
email1.send()
connection.close()
For bulk email reference, you can check this so answer: How does one send an email to 10,000 users in Django?
Edit
From this stackoverflow answer, you can send emails with template. If you use django 1.7, html_message can be added as perameter of send_mail(). Details here.
By the way, for mass email handling, django has send_mass_mail() method.

How to delay sending activation email in django_registration?

I am integrating django_paypal with my django_registration setup for which I have created a custom backend. I can't seem to find in the code where it sends the activation email. Is this located in the backend?
I want to wait and send the activation email until after they have completed a paypal checkout and I receive the IPN notification.
The RegistrationProfile.objects.create_inactive_user manager method has a send_email parameter, which defaults to True.
You just need to set send_email=False when you create a new user.
new_user = RegistrationProfile.objects.create_inactive_user(username, email,
password, site,
send_email=False)

Control a function (E.g send mail) from a users profile page

I have a profile page like so: http://i.stack.imgur.com/Rx4kg.png . In management I would like a option "Notify by mail" that would control my send_email functions in every application I want. As example I'm using django-messages and it sends private messages aswell as emails when you send a message. I would like for the user to be able to specify if he wants emails aswell when he gets a message.
messages/utils.py
def new_message_email(sender, instance, signal,
subject_prefix=_(u'New Message: %(subject)s'),
template_name="messages/new_message.html",
default_protocol=None,
*args, **kwargs):
"""
This function sends an email and is called via Django's signal framework.
Optional arguments:
``template_name``: the template to use
``subject_prefix``: prefix for the email subject.
``default_protocol``: default protocol in site URL passed to template
"""
if default_protocol is None:
default_protocol = getattr(settings, 'DEFAULT_HTTP_PROTOCOL', 'http')
if 'created' in kwargs and kwargs['created']:
try:
current_domain = Site.objects.get_current().domain
subject = subject_prefix % {'subject': instance.subject}
message = render_to_string(template_name, {
'site_url': '%s://%s' % (default_protocol, current_domain),
'message': instance,
})
if instance.recipient.email != "":
send_mail(subject, message, settings.DEFAULT_FROM_EMAIL,
[instance.recipient.email,])
except Exception, e:
#print e
pass #fail silently
Apparently instance.recipient.email is the email for the recipient user. So my questions are: How do I go about creating an option in my profile management that can be used in my new_message_email to check if the user wants emails or not? My own thoughts are that I need to save a value in the database for the user and then check for that value in new_message_email function. How I do that isn't clear though. Do I create a new function in my userprofile/views.py and class in userprofile/forms.py? And have my userprofile/overview.html template change them? Some specifics and thoughts if this is the right approach would help alot!
You probably want to start off by creating a user profile so that you have a good way to store weather or not the user wants these emails sent to them. This is done using the AUTH_PROFILE_MODULE setting in your settings.py.
Once you have the data stored, you should be able to access it from instance.recipient (assuming that instance.recipient is a User object). So you could change your code to:
if instance.recipient.get_profile().wants_emails and instance.recipient.email != "":
send_mail(subject, message, settings.DEFAULT_FROM_EMAIL,
[instance.recipient.email,])
Done and done.