- Timestamp:
- 4 Nov 2020, 17:52:22 (4 years ago)
- Location:
- main/waeup.kofa/trunk
- Files:
-
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
main/waeup.kofa/trunk/CHANGES.txt
r16293 r16299 4 4 1.6.1.dev0 (unreleased) 5 5 ======================= 6 7 * Implement bulk emailing. 6 8 7 9 * Make login trouble links more conspicuous. -
main/waeup.kofa/trunk/src/waeup/kofa/interfaces.py
r16059 r16299 508 508 ) 509 509 510 bcc_to = schema.Text( 511 title = _(u'Bcc to:'), 512 required = True, 513 #readonly = True, 514 ) 515 510 516 subject = schema.TextLine( 511 517 title = _(u'Subject:'), … … 519 525 title = _(u'Text:'), 520 526 required = True,) 527 521 528 522 529 class IKofaPrincipalInfo(IPrincipalInfo): -
main/waeup.kofa/trunk/src/waeup/kofa/smtp.py
r12836 r16299 160 160 161 161 def send_mail(from_name, from_addr, rcpt_name, rcpt_addrs, 162 subject, body, config=None, cc= False):162 subject, body, config=None, cc=None, bcc=None): 163 163 """Send mail. 164 164 … … 173 173 The from-address set here will be: `FROM_ADDRESS` as set above. 174 174 175 ``cc`` tells whether we want the from-address to be CCed. This is176 not the case by default as we easily act as an open relay177 otherwise.178 179 175 XXX: The hard-coded from-address should be changable or be 180 176 determined smarter by looking up a FQDN or similar. … … 184 180 rcpt_addrs = rcpt_addrs.replace(' ', '').split(',') 185 181 body_to = '' 182 from_addr = from_addr.split(',')[0] 186 183 for email in rcpt_addrs: 187 184 body_to += '%s, ' % encode_address(email, rcpt_name) … … 192 189 body["To"] = body_to.strip(', ') 193 190 if cc: 194 body["Cc"] = reply_addr 191 body["Cc"] = cc 192 if bcc: 193 body["Bcc"] = bcc 195 194 body["Reply-To"] = reply_addr 196 195 body["Subject"] = encode_header_item(subject) -
main/waeup.kofa/trunk/src/waeup/kofa/students/browser.py
r16286 r16299 36 36 from zope.security import checkPermission 37 37 from zope.securitypolicy.interfaces import IPrincipalRoleManager 38 from waeup.kofa.smtp import encode_address 38 39 from waeup.kofa.accesscodes import invalidate_accesscode, get_access_code 39 40 from waeup.kofa.accesscodes.workflow import USED … … 309 310 search_button = _('Find student(s)') 310 311 remove_button = _('Remove selected') 312 send_email_button = _('Send bulk email') 311 313 doclink = DOCLINK + '/students.html' 312 314 … … 340 342 if not self.hitlist: 341 343 self.flash(_('No student found.'), type="warning") 342 if 'remove' in form :344 if 'remove' in form or 'send_email' in form: 343 345 self.flash(_('No item selected.'), type="warning") 344 346 return … … 346 348 if isinstance(entries, basestring): 347 349 entries = [entries] 350 entries.sort() 348 351 deleted = [] 352 emails_tobesent = '' 349 353 for entry in entries: 350 354 if 'remove' in form: 351 355 del self.context[entry] 352 356 deleted.append(entry) 357 if 'send_email' in form and self.context[entry].email: 358 emails_tobesent += '%s,' % encode_address( 359 self.context[entry].email, 360 self.context[entry].student_id) 361 if 'send_email' in form and not len(emails_tobesent): 362 self.flash(_('No email address found.'), type="warning") 363 return 364 if len(emails_tobesent): 365 args = {'bcc_to': emails_tobesent.strip(',')} 366 self.redirect(self.url(self.context) + 367 '/send_bulk_email?%s' % urlencode(args)) 368 return 353 369 self.hitlist = search(query=self.searchterm, 354 370 searchtype=self.searchtype, view=self) … … 521 537 self.config.name, 522 538 data['body'],data['subject']) 539 if success: 540 self.flash(_('Your message has been sent.')) 541 else: 542 self.flash(_('An smtp server error occurred.'), type="danger") 543 return 544 545 class SendBulEmailsFormPage(ContactAdminFormPage): 546 grok.context(IStudentsContainer) 547 grok.name('send_bulk_email') 548 grok.require('waeup.manageStudent') 549 pnav = 4 550 form_fields = grok.AutoFields(IContactForm).select('subject', 'body', 'bcc_to') 551 label = _('Send bulk email') 552 553 def update(self, bcc_to=u''): 554 self.form_fields.get('bcc_to').field.default = bcc_to 555 return 556 557 @action('Send message now', style='primary') 558 def send(self, *args, **data): 559 try: 560 email = self.request.principal.email 561 except AttributeError: 562 email = self.config.email_admin 563 usertype = getattr(self.request.principal, 564 'user_type', 'system').title() 565 kofa_utils = getUtility(IKofaUtils) 566 success = kofa_utils.sendContactForm( 567 self.request.principal.title,email, 568 self.request.principal.title,email, # sent to the sender's address 569 self.request.principal.id,usertype, 570 self.config.name, 571 data['body'],data['subject'], 572 data['bcc_to']) 523 573 if success: 524 574 self.flash(_('Your message has been sent.')) -
main/waeup.kofa/trunk/src/waeup/kofa/students/browser_templates/containermanagepage.pt
r15417 r16299 75 75 <input type="submit" name="remove" 76 76 tal:attributes="value view/remove_button" class="btn btn-default" 77 onclick="return confirmPost('Are you sure?')"/> 77 onclick="return window.confirm('Are you sure?')"/> 78 <input type="submit" name="send_email" 79 tal:attributes="value view/send_email_button" class="btn btn-default" 80 onclick="return window.confirm('Are you sure?')"/> 78 81 79 82 </div> -
main/waeup.kofa/trunk/src/waeup/kofa/students/tests/test_browser.py
r16266 r16299 90 90 def setUp(self): 91 91 super(StudentsFullSetup, self).setUp() 92 self.setup_logging() 92 93 93 94 # Setup a sample site for each test … … 252 253 253 254 layer = FunctionalLayer 255 256 def setup_logging(self): 257 # setup a log-handler that catches all fake mailer output 258 self.stream = StringIO() 259 handler = logging.StreamHandler(self.stream) 260 logger = logging.getLogger('test.smtp') 261 logger.addHandler(handler) 262 logger.setLevel(logging.INFO) 263 return 264 265 def get_fake_smtp_output(self): 266 # get output generated by fake mailer 267 self.stream.flush() 268 self.stream.seek(0) 269 return self.stream.read() 254 270 255 271 def test_anonymous_access(self): … … 432 448 self.assertTrue('No student found' in self.browser.contents) 433 449 return 450 451 def test_send_bulk_emails(self): 452 self.browser.addHeader('Authorization', 'Basic mgr:mgrpw') 453 self.browser.open(self.manage_container_path) 454 self.browser.getLink("Add student").click() 455 self.assertEqual(self.browser.headers['Status'], '200 Ok') 456 self.assertEqual(self.browser.url, self.add_student_path) 457 self.browser.getControl(name="form.firstname").value = 'Bob' 458 self.browser.getControl(name="form.lastname").value = 'Tester' 459 self.browser.getControl(name="form.reg_number").value = '1234' 460 self.browser.getControl("Create student").click() 461 self.assertTrue('Student record created' in self.browser.contents) 462 self.browser.getLink("Manage").click() 463 self.browser.getControl(name="form.email").value = 'uli@uni.ng' 464 self.browser.getControl(name="form.sex").value = ['m'] 465 self.browser.getControl("Save").click() 466 # We can find Anna and Bob 467 self.browser.open(self.manage_container_path) 468 self.browser.getControl(name="searchtype").value = ['student_id'] 469 self.browser.getControl(name="searchterm").value = '*' 470 self.browser.getControl("Find student(s)").click() 471 self.assertTrue('Anna Tester' in self.browser.contents) 472 self.assertTrue('Bob Tester' in self.browser.contents) 473 # We can send bulk emails 474 ctrl = self.browser.getControl(name='entries') 475 ctrl.getControl(value='K1000000').selected = True 476 ctrl.getControl(value='K1000001').selected = True 477 self.browser.getControl("Send bulk", index=0).click() 478 self.assertTrue('K1000000 <aa@aa.ng>,K1000001 <uli@uni.ng>' 479 in self.browser.contents) 480 self.browser.getControl(name="form.subject").value = 'Test' 481 self.browser.getControl(name="form.body").value = 'Hello world' 482 self.browser.getControl("Send message").click() 483 self.assertTrue('Your message has been sent' in self.browser.contents) 484 self.assertMatches( 485 u'Sending email from no-reply@waeup.org to contact@waeup.org:\n' 486 u'Message:\n' 487 u'msg: MIME-Version: 1.0\n' 488 u'msg: Content-Type: text/plain; charset="us-ascii"\n' 489 u'msg: Content-Transfer-Encoding: 7bit\n' 490 u'msg: From: Manager <no-reply@waeup.org>\n' 491 u'msg: To: Manager <contact@waeup.org>\n' 492 u'msg: Bcc: K1000000 <aa@aa.ng>,K1000001 <uli@uni.ng>\n' 493 u'msg: Reply-To: Manager <contact@waeup.org>\n' 494 u'msg: Subject: Test\n' 495 u'msg: \n' 496 u'msg: Hello world\n' 497 u'msg: \n' 498 u'msg: ---\n' 499 u'msg: Manager (id: zope.mgr)\n' 500 u'msg: Sample University\n' 501 u'msg: \n', 502 self.get_fake_smtp_output() 503 ) 434 504 435 505 def test_add_graduated_students(self): -
main/waeup.kofa/trunk/src/waeup/kofa/tests/test_smtp.py
r14016 r16299 259 259 u'A recipient', u'recpt@example.com', 260 260 u'A subject', 261 u'This is a test mail.', 262 cc=True) 261 u'This is a test mail.',None, 262 u'A cc recipient <recpt@example.com>', 263 u'A bcc recipient <recpt@example.com>,A 2nd bcc recipient <recpt@example.com>', 264 ) 263 265 self.assertEqual(mail_id, 'fake-message-id@example.com') 264 266 self.assertEqual( … … 272 274 u'msg: From: A sender <no-reply@waeup.org>', 273 275 u'msg: To: A recipient <recpt@example.com>', 274 u'msg: Cc: A sender <sender@example.com>', 276 u'msg: Cc: A cc recipient <recpt@example.com>', 277 u'msg: Bcc: A bcc recipient <recpt@example.com>,', 278 u'msg: A 2nd bcc recipient <recpt@example.com>', 275 279 u'msg: Reply-To: A sender <sender@example.com>', 276 280 u'msg: Subject: A subject', -
main/waeup.kofa/trunk/src/waeup/kofa/utils/utils.py
r16213 r16299 35 35 def send_mail(from_name, from_addr, 36 36 rcpt_name, rcpt_addr, 37 subject, body, config): 37 subject, body, config, 38 cc=None, bcc=None): 38 39 """Wrapper for the real SMTP functionality in :mod:`waeup.kofa.smtp`. 39 40 … … 42 43 mail_id = send_mail_internally( 43 44 from_name, from_addr, rcpt_name, rcpt_addr, 44 subject, body, config )45 subject, body, config, cc, bcc) 45 46 return True 46 47 … … 247 248 248 249 def sendContactForm(self, from_name, from_addr, rcpt_name, rcpt_addr, 249 from_username, usertype, portal, body, subject): 250 from_username, usertype, portal, body, subject, 251 bcc_to=None): 250 252 """Send an email with data provided by forms. 251 253 """ … … 269 271 return send_mail( 270 272 from_name, from_addr, rcpt_name, rcpt_addr, 271 subject, body, config )273 subject, body, config, None, bcc_to) 272 274 273 275 def getUsers(self):
Note: See TracChangeset for help on using the changeset viewer.