Templating emails -- new account and new premium.

This commit is contained in:
Samuel Clay 2011-09-19 08:56:16 -07:00
parent 2a3c93a3e4
commit afae94cf7d
10 changed files with 176 additions and 96 deletions

View file

@ -2,19 +2,23 @@ import datetime
from django.db import models from django.db import models
from django.db import IntegrityError from django.db import IntegrityError
from django.db.utils import DatabaseError from django.db.utils import DatabaseError
from django.contrib.auth.models import User
from django.db.models.signals import post_save from django.db.models.signals import post_save
from django.core.mail import mail_admins from django.conf import settings
from django.contrib.auth import authenticate from django.contrib.auth import authenticate
from django.contrib.auth.models import User
from django.core.mail import mail_admins
from django.core.mail import EmailMultiAlternatives
from django.template.loader import render_to_string
from celery.task import Task
from apps.reader.models import UserSubscription from apps.reader.models import UserSubscription
from apps.rss_feeds.models import Feed from apps.rss_feeds.models import Feed
from paypal.standard.ipn.signals import subscription_signup
from apps.rss_feeds.tasks import NewFeeds from apps.rss_feeds.tasks import NewFeeds
from celery.task import Task
from utils import log as logging from utils import log as logging
from vendor.timezones.fields import TimeZoneField
from utils.user_functions import generate_secret_token from utils.user_functions import generate_secret_token
from vendor.timezones.fields import TimeZoneField
from vendor.paypal.standard.ipn.signals import subscription_signup
class Profile(models.Model): class Profile(models.Model):
user = models.OneToOneField(User, unique=True, related_name="profile") user = models.OneToOneField(User, unique=True, related_name="profile")
is_premium = models.BooleanField(default=False) is_premium = models.BooleanField(default=False)
@ -30,7 +34,7 @@ class Profile(models.Model):
secret_token = models.CharField(max_length=12, blank=True, null=True) secret_token = models.CharField(max_length=12, blank=True, null=True)
def __unicode__(self): def __unicode__(self):
return "%s" % self.user return "%s <%s> (Premium: %s)" % (self.user, self.user.email, self.is_premium)
def save(self, *args, **kwargs): def save(self, *args, **kwargs):
if not self.secret_token: if not self.secret_token:
@ -95,6 +99,34 @@ NewsBlur""" % {'user': self.user.username, 'feeds': subs.count()}
if stale_feeds: if stale_feeds:
stale_feeds = list(set([f.feed.pk for f in stale_feeds])) stale_feeds = list(set([f.feed.pk for f in stale_feeds]))
self.queue_new_feeds(new_feeds=stale_feeds) self.queue_new_feeds(new_feeds=stale_feeds)
def mail_new_account(self):
if not self.user.email:
return
user = self.user
text = render_to_string('mail/email_new_account.txt', locals())
html = render_to_string('mail/email_new_account.xhtml', locals())
subject = "Welcome to NewsBlur, %s" % (self.user.username)
msg = EmailMultiAlternatives(subject, text,
from_email='NewsBlur <%s>' % settings.HELLO_EMAIL,
to=['%s <%s>' % (user, user.email)])
msg.attach_alternative(html, "text/html")
msg.send()
def mail_new_premium(self):
if not self.user.email:
return
user = self.user
text = render_to_string('mail/email_new_premium.txt', locals())
html = render_to_string('mail/email_new_premium.xhtml', locals())
subject = "Thanks for going premium on NewsBlur!"
msg = EmailMultiAlternatives(subject, text,
from_email='NewsBlur <%s>' % settings.HELLO_EMAIL,
to=['%s <%s>' % (user, user.email)])
msg.attach_alternative(html, "text/html")
msg.send()
def create_profile(sender, instance, created, **kwargs): def create_profile(sender, instance, created, **kwargs):

View file

@ -8,7 +8,7 @@ import urllib
from collections import defaultdict from collections import defaultdict
from operator import itemgetter from operator import itemgetter
from BeautifulSoup import BeautifulStoneSoup from BeautifulSoup import BeautifulStoneSoup
from nltk.collocations import TrigramCollocationFinder, BigramCollocationFinder, TrigramAssocMeasures, BigramAssocMeasures # from nltk.collocations import TrigramCollocationFinder, BigramCollocationFinder, TrigramAssocMeasures, BigramAssocMeasures
from django.db import models from django.db import models
from django.db import IntegrityError from django.db import IntegrityError
from django.core.cache import cache from django.core.cache import cache
@ -867,39 +867,39 @@ class Feed(models.Model):
self.save() self.save()
def calculate_collocations_story_content(self, # def calculate_collocations_story_content(self,
collocation_measures=TrigramAssocMeasures, # collocation_measures=TrigramAssocMeasures,
collocation_finder=TrigramCollocationFinder): # collocation_finder=TrigramCollocationFinder):
stories = MStory.objects.filter(story_feed_id=self.pk) # stories = MStory.objects.filter(story_feed_id=self.pk)
story_content = ' '.join([s.story_content for s in stories if s.story_content]) # story_content = ' '.join([s.story_content for s in stories if s.story_content])
return self.calculate_collocations(story_content, collocation_measures, collocation_finder) # return self.calculate_collocations(story_content, collocation_measures, collocation_finder)
#
def calculate_collocations_story_title(self, # def calculate_collocations_story_title(self,
collocation_measures=BigramAssocMeasures, # collocation_measures=BigramAssocMeasures,
collocation_finder=BigramCollocationFinder): # collocation_finder=BigramCollocationFinder):
stories = MStory.objects.filter(story_feed_id=self.pk) # stories = MStory.objects.filter(story_feed_id=self.pk)
story_titles = ' '.join([s.story_title for s in stories if s.story_title]) # story_titles = ' '.join([s.story_title for s in stories if s.story_title])
return self.calculate_collocations(story_titles, collocation_measures, collocation_finder) # return self.calculate_collocations(story_titles, collocation_measures, collocation_finder)
#
def calculate_collocations(self, content, # def calculate_collocations(self, content,
collocation_measures=TrigramAssocMeasures, # collocation_measures=TrigramAssocMeasures,
collocation_finder=TrigramCollocationFinder): # collocation_finder=TrigramCollocationFinder):
content = re.sub(r'&#8217;', '\'', content) # content = re.sub(r'&#8217;', '\'', content)
content = re.sub(r'&amp;', '&', content) # content = re.sub(r'&amp;', '&', content)
try: # try:
content = unicode(BeautifulStoneSoup(content, # content = unicode(BeautifulStoneSoup(content,
convertEntities=BeautifulStoneSoup.HTML_ENTITIES)) # convertEntities=BeautifulStoneSoup.HTML_ENTITIES))
except ValueError, e: # except ValueError, e:
print "ValueError, ignoring: %s" % e # print "ValueError, ignoring: %s" % e
content = re.sub(r'</?\w+\s+[^>]*>', '', content) # content = re.sub(r'</?\w+\s+[^>]*>', '', content)
content = re.split(r"[^A-Za-z-'&]+", content) # content = re.split(r"[^A-Za-z-'&]+", content)
#
finder = collocation_finder.from_words(content) # finder = collocation_finder.from_words(content)
finder.apply_freq_filter(3) # finder.apply_freq_filter(3)
best = finder.nbest(collocation_measures.pmi, 10) # best = finder.nbest(collocation_measures.pmi, 10)
phrases = [' '.join(phrase) for phrase in best] # phrases = [' '.join(phrase) for phrase in best]
#
return phrases # return phrases
class Meta: class Meta:
db_table="feeds" db_table="feeds"

Binary file not shown.

After

Width:  |  Height:  |  Size: 402 B

View file

@ -47,7 +47,7 @@ LOGIN_URL = '/reader/login'
# Examples: "http://foo.com/media/", "/media/". # Examples: "http://foo.com/media/", "/media/".
ADMIN_MEDIA_PREFIX = '/media/admin/' ADMIN_MEDIA_PREFIX = '/media/admin/'
SECRET_KEY = 'YOUR_SECRET_KEY' SECRET_KEY = 'YOUR_SECRET_KEY'
EMAIL_BACKEND = 'django_ses.SESBackend' EMAIL_BACKEND = 'seacucumber.backend.SESBackend'
# =============== # ===============
@ -302,6 +302,7 @@ TEST_RUNNER = "utils.testrunner.TestRunner"
SESSION_COOKIE_NAME = 'newsblur_sessionid' SESSION_COOKIE_NAME = 'newsblur_sessionid'
SESSION_COOKIE_AGE = 60*60*24*365*2 # 2 years SESSION_COOKIE_AGE = 60*60*24*365*2 # 2 years
SERVER_EMAIL = 'server@newsblur.com' SERVER_EMAIL = 'server@newsblur.com'
HELLO_EMAIL = 'hello@newsblur.com'
# =========== # ===========
# = Logging = # = Logging =
@ -322,6 +323,7 @@ INSTALLED_APPS = (
'django.contrib.admin', 'django.contrib.admin',
'django_extensions', 'django_extensions',
'djcelery', 'djcelery',
'seacucumber',
'compress', 'compress',
'apps.rss_feeds', 'apps.rss_feeds',
'apps.reader', 'apps.reader',

View file

@ -0,0 +1,19 @@
{% block body %}{% endblock body %}
-----------------------------------------------------------------------------
Stay up to date and in touch with me, yr. developer, in a few different ways:
* Follow @samuelclay on Twitter: http://twitter.com/samuelclay
* Follow @newsblur on Twitter: http://twitter.com/newsblur
* Follow the constantly evolving source code on GitHub: http://github.com/samuelclay
{% block resources_header %}There are a few resources that would make sense to follow if you end up loving NewsBlur:{% endblock resources_header %}
* Read the NewsBlur Blog: http://blog.newsblur.com
* Get support on NewsBlur's Get Satisfaction: http://getsatisfaction.com/newsblur
* Download the free NewsBlur iPhone app: http://itunes.com/newsblur
-----------------------------------------------------------------------------
Don't want to be notified about anything NewsBlur related? Opt-out of emails from NewsBlur: http://www.newsblur.com/optout.

View file

@ -1,41 +1,66 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html> <html>
<head> <head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title></title> <title></title>
</head> </head>
<body bgcolor="#F5F6F4" text="#000000" link="#003399" vlink="#003399" alink="#DC181E" topmargin="0" leftmargin="0" marginheight="0" marginwidth="0"> <body bgcolor="#F5F6F4" text="#000000" link="#003399" vlink="#003399" alink="#DC181E" topmargin="0" leftmargin="0" marginheight="0" marginwidth="0">
<table cellpadding="0" cellspacing="0" border="0" bgcolor="#F5F6F4" width="100%" height="100%" style="padding-bottom:24px;"> <table cellpadding="0" cellspacing="0" border="0" bgcolor="#F5F6F4" width="100%" height="100%" style="padding-bottom:24px;">
<tr> <tr>
<td> <td>
<table cellpadding="0" cellspacing="0" border="0" bgcolor="#FFFFFF" align="left" width="644" style="padding: 20px; margin-top: 24px;"> <center>
<table cellpadding="0" cellspacing="0" border="0" bgcolor="#FFFFFF" align="left" width="644" style="padding: 20px; margin-top: 24px;align:center;border: 1px solid #BABABA;">
<tr> <tr>
<td style="font-family:'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:16px;color:#333;"> <td align="center">
{% block body %}{% endblock %} <a href="http://www.newsblur.com/login"><img alt="NewsBlur" src="http://www.newsblur.com/media/img/logo_newsblur_blur.png" title="NewsBlur" style="width:312px;height:55px;border: none;"></a>
</td> </td>
</tr> </tr>
<tr> <tr>
<td colspan="2" style="border-top: 3px solid black; padding-top: 12px;" align="center"> <td style="font-family:'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:16px;color:#333;">
<table>
<tr> {% block body %}{% endblock %}
<td>
<a href="http://thebolditalic.com/"><img alt="Logo_email_black" border="false" src="http://thebolditalic.com/images/logo_email_black.png" /></a> <p style="line-height: 20px;border-top: 3px solid #404040;margin-top: 18px;padding-top: 18px">Stay up to date and in touch with me, yr. developer, in a few different ways:</p>
</td> <p style="line-height: 20px;">
<td> <ul style="list-style: none;">
<p style="font-size:12px;"> Don't want to be notified about Idea activity? Go to '<a href="http://thebolditalic.com/users/Samuelclay/edit" style="color:#00BBFF; text-decoration:none;">My Ac= <li><a href="http://twitter.com/samuelclay" style="text-decoration:none"><img src="http://www.newsblur.com/media/img/reader/twitter_icon_2.png" style="width:16px;height:16px;vertical-align:top;"> Follow @samuelclay on Twitter</a>.</li>
count</a>' to update your email settings.<br /> The Bold Italic and The B= <li><a href="http://twitter.com/newsblur" style="text-decoration:none"><img src="http://www.newsblur.com/media/img/reader/twitter.png" style="width:16px;height:16px;vertical-align:top;"> Follow @newsblur on Twitter</a>.</li>
old Italic Logo are registered trademarks of The Bold Italic, 100 Pine St= <li><a href="http://github.com/samuelclay" style="text-decoration:none"><img src="http://www.newsblur.com/media/img/reader/github_icon.png" style="width:16px;height:16px;vertical-align:top;"> Follow the constantly evolving source code on GitHub</a>.</li>
reet, Suite 250, San Francisco, CA 94111.</p> </ul>
</td> </p>
</tr> <p style="line-height: 20px;">{% block resources_header %}There are a few resources that would make sense to follow if you end up loving NewsBlur:{% endblock resources_header %}</p>
<p style="line-height: 20px;">
<ul style="list-style: none;">
<li><a href="http://blog.newsblur.com" style="text-decoration:none"><img src="http://www.newsblur.com/media/img/favicon.png" style="width:16px;height:16px;vertical-align:top;"> Read the NewsBlur Blog</a>.</li>
<li><a href="http://getsatisfaction.com/newsblur" style="text-decoration:none"><img src="http://www.newsblur.com/media/img/reader/getsatisfaction.png" style="width:16px;height:16px;vertical-align:top;"> Get support on NewsBlur's Get Satisfaction</a>.</li>
<li><a href="http://itunes.com/newsblur" style="text-decoration:none"><img src="http://nb.local.host:8000/media/img/reader/iphone_icon.png" style="width:16px;height:16px;vertical-align:top;"> Download the free NewsBlur iPhone app</a>.</li>
</ul>
</p>
</td>
</tr>
<tr>
<td style="border-top: 3px solid #404040; padding-top: 4px;" align="center">
<table>
<tr>
<td>
<p style="font-size:12px;">
Don't want to be notified about anything NewsBlur related? <a href="http://www.newsblur.com/" style="color:#1C4D84; text-decoration:none;">Opt-out of emails from NewsBlur</a>.
</p>
</td>
</tr>
</table>
</td>
</tr>
<tr>
<td align="center">
<a href="http://www.newsblur.com/login"><img alt="NewsBlur" src="http://www.newsblur.com/media/img/logo_newsblur.png" title="NewsBlur" style="width:312px;height:55px;border: none;"></a>
</td>
</tr>
</table> </table>
</td> </center>
</tr> </td>
</table> </tr>
</td>
</tr>
</table> </table>
</body> </body>
</html> </html>

View file

@ -0,0 +1,7 @@
{% extends "mail/email_base.txt" %}
{% block body %}Welcome to NewsBlur, {{ user.username }}.
OK, firstly, thank you for trying out new software. It's not quite what you're used to, but you might find NewsBlur to be a perfect fit. There's a lot packed into a minimal interface.
Spend a few days trying out NewsBlur. I hope you end up loving it.{% endblock body %}

View file

@ -1,25 +1,9 @@
{% extends "email_base.xhtml" %} {% extends "mail/email_base.xhtml" %}
{% block body %} {% block body %}
<table cellspacing="0" cellpadding="0" style="width:100%;"> <p style="font-size: 37px; color:#555555; margin-top: 18px;margin-bottom: 10px;padding-top:6px;">Welcome to NewsBlur, {{ user.username }}.</p>
<tr>
<td align="center">
<img alt="NewsBlur" src="http://www.newsblur.com/media/img/logo_newsblur.png" title="NewsBlur" />
</td>
</tr>
</table>
<p style="font-size: 37px; color:#555555; margin-top: 12px;margin-bottom: 10px;padding-top:6px;">Welcome, {{ user.name }}.</p>
<p style="line-height: 20px;">OK, firstly, thank you for trying out new software. It's not quite what you're used to, but you might find NewsBlur to be a perfect fit. There's a lot packed into a minimal interface.</p> <p style="line-height: 20px;">OK, firstly, thank you for trying out new software. It's not quite what you're used to, but you might find NewsBlur to be a perfect fit. There's a lot packed into a minimal interface.</p>
<p style="line-height: 20px;">Spend a few days trying out NewsBlur. I hope you end up loving it.</p> <p style="line-height: 20px;">Spend a few days trying out NewsBlur. I hope you end up loving it.</p>
<p style="line-height: 20px;">Stay up to date and in touch with me, yr. developer, in a few different ways:</p> {% endblock %}
<p style="line-height: 20px;">
<ul> {% block resources_header %}There are a few resources that would make sense to follow if you end up loving NewsBlur:{% endblock resources_header %}
<li><a href="http://twitter.com/samuelclay">Follow @samuelclay on Twitter</a>.</li>
<li><a href="http://twitter.com/samuelclay">Follow @newsblur on Twitter</a>.</li>
<li><a href="http://github.com/samuelclay">Peak at the source code on GitHub</a>.</li>
<li><a href="http://blog.newsblur.com">Read the NewsBlur Blog</a>.</li>
<li><a href="http://getsatisfaction.com/newsblur">Get support on NewsBlur's Get Satisfaction</a>.</li>
<li><a href="http://itunes.com/newsblur">Download the free NewsBlur iPhone app</a>.</li>
</ul>
</p>
{% endblock %}

View file

@ -0,0 +1,3 @@
{% extends "mail/email_base.txt" %}
{% block body %}Thank you, thank you, thank you!{% endblock body %}

View file

@ -0,0 +1,8 @@
{% extends "mail/email_base.xhtml" %}
{% block body %}
<p style="font-size: 37px; color:#555555; margin-top: 18px;margin-bottom: 10px;padding-top:6px;">Thank you, thank you, thank you!</p>
<p style="line-height: 20px;">A huge thanks for going premium.</p>
{% endblock %}
{% block resources_header %}Now that you're premium, you may want to follow a few resources:{% endblock resources_header %}