annotate core/functions.py @ 892:79a71b9d0a2a

Use Reply-To header when sending mail from other users. See issue #81.
author Brian Neal <bgneal@gmail.com>
date Mon, 16 Feb 2015 20:30:48 -0600
parents 97f8fab9b1a3
children 51a2051588f5
rev   line source
bgneal@700 1 """This file houses various core utility functions"""
bgneal@700 2 from contextlib import contextmanager
bgneal@176 3 import datetime
bgneal@700 4 import logging
bgneal@700 5 import os
bgneal@227 6 import re
gremmie@1 7
gremmie@1 8 from django.contrib.sites.models import Site
gremmie@1 9 from django.conf import settings
bgneal@522 10 import django.core.mail
gremmie@1 11
bgneal@513 12 import core.tasks
bgneal@181 13
gremmie@1 14
bgneal@700 15 @contextmanager
bgneal@700 16 def temp_open(path, mode):
bgneal@700 17 """A context manager for closing and removing temporary files."""
bgneal@700 18 fp = open(path, mode)
bgneal@700 19 try:
bgneal@700 20 yield fp
bgneal@700 21 finally:
bgneal@700 22 fp.close()
bgneal@700 23 os.remove(path)
bgneal@700 24
bgneal@700 25
bgneal@892 26 def send_mail(subject, message, from_email, recipient_list, reply_to=None, defer=True):
gremmie@1 27 """
bgneal@513 28 The main send email function. Use this function to send email from the
bgneal@513 29 site. All applications should use this function instead of calling
bgneal@513 30 Django's directly.
bgneal@522 31 If defer is True, the email will be sent to a Celery task to actually send
bgneal@522 32 the email. Otherwise it is sent on the caller's thread. In any event, the
bgneal@513 33 email will be logged at the DEBUG level.
bgneal@513 34
bgneal@513 35 """
bgneal@513 36 # Guard against empty email addresses
bgneal@418 37 recipient_list = [dest for dest in recipient_list if dest]
bgneal@418 38 if not recipient_list:
bgneal@418 39 logging.warning("Empty recipient_list in send_mail")
bgneal@418 40 return
gremmie@1 41
bgneal@892 42 logging.debug('EMAIL:\nFrom: %s\nTo: %s\nReply-To: %s\nSubject: %s\nMessage:\n%s',
bgneal@892 43 from_email, str(recipient_list), reply_to, subject, message)
bgneal@892 44
bgneal@892 45 headers = {'Reply-To': reply_to} if reply_to else None
bgneal@892 46 msg_kwargs = {
bgneal@892 47 'subject': subject,
bgneal@892 48 'body': message,
bgneal@892 49 'from_email': from_email,
bgneal@892 50 'to': recipient_list,
bgneal@892 51 'headers': headers,
bgneal@892 52 }
gremmie@1 53
bgneal@522 54 if defer:
bgneal@892 55 core.tasks.send_mail.delay(**msg_kwargs)
bgneal@522 56 else:
bgneal@892 57 msg = django.core.mail.EmailMessage(**msg_kwargs)
bgneal@892 58 msg.send()
bgneal@513 59
gremmie@1 60
gremmie@1 61 def email_admins(subject, message):
gremmie@1 62 """Emails the site admins. Goes through the site send_mail function."""
gremmie@1 63 site = Site.objects.get_current()
gremmie@1 64 subject = '[%s] %s' % (site.name, subject)
bgneal@316 65 send_mail(subject,
bgneal@316 66 message,
gremmie@1 67 '%s@%s' % (settings.GPP_NO_REPLY_EMAIL, site.domain),
gremmie@1 68 [mail_tuple[1] for mail_tuple in settings.ADMINS])
gremmie@1 69
gremmie@1 70
gremmie@1 71 def email_managers(subject, message):
gremmie@1 72 """Emails the site managers. Goes through the site send_mail function."""
gremmie@1 73 site = Site.objects.get_current()
gremmie@1 74 subject = '[%s] %s' % (site.name, subject)
bgneal@316 75 send_mail(subject,
bgneal@700 76 message,
gremmie@1 77 '%s@%s' % (settings.GPP_NO_REPLY_EMAIL, site.domain),
gremmie@1 78 [mail_tuple[1] for mail_tuple in settings.MANAGERS])
gremmie@1 79
gremmie@1 80
gremmie@1 81 def get_full_name(user):
gremmie@1 82 """Returns the user's full name if available, otherwise falls back
gremmie@1 83 to the username."""
gremmie@1 84 full_name = user.get_full_name()
gremmie@1 85 if full_name:
gremmie@1 86 return full_name
gremmie@1 87 return user.username
bgneal@9 88
bgneal@176 89
bgneal@176 90 BASE_YEAR = 2010
bgneal@176 91
bgneal@176 92 def copyright_str():
bgneal@176 93 curr_year = datetime.datetime.now().year
bgneal@176 94 if curr_year == BASE_YEAR:
bgneal@176 95 year_range = str(BASE_YEAR)
bgneal@176 96 else:
bgneal@176 97 year_range = "%d - %d" % (BASE_YEAR, curr_year)
bgneal@176 98
bgneal@176 99 return 'Copyright (C) %s, SurfGuitar101.com' % year_range
bgneal@227 100
bgneal@227 101
bgneal@227 102 IP_PAT = re.compile('(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})')
bgneal@227 103
bgneal@227 104 def get_ip(request):
bgneal@227 105 """Returns the IP from the request or None if it cannot be retrieved."""
bgneal@227 106 ip = request.META.get('HTTP_X_FORWARDED_FOR',
bgneal@227 107 request.META.get('REMOTE_ADDR'))
bgneal@227 108
bgneal@227 109 if ip:
bgneal@227 110 match = IP_PAT.match(ip)
bgneal@227 111 ip = match.group(1) if match else None
bgneal@227 112
bgneal@227 113 return ip
bgneal@241 114
bgneal@241 115
bgneal@241 116 def get_page(qdict):
bgneal@241 117 """Attempts to retrieve the value for "page" from the given query dict and
bgneal@241 118 return it as an integer. If the key cannot be found or converted to an
bgneal@241 119 integer, 1 is returned.
bgneal@241 120 """
bgneal@241 121 n = qdict.get('page', 1)
bgneal@241 122 try:
bgneal@241 123 n = int(n)
bgneal@241 124 except ValueError:
bgneal@241 125 n = 1
bgneal@241 126 return n
bgneal@566 127
bgneal@566 128
bgneal@566 129 def quote_message(who, message):
bgneal@566 130 """
bgneal@566 131 Builds a message reply by quoting the existing message in a
bgneal@566 132 typical email-like fashion. The quoting is compatible with Markdown.
bgneal@566 133 """
bgneal@816 134 msg = "> %s" % message.rstrip().replace('\n', '\n> ')
bgneal@566 135 if msg.endswith('\n> '):
bgneal@566 136 msg = msg[:-2]
bgneal@566 137
bgneal@566 138 return "*%s wrote:*\n\n%s\n\n" % (who, msg)