source: main/trunk/openPLM/plmapp/mail.py @ 473

Revision 473, 6.2 KB checked in by pcosquer, 9 years ago (diff)

mail: add a missing call to convert_users

Line 
1############################################################################
2# openPLM - open source PLM
3# Copyright 2010 Philippe Joulaud, Pierre Cosquer
4#
5# This file is part of openPLM.
6#
7#    openPLM is free software: you can redistribute it and/or modify
8#    it under the terms of the GNU General Public License as published by
9#    the Free Software Foundation, either version 3 of the License, or
10#    (at your option) any later version.
11#
12#    openPLM is distributed in the hope that it will be useful,
13#    but WITHOUT ANY WARRANTY; without even the implied warranty of
14#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15#    GNU General Public License for more details.
16#
17#    You should have received a copy of the GNU General Public License
18#    along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
19#
20# Contact :
21#    Philippe Joulaud : ninoo.fr@gmail.com
22#    Pierre Cosquer : pierre.cosquer@insa-rennes.fr
23################################################################################
24
25"""
26This module contains a function :func:`send_mail` which can be used to notify
27users about a changement in a :class:`.PLMObject`.
28"""
29from collections import Iterable, Mapping
30
31import kjbuckets
32
33from django.conf import settings
34from django.core.mail import EmailMultiAlternatives
35from django.db.models import Model
36from django.template.loader import render_to_string
37from django.contrib.contenttypes.models import ContentType
38from django.contrib.sites.models import Site
39from celery.task import task
40
41from openPLM.plmapp.models import User, DelegationLink, ROLE_OWNER
42
43
44def get_recipients(obj, roles, users):
45    recipients = set(users)
46    if hasattr(obj, "plmobjectuserlink_plmobject"):
47        manager = obj.plmobjectuserlink_plmobject
48        for role in roles:
49            users = manager.filter(role__contains=role).values_list("user", flat=True)
50            recipients.update(users)
51            links = DelegationLink.objects.filter(role__contains=role)\
52                        .values_list("delegator", "delegatee")
53            gr = kjbuckets.kjGraph(tuple(links))
54            for u in users:
55                recipients.update(gr.reachable(u).items())
56    elif ROLE_OWNER:
57        if hasattr(obj, "owner"):
58            recipients.add(obj.owner.id)
59        elif isinstance(obj, User):
60            recipients.add(obj.id)
61    return recipients
62
63def convert_users(users):
64    if users:
65        r = iter(users).next()
66        if hasattr(r, "id"):
67            users = [x.id for x in users]
68    return users
69
70class CT(object):
71    def __init__(self, ct_id, pk):
72        self.ct_id = ct_id
73        self.pk = pk
74
75    @classmethod
76    def from_object(cls, obj):
77        return cls(ContentType.objects.get_for_model(obj).id, obj.pk)
78
79    def get_object(self):
80        ct = ContentType.objects.get_for_id(self.ct_id)
81        return ct.get_object_for_this_type(pk=self.pk)
82
83
84def serialize(obj):
85    if isinstance(obj, basestring):
86        return obj
87    if isinstance(obj, Model):
88        return CT.from_object(obj)
89    elif isinstance(obj, Mapping):
90        new_ctx = {}
91        for key, value in obj.iteritems():
92            new_ctx[key] = serialize(value)
93        return new_ctx
94    elif isinstance(obj, Iterable):
95        return [serialize(o) for o in obj]
96    return obj
97
98def unserialize(obj):
99    if isinstance(obj, basestring):
100        return obj
101    if isinstance(obj, CT):
102        return obj.get_object()
103    elif isinstance(obj, Mapping):
104        new_ctx = {}
105        for key, value in obj.iteritems():
106            new_ctx[key] = unserialize(value)
107        return new_ctx
108    elif isinstance(obj, Iterable):
109        return [unserialize(o) for o in obj]
110    return obj
111
112@task(ignore_result=True)
113def do_send_histories_mail(plmobject, roles, last_action, histories, user, blacklist=(),
114              users=(), template="mails/history"):
115    """
116    Sends a mail to users who have role *role* for *plmobject*.
117
118    :param plmobject: object which was modified
119    :type plmobject: :class:`.PLMObject`
120    :param str roles: list of roles of the users who should be notified
121    :param str last_action: type of modification
122    :param str histories: list of :class:`.AbstractHistory`
123    :param user: user who made the modification
124    :type user: :class:`~django.contrib.auth.models.User`
125    :param blacklist: list of emails whose no mail should be sent (empty by default).
126
127    .. note::
128
129        This function fails silently if it can not send the mail.
130        The mail is sent in a separated thread.
131    """
132   
133    plmobject = unserialize(plmobject)
134    user = unserialize(user)
135    subject = "[PLM] " + unicode(plmobject)
136    recipients = get_recipients(plmobject, roles, users)
137   
138    if recipients:
139        ctx = {
140                "last_action" : last_action,
141                "histories" : histories,
142                "plmobject" : plmobject,
143                "user" : user,
144            }
145        do_send_mail(subject, recipients, ctx, template, blacklist)
146
147@task(ignore_result=True)
148def do_send_mail(subject, recipients, ctx, template, blacklist=()):
149    if recipients:
150        ctx = unserialize(ctx)
151        emails = User.objects.filter(id__in=recipients).exclude(email="")\
152                        .values_list("email", flat=True)
153        emails = set(emails) - set(blacklist)
154        ctx["site"] = Site.objects.get_current()
155        html_content = render_to_string(template + ".htm", ctx)
156        message = render_to_string(template + ".txt", ctx)
157        msg = EmailMultiAlternatives(subject, message, settings.EMAIL_OPENPLM,
158            emails)
159        msg.attach_alternative(html_content, "text/html")
160        msg.send(fail_silently=True)
161
162def send_mail(subject, recipients, ctx, template, blacklist=()):
163    ctx = serialize(ctx)
164    do_send_mail.delay(subject, convert_users(recipients),
165            ctx, template, blacklist)
166
167def send_histories_mail(plmobject, roles, last_action, histories, user, blacklist=(),
168              users=(), template="mails/history"):
169    if hasattr(plmobject, "object"):
170        plmobject = plmobject.object
171    plmobject = CT.from_object(plmobject)
172    histories = serialize(histories)
173    user = CT.from_object(user)
174    do_send_histories_mail.delay(plmobject, roles, last_action, histories, user, blacklist,
175              convert_users(users), template)
176
177
Note: See TracBrowser for help on using the repository browser.