Ticket #1028: patch-emailnotify-r1106.diff
| File patch-emailnotify-r1106.diff, 13.5 KB (added by pkou <pkou at ua.fm>, 4 years ago) |
|---|
-
wiki-default/TracIni
32 32 || default_priority || Default priority for newly created tickets || 33 33 || default_milestone || Default milestone for newly created tickets || 34 34 || default_component || Default component for newly created tickets || 35 || restrict_owner || Select ticket owner from combo box that lists all logged users || 35 36 36 37 See also: TracTicketsCustomFields 37 38 … … 44 45 || smtp_from || Sender address to use in notification emails || 45 46 || smtp_replyto || Reply-To address to use in notification emails || 46 47 || smtp_always_cc || Email address(es) to always send notifications to || 48 || always_notify_owner || Always send notifications to ticket owners || 47 49 || always_notify_reporter || Always send notifications to any address in the ''reporter'' field || 48 50 49 51 See also: TracNotification -
wiki-default/TracNotification
21 21 * '''smtp_from''': Email address to use for ''Sender''-headers in notification emails. 22 22 * '''smtp_replyto''': Email address to use for ''Reply-To''-headers in notification emails. 23 23 * '''smtp_always_cc''': List of email addresses to always send notifications to. ''Typically used to post ticket changes to a dedicated mailing list.'' 24 * '''always_notify_owner''': Always send notifications to ticket owners. 24 25 * '''always_notify_reporter''': Always send notifications to any address in the reporter field. 25 26 26 27 Either '''smtp_from''' or '''smtp_replyto''' (or both) ''must'' be set, otherwise Trac refuses to send notification mails. -
trac/db_default.py
431 431 ('ticket', 'default_priority', 'normal'), 432 432 ('ticket', 'default_milestone', ''), 433 433 ('ticket', 'default_component', 'component1'), 434 ('ticket', 'restrict_owner', 'false'), 434 435 ('header_logo', 'link', 'http://trac.edgewall.com/'), 435 436 ('header_logo', 'src', 'trac_banner.png'), 436 437 ('header_logo', 'alt', 'Trac'), … … 442 443 ('notification', 'smtp_enabled', 'false'), 443 444 ('notification', 'smtp_server', 'localhost'), 444 445 ('notification', 'smtp_always_cc', ''), 446 ('notification', 'always_notify_owner', 'false'), 445 447 ('notification', 'always_notify_reporter', 'false'), 446 448 ('notification', 'smtp_from', 'trac@localhost'), 447 449 ('notification', 'smtp_replyto', 'trac@localhost'), -
trac/Session.py
111 111 or rows[0][0] == self.req.authname): # Session is mine 112 112 for u,k,v in rows: 113 113 self.vars[k] = v 114 # For logged users: Load (new) global settings for new session 115 if self.req.authname != 'anonymous': 116 curs.execute("SELECT var_name,var_value FROM session" 117 " WHERE sid ISNULL AND username = %s", self.req.authname) 118 rows = curs.fetchall() 119 for k,v in rows: 120 if not self.vars.has_key(k): self.vars[k] = v 114 121 self.update_sess_time() 115 122 self.bake_cookie() 116 123 self.populate_hdf() … … 143 150 curs.execute('UPDATE session SET username=%s,var_value=%s' 144 151 ' WHERE sid=%s AND var_name=%s', 145 152 self.req.authname, val, self.sid, key) 153 # For logged users: Set global settings (ignore session-specific attributes) 154 if self.req.authname != 'anonymous' and \ 155 not key in ['mod_time', 'last_visit']: 156 curs.execute("DELETE FROM session WHERE sid ISNULL AND username = %s AND var_name = %s", 157 self.req.authname, key) 158 curs.execute("INSERT INTO session(sid,username,var_name,var_value)" 159 " VALUES(NULL,%s,%s,%s)", self.req.authname, key, val) 146 160 self.db.commit() 147 161 self.vars[key] = val 148 162 149 163 def create_new_sid(self): 150 164 self.sid = hex_entropy(24) 165 # For logged users: Load (existing) global settings for new session 166 if self.req.authname != 'anonymous': 167 curs = self.db.cursor() 168 curs.execute("SELECT var_name,var_value FROM session" 169 " WHERE sid ISNULL AND username = %s", self.req.authname) 170 rows = curs.fetchall() 171 for k,v in rows: 172 if not self.vars.has_key(k): self.vars[k] = v 151 173 self.bake_cookie() 152 174 self.populate_hdf() 153 175 … … 173 195 curs.execute("DELETE FROM session WHERE sid IN" 174 196 " (SELECT sid FROM session WHERE var_name='mod_time'" 175 197 " AND var_value < %i)", mintime) 198 # For logged users: Delete global settings when all sessions are removed 199 curs.execute("DELETE FROM session WHERE sid ISNULL AND username NOT IN" 200 " (SELECT username FROM session WHERE NOT sid ISNULL)") 176 201 self.db.commit() 177 202 -
trac/Notify.py
24 24 import time 25 25 import smtplib 26 26 import os.path 27 import email.Utils 27 28 28 29 import neo_cgi 29 30 import neo_cs … … 106 107 from_email = 'trac+tickets@localhost' 107 108 subject = '' 108 109 server = None 110 useremails = {} 109 111 112 def __init__(self, env, msg_template): 113 Notify.__init__(self, env, msg_template) 114 cursor = self.db.cursor() 115 cursor.execute("SELECT username,var_value FROM session WHERE sid ISNULL AND var_name = 'email'") 116 rows = cursor.fetchall() 117 for k,v in rows: self.useremails[k] = v 118 110 119 def notify(self, resid, subject): 111 120 self.subject = subject 112 121 … … 131 140 Notify.notify(self, resid) 132 141 133 142 def get_email_addresses(self, txt): 134 import email.Utils135 emails = [x[1] for x in email.Utils.getaddresses([str(txt)])]143 emails = [x[1] for x in email.Utils.getaddresses([str(txt), \ 144 self.useremails.has_key(txt) and self.useremails[txt] or ''])] 136 145 return filter(lambda x: x.find('@') > -1, emails) 137 146 138 147 def begin_send(self): … … 279 288 return txt 280 289 281 290 def parse_cc(self, txt): 282 return filter(lambda x: '@' in x, txt.replace(',', ' ').split()) 291 recipients = txt.replace(',', ' ').split() 292 additional = [] 293 for r in recipients: 294 if self.useremails.has_key(r): 295 additional.append(self.useremails[r]) 296 emails = [x[1] for x in email.Utils.getaddresses(recipients + additional)] 297 return filter(lambda x: '@' in x, emails) 283 298 284 299 def format_hdr(self): 285 300 return '#%s: %s' % (self.ticket['id'], … … 295 310 # is set to true 296 311 val = self.env.get_config('notification', 'always_notify_reporter', 'false') 297 312 notify_reporter = val.lower() in TRUE 313 val = self.env.get_config('notification', 'always_notify_owner', 'false') 314 notify_owner = val.lower() in TRUE 298 315 299 316 emails = self.prev_cc 300 317 cursor = self.db.cursor() 301 318 # Harvest email addresses from the cc field 302 cursor.execute('SELECT cc,reporter FROM ticket WHERE id=%s', tktid)319 cursor.execute('SELECT cc,reporter,owner FROM ticket WHERE id=%s', tktid) 303 320 row = cursor.fetchone() 304 321 if row: 305 322 emails += row[0] and self.parse_cc(row[0]) or [] 306 323 if notify_reporter: 307 324 emails += row[1] and self.get_email_addresses(row[1]) or [] 325 if notify_owner: 326 emails += row[2] and self.get_email_addresses(row[2]) or [] 308 327 309 328 if notify_reporter: 310 329 cursor.execute('SELECT DISTINCT author,ticket FROM ticket_change ' -
trac/Ticket.py
196 196 return log 197 197 198 198 199 def userlist_to_hdf(env, db, hdf, prefix): 200 val = env.get_config('ticket', 'restrict_owner') 201 if val.lower() in util.TRUE: 202 cursor = db.cursor() 203 cursor.execute("SELECT DISTINCT s1.username, s2.var_value " 204 "FROM session s1 " 205 "LEFT OUTER JOIN session s2 " 206 " ON (s2.sid ISNULL AND s1.username = s2.username " 207 " AND s2.var_name = 'name') " 208 "WHERE s1.sid ISNULL " 209 "ORDER BY s1.username") 210 idx = 0 211 hdf.setValue('%s.%d.name' % (prefix, idx), '') 212 idx = idx + 1 213 while 1: 214 row = cursor.fetchone() 215 if not row: 216 break 217 hdf.setValue('%s.%d.name' % (prefix, idx), row[0]) 218 if row[1]: 219 displaytext = '%s (%s)' % (row[0], row[1]) 220 hdf.setValue('%s.%d.text' % (prefix, idx), displaytext) 221 idx = idx + 1 222 223 199 224 def cmp_by_order(a, b): 200 225 try: 201 226 return int(a['order']) - int(b['order']) … … 327 352 self.req.hdf, 'newticket.milestones') 328 353 util.sql_to_hdf(self.db, 'SELECT name FROM version ORDER BY name', 329 354 self.req.hdf, 'newticket.versions') 355 userlist_to_hdf(self.env, self.db, self.req.hdf, 'newticket.userlist') 330 356 331 357 insert_custom_fields(self.env, self.req.hdf, ticket) 332 358 … … 390 416 util.sql_to_hdf(self.db, "SELECT name FROM enum WHERE type='resolution'" 391 417 " ORDER BY value", 392 418 self.req.hdf, 'enums.resolution') 419 userlist_to_hdf(self.env, self.db, self.req.hdf, 'ticket.userlist') 393 420 util.hdf_add_if_missing(self.req.hdf, 'ticket.components', ticket['component']) 394 421 util.hdf_add_if_missing(self.req.hdf, 'ticket.milestones', ticket['milestone']) 395 422 util.hdf_add_if_missing(self.req.hdf, 'ticket.versions', ticket['version']) -
templates/ticket.cs
229 229 <?cs call:hdf_select(enums.resolution, "resolve_resolution", args.resolve_resolution) ?><br /> 230 230 <?cs call:action_radio('reassign') ?> 231 231 <label for="reassign">reassign</label> 232 <label for="reassign_owner">to:</label> 233 <input type="text" id="reassign_owner" name="reassign_owner" size="40" value="<?cs 234 if:args.reassign_to ?><?cs var:args.reassign_to ?><?cs 235 else ?><?cs var:trac.authname ?><?cs /if ?>" /><?cs 232 <label for="reassign_owner">to:</label><?cs 233 if:args.reassign_to ?><?cs 234 set default_owner=args.reassign_to ?><?cs 235 else ?><?cs 236 set default_owner=trac.authname ?><?cs 237 /if ?><?cs 238 if:len(ticket.userlist) ?><?cs 239 call:hdf_select(ticket.userlist, "reassign_owner", default_owner) ?><?cs 240 else ?> 241 <input type="text" id="reassign_owner" name="reassign_owner" size="40" 242 value="<?cs var:default_owner ?>" /><?cs 243 /if ?><?cs 236 244 /if ?><?cs 237 245 if $ticket.status == "new" || $ticket.status == "assigned" || $ticket.status == "reopened" ?> 238 246 <script type="text/javascript"> -
templates/macros.cs
1 1 <?cs def:hdf_select(options, name, selected) ?> 2 2 <select size="1" id="<?cs var:name ?>" name="<?cs var:name ?>"><?cs 3 each:option = options ?><?cs 4 if option.name == $selected ?> 5 <option selected="selected"><?cs var:option.name ?></option><?cs 6 else ?> 7 <option><?cs var:option.name ?></option><?cs 8 /if ?><?cs 3 each:option = options ?> 4 <option <?cs if option.name == $selected ?>selected="selected"<?cs /if ?> 5 <?cs if option.text ?>value="<?cs var:option.name ?>"<?cs /if ?> ><?cs 6 if option.text ?><?cs 7 var:option.text ?><?cs 8 else ?><?cs 9 var:option.name ?><?cs 10 /if ?> 11 </option><?cs 9 12 /each ?> 10 13 </select><?cs 11 14 /def?> -
templates/newticket.cs
59 59 <label for="milestone">Milestone:</label><?cs 60 60 call:hdf_select(newticket.milestones, "milestone", newticket.milestone) ?><br /> 61 61 <label for="owner">Assign to:</label> 62 <?cs if:len(newticket.userlist) ?><?cs 63 call:hdf_select(newticket.userlist, "owner", newticket.owner) ?><br /><?cs 64 else ?> 62 65 <input type="text" id="owner" name="owner" size="20" value="<?cs 63 66 var:newticket.owner ?>" /><br /> 67 <?cs /if ?> 64 68 <label for="cc">Cc:</label> 65 69 <input type="text" id="cc" name="cc" size="30" value="<?cs var:newticket.cc ?>" /> 66 70 </div>
