1
1
import uuid
2
+ import traceback
2
3
3
4
from django .conf import settings
4
5
from django .db import models
5
6
from django .db .models import Q
6
7
from django .contrib .auth .models import User
8
+ from django .utils .translation import ugettext as _
9
+
10
+ from ecs .communication .mailutils import deliver_to_recipient
11
+ from ecs .users .utils import get_full_name
7
12
8
13
9
14
DELIVERY_STATES = (
13
18
("failure" , "failure" ),
14
19
)
15
20
21
+ # https://tools.ietf.org/html/rfc3834
22
+ # https://tools.ietf.org/html/rfc5436
23
+ CREATOR_CHOICES = (
24
+ ("human" , "human" ),
25
+ ("auto-self" , "auto-self" ),
26
+ ("auto-custom" , "auto-custom" ),
27
+ # rfc3834 compatible
28
+ ("auto-generated" , "auto-generated" ),
29
+ ("auto-replied" , "auto-replied" ),
30
+ ("auto-notified" , "auto-notified" ),
31
+ )
32
+
16
33
17
34
class ThreadQuerySet (models .QuerySet ):
18
35
def by_user (self , user ):
@@ -60,7 +77,10 @@ def unstar(self, user):
60
77
self .starred_by_receiver = False
61
78
self .save (update_fields = ('starred_by_sender' , 'starred_by_receiver' ))
62
79
63
- def add_message (self , user , text , rawmsg_msgid = None , rawmsg = None , reply_receiver = None ):
80
+ def add_message (self , user , text ,
81
+ reply_receiver = None , rawmsg = None ,
82
+ outgoing_msgid = None , incoming_msgid = None ,
83
+ in_reply_to = None , creator = None ):
64
84
assert user .id in (self .sender_id , self .receiver_id )
65
85
66
86
if user .id == self .sender_id :
@@ -80,14 +100,20 @@ def add_message(self, user, text, rawmsg_msgid=None, rawmsg=None, reply_receiver
80
100
else :
81
101
self .sender = receiver
82
102
103
+ if creator is None :
104
+ creator = 'human'
105
+
83
106
msg = self .messages .create (
84
107
sender = user ,
85
108
receiver = receiver ,
86
109
text = text ,
87
110
smtp_delivery_state = 'new' ,
88
111
rawmsg = rawmsg ,
89
- rawmsg_msgid = rawmsg_msgid ,
90
- reply_receiver = reply_receiver
112
+ outgoing_msgid = outgoing_msgid ,
113
+ incoming_msgid = incoming_msgid ,
114
+ reply_receiver = reply_receiver ,
115
+ in_reply_to = in_reply_to ,
116
+ creator = creator ,
91
117
)
92
118
self .last_message = msg
93
119
self .closed_by_sender = False
@@ -110,24 +136,81 @@ def message_list(self):
110
136
111
137
112
138
class Message (models .Model ):
139
+ uuid = models .UUIDField (default = uuid .uuid4 , unique = True , db_index = True )
113
140
thread = models .ForeignKey (Thread , related_name = 'messages' )
114
141
sender = models .ForeignKey (User , related_name = 'outgoing_messages' )
115
142
receiver = models .ForeignKey (User , related_name = 'incoming_messages' )
143
+ reply_receiver = models .ForeignKey (User , null = True ,
144
+ related_name = 'reply_receiver_for_messages' )
116
145
timestamp = models .DateTimeField (auto_now_add = True )
117
146
unread = models .BooleanField (default = True , db_index = True )
118
147
text = models .TextField ()
119
148
120
149
rawmsg = models .TextField (null = True )
121
- rawmsg_msgid = models .CharField (max_length = 250 , null = True , db_index = True )
150
+ outgoing_msgid = models .CharField (max_length = 250 , null = True )
151
+ incoming_msgid = models .CharField (max_length = 250 , null = True )
122
152
123
153
smtp_delivery_state = models .CharField (max_length = 7 ,
124
154
choices = DELIVERY_STATES , default = 'new' , db_index = True )
125
-
126
- uuid = models . UUIDField ( default = uuid . uuid4 , unique = True , db_index = True )
127
-
128
- reply_receiver = models . ForeignKey ( User , null = True , related_name = 'reply_receiver_for_messages ' )
155
+ in_reply_to = models . ForeignKey ( 'self' , related_name = 'is_replied_in' ,
156
+ null = True , default = None )
157
+ creator = models . CharField ( max_length = 14 ,
158
+ choices = CREATOR_CHOICES , default = 'human ' )
129
159
130
160
@property
131
161
def return_address (self ):
132
- return 'ecs-{}@{}' .format (self .uuid .hex ,
133
- settings .DOMAIN )
162
+ return 'ecs-{}@{}' .format (self .uuid .hex , settings .DOMAIN )
163
+
164
+ @property
165
+ def smtp_subject (self ):
166
+ submission = self .thread .submission
167
+ ec_number = ''
168
+ if submission :
169
+ ec_number = ' ' + submission .get_ec_number_display ()
170
+ subject = _ ('[ECS{ec_number}] {subject}.' ).format (
171
+ ec_number = ec_number , subject = self .thread .subject )
172
+ return subject
173
+
174
+ def forward_smtp (self ):
175
+ try :
176
+ forwarded = False
177
+ subject = self .smtp_subject
178
+ headers = {}
179
+
180
+ if self .creator in ("human" , "auto-self" ):
181
+ self .smtp_delivery_state = 'started'
182
+ self .save ()
183
+
184
+ if self .creator == "auto-self" :
185
+ headers .update ({"Auto-Submitted" : "auto-generated" , })
186
+ else :
187
+ headers .update ({"Auto-Submitted" : "auto-replied" , })
188
+ if self .incoming_msgid :
189
+ headers .update ({
190
+ 'In-Reply-To' : self .incoming_msgid ,
191
+ 'References' : " " .join ((self .incoming_msgid ,
192
+ self .in_reply_to .outgoing_msgid )),
193
+ })
194
+
195
+ msgid , rawmsg = deliver_to_recipient (
196
+ self .receiver .email ,
197
+ subject = subject ,
198
+ message = self .text ,
199
+ from_email = '{0} <{1}>' .format (get_full_name (self .sender ), self .return_address ),
200
+ rfc2822_headers = headers ,
201
+ )
202
+
203
+ forwarded = True
204
+ self .outgoing_msgid = msgid
205
+ # do not overwrite rawmsg on forward, if it originated from smtp
206
+ if not self .incoming_msgid :
207
+ self .rawmsg = rawmsg .as_string ()
208
+
209
+ self .smtp_delivery_state = 'success'
210
+ except :
211
+ traceback .print_exc ()
212
+ self .smtp_delivery_state = 'failure'
213
+ raise
214
+ finally :
215
+ self .save ()
216
+ return forwarded
0 commit comments