1 # Copyright 2011 GRNET S.A. All rights reserved.
3 # Redistribution and use in source and binary forms, with or
4 # without modification, are permitted provided that the following
7 # 1. Redistributions of source code must retain the above
8 # copyright notice, this list of conditions and the following
11 # 2. Redistributions in binary form must reproduce the above
12 # copyright notice, this list of conditions and the following
13 # disclaimer in the documentation and/or other materials
14 # provided with the distribution.
16 # THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17 # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20 # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23 # USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24 # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26 # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 # POSSIBILITY OF SUCH DAMAGE.
29 # The views and conclusions contained in the software and
30 # documentation are those of the authors and should not be
31 # interpreted as representing official policies, either expressed
32 # or implied, of GRNET S.A.
37 from django.utils.translation import ugettext as _
38 from django.template.loader import render_to_string
39 from django.core.mail import send_mail
40 from django.core.urlresolvers import reverse
41 from django.template import Context, loader
42 from django.contrib.auth import (
46 from django.conf import settings
47 from django.contrib.auth.models import AnonymousUser
49 from urllib import quote
50 from urlparse import urljoin
51 from smtplib import SMTPException
52 from datetime import datetime
53 from functools import wraps
55 from astakos.im.settings import (
56 DEFAULT_CONTACT_EMAIL, SITENAME, BASEURL, LOGGING_LEVEL,
57 VERIFICATION_EMAIL_SUBJECT, ACCOUNT_CREATION_SUBJECT,
58 GROUP_CREATION_SUBJECT, HELPDESK_NOTIFICATION_EMAIL_SUBJECT,
59 INVITATION_EMAIL_SUBJECT, GREETING_EMAIL_SUBJECT, FEEDBACK_EMAIL_SUBJECT,
60 EMAIL_CHANGE_EMAIL_SUBJECT
62 import astakos.im.messages as astakos_messages
64 logger = logging.getLogger(__name__)
67 def logged(func, msg):
69 def with_logging(*args, **kwargs):
74 email = request.user.email
75 except (KeyError, AttributeError), e:
77 r = func(*args, **kwargs)
79 logger.log(LOGGING_LEVEL, msg % email)
84 def login(request, user):
85 auth_login(request, user)
86 from astakos.im.models import SessionCatalog
88 session_key=request.session.session_key,
92 login = logged(login, '%s logged in.')
93 logout = logged(auth_logout, '%s logged out.')
96 def send_verification(user, template_name='im/activation_email.txt'):
98 Send email to user to verify his/her email and activate his/her account.
100 Raises SendVerificationError
102 url = '%s?auth=%s&next=%s' % (urljoin(BASEURL, reverse('activate')),
103 quote(user.auth_token),
104 quote(urljoin(BASEURL, reverse('index'))))
105 message = render_to_string(template_name, {
109 'site_name': SITENAME,
110 'support': DEFAULT_CONTACT_EMAIL})
111 sender = settings.SERVER_EMAIL
113 send_mail(_(VERIFICATION_EMAIL_SUBJECT), message, sender, [user.email])
114 except (SMTPException, socket.error) as e:
116 raise SendVerificationError()
118 msg = 'Sent activation %s' % user.email
119 logger.log(LOGGING_LEVEL, msg)
122 def send_activation(user, template_name='im/activation_email.txt'):
123 send_verification(user, template_name)
124 user.activation_sent = datetime.now()
128 def _send_admin_notification(template_name,
130 subject='alpha2 testing notification',):
132 Send notification email to settings.ADMINS.
134 Raises SendNotificationError
136 if not settings.ADMINS:
138 dictionary = dictionary or {}
139 message = render_to_string(template_name, dictionary)
140 sender = settings.SERVER_EMAIL
143 message, sender, [i[1] for i in settings.ADMINS])
144 except (SMTPException, socket.error) as e:
146 raise SendNotificationError()
148 msg = 'Sent admin notification for user %s' % dictionary
149 logger.log(LOGGING_LEVEL, msg)
152 def send_account_creation_notification(template_name, dictionary=None):
153 user = dictionary.get('user', AnonymousUser())
154 subject = _(ACCOUNT_CREATION_SUBJECT) % {'user':user.get('email', '')}
155 return _send_admin_notification(template_name, dictionary, subject=subject)
158 def send_group_creation_notification(template_name, dictionary=None):
159 group = dictionary.get('group')
162 subject = _(GROUP_CREATION_SUBJECT) % {'group':group.get('name', '')}
163 return _send_admin_notification(template_name, dictionary, subject=subject)
166 def send_helpdesk_notification(user, template_name='im/helpdesk_notification.txt'):
168 Send email to DEFAULT_CONTACT_EMAIL to notify for a new user activation.
170 Raises SendNotificationError
172 if not DEFAULT_CONTACT_EMAIL:
174 message = render_to_string(
178 sender = settings.SERVER_EMAIL
181 _(HELPDESK_NOTIFICATION_EMAIL_SUBJECT) % {'user': user.email},
182 message, sender, [DEFAULT_CONTACT_EMAIL])
183 except (SMTPException, socket.error) as e:
185 raise SendNotificationError()
187 msg = 'Sent helpdesk admin notification for %s' % user.email
188 logger.log(LOGGING_LEVEL, msg)
191 def send_invitation(invitation, template_name='im/invitation.txt'):
193 Send invitation email.
195 Raises SendInvitationError
197 subject = _(INVITATION_EMAIL_SUBJECT)
198 url = '%s?code=%d' % (urljoin(BASEURL, reverse('index')), invitation.code)
199 message = render_to_string(template_name, {
200 'invitation': invitation,
203 'site_name': SITENAME,
204 'support': DEFAULT_CONTACT_EMAIL})
205 sender = settings.SERVER_EMAIL
207 send_mail(subject, message, sender, [invitation.username])
208 except (SMTPException, socket.error) as e:
210 raise SendInvitationError()
212 msg = 'Sent invitation %s' % invitation
213 logger.log(LOGGING_LEVEL, msg)
214 invitation.inviter.invitations = max(0, invitation.inviter.invitations - 1)
215 invitation.inviter.save()
218 def send_greeting(user, email_template_name='im/welcome_email.txt'):
222 Raises SMTPException, socket.error
224 subject = _(GREETING_EMAIL_SUBJECT)
225 message = render_to_string(email_template_name, {
227 'url': urljoin(BASEURL, reverse('index')),
229 'site_name': SITENAME,
230 'support': DEFAULT_CONTACT_EMAIL})
231 sender = settings.SERVER_EMAIL
233 send_mail(subject, message, sender, [user.email])
234 except (SMTPException, socket.error) as e:
236 raise SendGreetingError()
238 msg = 'Sent greeting %s' % user.email
239 logger.log(LOGGING_LEVEL, msg)
242 def send_feedback(msg, data, user, email_template_name='im/feedback_mail.txt'):
243 subject = _(FEEDBACK_EMAIL_SUBJECT)
244 from_email = user.email
245 recipient_list = [DEFAULT_CONTACT_EMAIL]
246 content = render_to_string(email_template_name, {
251 send_mail(subject, content, from_email, recipient_list)
252 except (SMTPException, socket.error) as e:
254 raise SendFeedbackError()
256 msg = 'Sent feedback from %s' % user.email
257 logger.log(LOGGING_LEVEL, msg)
260 def send_change_email(ec, request, email_template_name='registration/email_change_email.txt'):
262 url = reverse('email_change_confirm',
263 kwargs={'activation_key': ec.activation_key})
264 url = request.build_absolute_uri(url)
265 t = loader.get_template(email_template_name)
266 c = {'url': url, 'site_name': SITENAME}
267 from_email = settings.SERVER_EMAIL
268 send_mail(_(EMAIL_CHANGE_EMAIL_SUBJECT),
269 t.render(Context(c)), from_email, [ec.new_email_address])
270 except (SMTPException, socket.error) as e:
272 raise ChangeEmailError()
274 msg = 'Sent change email for %s' % ec.user.email
275 logger.log(LOGGING_LEVEL, msg)
280 email_template_name='im/welcome_email.txt',
281 helpdesk_email_template_name='im/helpdesk_notification.txt',
285 Activates the specific user and sends email.
287 Raises SendGreetingError, ValidationError
289 user.is_active = True
291 user.email_verified = True
293 send_helpdesk_notification(user, helpdesk_email_template_name)
294 send_greeting(user, email_template_name)
297 def switch_account_to_shibboleth(user, local_user,
298 greeting_template_name='im/welcome_email.txt'):
300 provider = user.provider
301 except AttributeError:
304 if not provider == 'shibboleth':
307 local_user.provider = 'shibboleth'
308 local_user.third_party_identifier = user.third_party_identifier
310 send_greeting(local_user, greeting_template_name)
314 class SendMailError(Exception):
318 class SendAdminNotificationError(SendMailError):
320 self.message = _(astakos_messages.ADMIN_NOTIFICATION_SEND_ERR)
321 super(SendAdminNotificationError, self).__init__()
324 class SendVerificationError(SendMailError):
326 self.message = _(astakos_messages.VERIFICATION_SEND_ERR)
327 super(SendVerificationError, self).__init__()
330 class SendInvitationError(SendMailError):
332 self.message = _(astakos_messages.INVITATION_SEND_ERR)
333 super(SendInvitationError, self).__init__()
336 class SendGreetingError(SendMailError):
338 self.message = _(astakos_messages.GREETING_SEND_ERR)
339 super(SendGreetingError, self).__init__()
342 class SendFeedbackError(SendMailError):
344 self.message = _(astakos_messages.FEEDBACK_SEND_ERR)
345 super(SendFeedbackError, self).__init__()
348 class ChangeEmailError(SendMailError):
350 self.message = self.message = _(astakos_messages.CHANGE_EMAIL_SEND_ERR)
351 super(ChangeEmailError, self).__init__()
354 class SendNotificationError(SendMailError):
356 self.message = _(astakos_messages.NOTIFICATION_SEND_ERR)
357 super(SendNotificationError, self).__init__()