def test_date(self): """Date format compliance (RFC822) we do not support 'military' format""" date_str = r"^((?P<day>\w{3}),\s*)*(?P<dm>\d{2})\s+" \ r"(?P<month>\w{3})\s+(?P<year>\d{4})\s+" \ r"(?P<hour>\d{2}):(?P<min>[0-5][0-9])" \ r"(:(?P<sec>[0-5][0-9]))*\s" \ r"((?P<tz>\w{2,3})|(?P<offset>[+\-]\d{4}))$" date_re = re.compile(date_str) # python time module does not detect incorrect time values days = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'] months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', \ 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'] tz = [ 'UT', 'GMT', 'EST', 'EDT', 'CST', 'CDT', 'MST', 'MDT', 'PST', 'PDT' ] ticket = Ticket(self.env) ticket['reporter'] = '"Joe User" <*****@*****.**>' ticket['summary'] = 'This is a summary' ticket.insert() tn = TicketNotifyEmail(self.env) tn.notify(ticket, newticket=True) message = notifysuite.smtpd.get_message() (headers, body) = parse_smtp_message(message) self.failIf('Date' not in headers) mo = date_re.match(headers['Date']) self.failIf(not mo) if mo.group('day'): self.failIf(mo.group('day') not in days) self.failIf(int(mo.group('dm')) not in range(1, 32)) self.failIf(mo.group('month') not in months) self.failIf(int(mo.group('hour')) not in range(0, 24)) if mo.group('tz'): self.failIf(mo.group('tz') not in tz)
def _test_short_login(enabled): ticket = Ticket(self.env) ticket["reporter"] = "joeuser" ticket["summary"] = "This is a summary" ticket.insert() # Be sure that at least one email address is valid, so that we # send a notification even if other addresses are not valid self.env.config.set("notification", "smtp_always_cc", "*****@*****.**") if enabled: self.env.config.set("notification", "use_short_addr", "true") tn = TicketNotifyEmail(self.env) tn.notify(ticket, newticket=True) message = notifysuite.smtpd.get_message() (headers, body) = parse_smtp_message(message) # Msg should not have a 'To' header if not enabled: self.failIf("To" in headers) else: tolist = [addr.strip() for addr in headers["To"].split(",")] # Msg should have a 'Cc' field self.failIf("Cc" not in headers) cclist = [addr.strip() for addr in headers["Cc"].split(",")] if enabled: # Msg should be delivered to the reporter self.failIf(ticket["reporter"] not in tolist) else: # Msg should not be delivered to joeuser self.failIf(ticket["reporter"] in cclist) # Msg should still be delivered to the always_cc list self.failIf(self.env.config.get("notification", "smtp_always_cc") not in cclist)
def _validate_mimebody(self, mime, ticket, newtk): """Body of a ticket notification message""" (mime_decoder, mime_name, mime_charset) = mime tn = TicketNotifyEmail(self.env) tn.notify(ticket, newticket=newtk) message = notifysuite.smtpd.get_message() (headers, body) = parse_smtp_message(message) self.failIf('MIME-Version' not in headers) self.failIf('Content-Type' not in headers) self.failIf('Content-Transfer-Encoding' not in headers) self.failIf(not re.compile(r"1.\d").match(headers['MIME-Version'])) type_re = re.compile(r'^text/plain;\scharset="([\w\-\d]+)"$') charset = type_re.match(headers['Content-Type']) self.failIf(not charset) charset = charset.group(1) self.assertEqual(charset, mime_charset) self.assertEqual(headers['Content-Transfer-Encoding'], mime_name) # checks the width of each body line for line in body.splitlines(): self.failIf(len(line) > MAXBODYWIDTH) # attempts to decode the body, following the specified MIME endoding # and charset try: if mime_decoder: body = mime_decoder.decodestring(body) body = unicode(body, charset) except Exception, e: raise AssertionError, e
def test_send_mail(self): dir = resource_filename(__name__, os.path.join('..', 'htdocs')) files = [os.path.join(dir, f) for f in os.listdir(dir)] resources = [] parent = Resource('repository', '') for f in files: res = Resource('source', f, parent=parent) resources.append(res) subjects = ('Re: åäö', u'Re: åäö', 'Re: ascii', ) bodies = ('Here you gö (Här får du)', u'Here you gö (Här får du)', 'Ascii body', ) for subject in subjects: subject = to_unicode(subject) for body in bodies: body = to_unicode(body) mail = self.sharesys.send_as_email("anonymous", (u'Pöntus Enmärk', '*****@*****.**'), [(u'Pontus Enmark', '*****@*****.**'), (u'Pöntus Enmärk', '*****@*****.**')], subject, body, *resources) headers, sent_body = parse_smtp_message(self.server.get_message()) assert 'utf-8' in sent_body.split('\n')[2] assert subject == headers['Subject'], headers assert os.path.basename(files[0]) in sent_body
def test_ignore_domains(self): """Non-SMTP domain exclusion""" self.env.config.set('notification', 'ignore_domains', 'example.com, example.org') self.env.known_users = \ [('*****@*****.**', 'No Email', ''), ('*****@*****.**', 'With Email', '*****@*****.**')] ticket = Ticket(self.env) ticket['reporter'] = '*****@*****.**' ticket['owner'] = '*****@*****.**' ticket['summary'] = 'This is a summary' ticket.insert() tn = TicketNotifyEmail(self.env) tn.notify(ticket, newticket=True) message = notifysuite.smtpd.get_message() (headers, body) = parse_smtp_message(message) # Msg should always have a 'To' field self.failIf('To' not in headers) tolist = [addr.strip() for addr in headers['To'].split(',')] # 'To' list should not contain addresses with non-SMTP domains self.failIf('*****@*****.**' in tolist) self.failIf('*****@*****.**' in tolist) # 'To' list should have been resolved to the actual email address self.failIf('*****@*****.**' not in tolist) self.failIf(len(tolist) != 1)
def test_ignore_domains(self): """Non-SMTP domain exclusion""" self.env.config.set("notification", "ignore_domains", "example.com, example.org") self.env.known_users = [ ("*****@*****.**", "No Email", ""), ("*****@*****.**", "With Email", "*****@*****.**"), ] ticket = Ticket(self.env) ticket["reporter"] = "*****@*****.**" ticket["owner"] = "*****@*****.**" ticket["summary"] = "This is a summary" ticket.insert() tn = TicketNotifyEmail(self.env) tn.notify(ticket, newticket=True) message = notifysuite.smtpd.get_message() (headers, body) = parse_smtp_message(message) # Msg should always have a 'To' field self.failIf("To" not in headers) tolist = [addr.strip() for addr in headers["To"].split(",")] # 'To' list should not contain addresses with non-SMTP domains self.failIf("*****@*****.**" in tolist) self.failIf("*****@*****.**" in tolist) # 'To' list should have been resolved to the actual email address self.failIf("*****@*****.**" not in tolist) self.failIf(len(tolist) != 1)
def _test_updater(disable): if disable: self.env.config.set('notification','always_notify_updater', 'false') ticket = Ticket(self.env) ticket['reporter'] = '*****@*****.**' ticket['summary'] = u'This is a súmmäry' ticket['cc'] = '*****@*****.**' ticket.insert() ticket['component'] = 'dummy' now = time.time() ticket.save_changes('*****@*****.**', 'This is a change', when=now) tn = TicketNotifyEmail(self.env) tn.notify(ticket, newticket=False, modtime=now) message = notifysuite.smtpd.get_message() (headers, body) = parse_smtp_message(message) # checks for header existence self.failIf(not headers) # checks for updater in the 'To' recipient list self.failIf('To' not in headers) tolist = [addr.strip() for addr in headers['To'].split(',')] if disable: self.failIf('*****@*****.**' in tolist) else: self.failIf('*****@*****.**' not in tolist)
def test_email_map(self): """Login-to-email mapping""" self.env.config.set('notification', 'always_notify_owner', 'true') self.env.config.set('notification', 'always_notify_reporter', 'true') self.env.config.set('notification', 'smtp_always_cc', '*****@*****.**') self.env.known_users = [ ('joeuser', 'Joe User', '*****@*****.**'), ('jim@domain', 'Jim User', '*****@*****.**') ] ticket = Ticket(self.env) ticket['reporter'] = 'joeuser' ticket['owner'] = 'jim@domain' ticket['summary'] = 'This is a summary' ticket.insert() tn = TicketNotifyEmail(self.env) tn.notify(ticket, newticket=True) message = notifysuite.smtpd.get_message() (headers, body) = parse_smtp_message(message) # Msg should always have a 'To' field self.failIf('To' not in headers) tolist = [addr.strip() for addr in headers['To'].split(',')] # 'To' list should have been resolved to the real email address self.failIf('*****@*****.**' not in tolist) self.failIf('*****@*****.**' not in tolist) self.failIf('joeuser' in tolist) self.failIf('jim@domain' in tolist)
def _test_default_domain(enabled): self.env.config.set('notification', 'always_notify_owner', 'false') self.env.config.set('notification', 'always_notify_reporter', 'false') self.env.config.set('notification', 'smtp_always_cc', '') ticket = Ticket(self.env) ticket['cc'] = 'joenodom, [email protected]' ticket['summary'] = 'This is a summary' ticket.insert() # Be sure that at least one email address is valid, so that we # send a notification even if other addresses are not valid self.env.config.set('notification', 'smtp_always_cc', '*****@*****.**') if enabled: self.env.config.set('notification', 'smtp_default_domain', 'example.org') tn = TicketNotifyEmail(self.env) tn.notify(ticket, newticket=True) message = notifysuite.smtpd.get_message() (headers, body) = parse_smtp_message(message) # Msg should always have a 'Cc' field self.failIf('Cc' not in headers) cclist = [addr.strip() for addr in headers['Cc'].split(',')] self.failIf('*****@*****.**' not in cclist) self.failIf('*****@*****.**' not in cclist) if not enabled: self.failIf(len(cclist) != 2) self.failIf('joenodom' in cclist) else: self.failIf(len(cclist) != 3) self.failIf('*****@*****.**' not in cclist)
def _test_short_login(enabled): ticket = Ticket(self.env) ticket['reporter'] = 'joeuser' ticket['summary'] = 'This is a summary' ticket.insert() # Be sure that at least one email address is valid, so that we # send a notification even if other addresses are not valid self.env.config.set('notification', 'smtp_always_cc', '*****@*****.**') if enabled: self.env.config.set('notification', 'use_short_addr', 'true') tn = TicketNotifyEmail(self.env) tn.notify(ticket, newticket=True) message = notifysuite.smtpd.get_message() (headers, body) = parse_smtp_message(message) # Msg should not have a 'To' header if not enabled: self.failIf('To' in headers) else: tolist = [addr.strip() for addr in headers['To'].split(',')] # Msg should have a 'Cc' field self.failIf('Cc' not in headers) cclist = [addr.strip() for addr in headers['Cc'].split(',')] if enabled: # Msg should be delivered to the reporter self.failIf(ticket['reporter'] not in tolist) else: # Msg should not be delivered to joeuser self.failIf(ticket['reporter'] in cclist) # Msg should still be delivered to the always_cc list self.failIf( self.env.config.get('notification', 'smtp_always_cc') not in cclist)
def _test_updater(disable): if disable: self.env.config.set('notification', 'always_notify_updater', 'false') ticket = Ticket(self.env) ticket['reporter'] = '*****@*****.**' ticket['summary'] = u'This is a súmmäry' ticket['cc'] = '*****@*****.**' ticket.insert() ticket['component'] = 'dummy' now = datetime.now(utc) ticket.save_changes('*****@*****.**', 'This is a change', when=now) tn = TicketNotifyEmail(self.env) tn.notify(ticket, newticket=False, modtime=now) message = notifysuite.smtpd.get_message() (headers, body) = parse_smtp_message(message) # checks for header existence self.failIf(not headers) # checks for updater in the 'To' recipient list self.failIf('To' not in headers) tolist = [addr.strip() for addr in headers['To'].split(',')] if disable: self.failIf('*****@*****.**' in tolist) else: self.failIf('*****@*****.**' not in tolist)
def test_date(self): """Date format compliance (RFC822) we do not support 'military' format""" date_str = ( r"^((?P<day>\w{3}),\s*)*(?P<dm>\d{2})\s+" r"(?P<month>\w{3})\s+(?P<year>\d{4})\s+" r"(?P<hour>\d{2}):(?P<min>[0-5][0-9])" r"(:(?P<sec>[0-5][0-9]))*\s" r"((?P<tz>\w{2,3})|(?P<offset>[+\-]\d{4}))$" ) date_re = re.compile(date_str) # python time module does not detect incorrect time values days = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"] months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"] tz = ["UT", "GMT", "EST", "EDT", "CST", "CDT", "MST", "MDT", "PST", "PDT"] ticket = Ticket(self.env) ticket["reporter"] = '"Joe User" <*****@*****.**>' ticket["summary"] = "This is a summary" ticket.insert() tn = TicketNotifyEmail(self.env) tn.notify(ticket, newticket=True) message = notifysuite.smtpd.get_message() (headers, body) = parse_smtp_message(message) self.failIf("Date" not in headers) mo = date_re.match(headers["Date"]) self.failIf(not mo) if mo.group("day"): self.failIf(mo.group("day") not in days) self.failIf(int(mo.group("dm")) not in range(1, 32)) self.failIf(mo.group("month") not in months) self.failIf(int(mo.group("hour")) not in range(0, 24)) if mo.group("tz"): self.failIf(mo.group("tz") not in tz)
def test_email_map(self): """Login-to-email mapping""" self.env.config.set("notification", "always_notify_owner", "true") self.env.config.set("notification", "always_notify_reporter", "true") self.env.config.set("notification", "smtp_always_cc", "*****@*****.**") self.env.known_users = [ ("joeuser", "Joe User", "*****@*****.**"), ("jim@domain", "Jim User", "*****@*****.**"), ] ticket = Ticket(self.env) ticket["reporter"] = "joeuser" ticket["owner"] = "jim@domain" ticket["summary"] = "This is a summary" ticket.insert() tn = TicketNotifyEmail(self.env) tn.notify(ticket, newticket=True) message = notifysuite.smtpd.get_message() (headers, body) = parse_smtp_message(message) # Msg should always have a 'To' field self.failIf("To" not in headers) tolist = [addr.strip() for addr in headers["To"].split(",")] # 'To' list should have been resolved to the real email address self.failIf("*****@*****.**" not in tolist) self.failIf("*****@*****.**" not in tolist) self.failIf("joeuser" in tolist) self.failIf("jim@domain" in tolist)
def test_date(self): """Date format compliance (RFC822) we do not support 'military' format""" date_str = r"^((?P<day>\w{3}),\s*)*(?P<dm>\d{2})\s+" \ r"(?P<month>\w{3})\s+(?P<year>200\d)\s+" \ r"(?P<hour>\d{2}):(?P<min>[0-5][0-9])" \ r"(:(?P<sec>[0-5][0-9]))*\s" \ r"((?P<tz>\w{2,3})|(?P<offset>[+\-]\d{4}))$" date_re = re.compile(date_str) # python time module does not detect incorrect time values days = ['Mon','Tue','Wed','Thu','Fri','Sat','Sun'] months = ['Jan','Feb','Mar','Apr','May','Jun', \ 'Jul','Aug','Sep','Oct','Nov','Dec'] tz = ['UT','GMT','EST','EDT','CST','CDT','MST','MDT''PST','PDT'] ticket = Ticket(self.env) ticket['reporter'] = '"Joe User" <*****@*****.**>' ticket['summary'] = 'This is a summary' ticket.insert() tn = TicketNotifyEmail(self.env) tn.notify(ticket, newticket=True) message = notifysuite.smtpd.get_message() (headers, body) = parse_smtp_message(message) self.failIf('Date' not in headers) mo = date_re.match(headers['Date']) self.failIf(not mo) if mo.group('day'): self.failIf(mo.group('day') not in days) self.failIf(int(mo.group('dm')) not in range(1,32)) self.failIf(mo.group('month') not in months) self.failIf(int(mo.group('hour')) not in range(0,24)) if mo.group('tz'): self.failIf(mo.group('tz') not in tz)
def runTest(self): """User password resets notifies admin by mail""" self._tester.logout() self._smtpd.full_reset() # Clean all previous sent emails tc.notfind('Logout') # Goto Login tc.find("Login") tc.follow("Login") # Do we have the Forgot passwd link tc.find('Forgot your password?') tc.follow('Forgot your password?') username = "******" email_addr = "foo@testenv%s.tld" % self._testenv.port reset_form_name = 'acctmgr_passwd_reset' tc.formvalue(reset_form_name, 'username', username) tc.formvalue(reset_form_name, 'email', email_addr) tc.submit() headers, body = parse_smtp_message( self._smtpd.get_message('admin@testenv%s.tld' % self._testenv.port)) self.assertEqual(headers['Subject'], '[%s] Password reset for user: %s' % ( 'testenv%s' % self._testenv.port, username)) self.assertEqual(headers['X-URL'], self._testenv.url)
def _test_short_login(enabled): ticket = Ticket(self.env) ticket['reporter'] = 'joeuser' ticket['summary'] = 'This is a summary' ticket.insert() # Be sure that at least one email address is valid, so that we # send a notification even if other addresses are not valid self.env.config.set('notification', 'smtp_always_cc', '*****@*****.**') if enabled: self.env.config.set('notification', 'use_short_addr', 'true') tn = TicketNotifyEmail(self.env) tn.notify(ticket, newticket=True) message = notifysuite.smtpd.get_message() (headers, body) = parse_smtp_message(message) # Msg should not have a 'To' header if not enabled: self.failIf('To' in headers) else: tolist = [addr.strip() for addr in headers['To'].split(',')] # Msg should have a 'Cc' field self.failIf('Cc' not in headers) cclist = [addr.strip() for addr in headers['Cc'].split(',')] if enabled: # Msg should be delivered to the reporter self.failIf(ticket['reporter'] not in tolist) else: # Msg should not be delivered to joeuser self.failIf(ticket['reporter'] in cclist) # Msg should still be delivered to the always_cc list self.failIf(self.env.config.get('notification', 'smtp_always_cc') not in cclist)
def _test_default_domain(enabled): self.env.config.set("notification", "always_notify_owner", "false") self.env.config.set("notification", "always_notify_reporter", "false") self.env.config.set("notification", "smtp_always_cc", "") ticket = Ticket(self.env) ticket["cc"] = "joenodom, [email protected]" ticket["summary"] = "This is a summary" ticket.insert() # Be sure that at least one email address is valid, so that we # send a notification even if other addresses are not valid self.env.config.set("notification", "smtp_always_cc", "*****@*****.**") if enabled: self.env.config.set("notification", "smtp_default_domain", "example.org") tn = TicketNotifyEmail(self.env) tn.notify(ticket, newticket=True) message = notifysuite.smtpd.get_message() (headers, body) = parse_smtp_message(message) # Msg should always have a 'Cc' field self.failIf("Cc" not in headers) cclist = [addr.strip() for addr in headers["Cc"].split(",")] self.failIf("*****@*****.**" not in cclist) self.failIf("*****@*****.**" not in cclist) if not enabled: self.failIf(len(cclist) != 2) self.failIf("joenodom" in cclist) else: self.failIf(len(cclist) != 3) self.failIf("*****@*****.**" not in cclist)
def runTest(self): """User password resets notifies admin by mail""" self._tester.logout() self._smtpd.full_reset() # Clean all previous sent emails tc.notfind('Logout') # Goto Login tc.find("Login") tc.follow("Login") # Do we have the Forgot passwd link tc.find('Forgot your password?') tc.follow('Forgot your password?') username = "******" email_addr = "foo@testenv%s.tld" % self._testenv.port reset_form_name = 'acctmgr_passwd_reset' tc.formvalue(reset_form_name, 'username', username) tc.formvalue(reset_form_name, 'email', email_addr) tc.submit() headers, body = parse_smtp_message( self._smtpd.get_message('admin@testenv%s.tld' % self._testenv.port)) self.assertEqual( headers['Subject'], '[%s] Password reset for user: %s' % ('testenv%s' % self._testenv.port, username)) self.assertEqual(headers['X-URL'], self._testenv.url)
def runTest(self): """Password reset sends new password to user by mail""" username = "******" email_addr = "foo@testenv%s.tld" % self._testenv.port headers, self.body = parse_smtp_message(self._smtpd.get_message(email_addr)) self.assertEqual(headers['Subject'], '[%s] Trac password reset for user: %s' % ( 'testenv%s' % self._testenv.port, username))
def runTest(self): """Password reset sends new password to user by mail""" username = "******" email_addr = "foo@testenv%s.tld" % self._testenv.port headers, self.body = parse_smtp_message( self._smtpd.get_message(email_addr)) self.assertEqual( headers['Subject'], '[%s] Trac password reset for user: %s' % ('testenv%s' % self._testenv.port, username))
def test_md5_digest(self): """MD5 digest w/ non-ASCII recipient address (#3491)""" self.env.config.set('notification', 'always_notify_owner', 'false') self.env.config.set('notification', 'always_notify_reporter', 'true') self.env.config.set('notification', 'smtp_always_cc', '') ticket = Ticket(self.env) ticket['reporter'] = u'"Jöe Usèr" <*****@*****.**>' ticket['summary'] = u'This is a summary' ticket.insert() tn = TicketNotifyEmail(self.env) tn.notify(ticket, newticket=True) message = notifysuite.smtpd.get_message() (headers, body) = parse_smtp_message(message)
def test_md5_digest(self): """MD5 digest w/ non-ASCII recipient address (#3491)""" self.env.config.set("notification", "always_notify_owner", "false") self.env.config.set("notification", "always_notify_reporter", "true") self.env.config.set("notification", "smtp_always_cc", "") ticket = Ticket(self.env) ticket["reporter"] = u'"Jöe Usèr" <*****@*****.**>' ticket["summary"] = u"This is a summary" ticket.insert() tn = TicketNotifyEmail(self.env) tn.notify(ticket, newticket=True) message = notifysuite.smtpd.get_message() (headers, body) = parse_smtp_message(message)
def runTest(self): """Delete account notifies admin""" tc.find("Logout") # We're logged-in from previous post tc.follow("Preferences") tc.follow("Account") tc.url(self._testenv.url + '/prefs/account') delete_account_form_name = 'acctmgr_delete_account' tc.formvalue(delete_account_form_name, 'password', 'foo') tc.submit() tc.find("Login") # We're logged out when we delete our account headers, _ = parse_smtp_message(self._smtpd.get_message()) self.assertEqual( headers['Subject'], '[%s] Deleted User: %s' % ('testenv%s' % self._testenv.port, 'foo'))
def runTest(self): """Delete account notifies admin""" tc.find("Logout") # We're logged-in from previous post tc.follow("Preferences") tc.follow("Account") tc.url(self._testenv.url + '/prefs/account') delete_account_form_name = 'acctmgr_delete_account' tc.formvalue(delete_account_form_name, 'password', 'foo') tc.submit() tc.find("Login") # We're logged out when we delete our account headers, _ = parse_smtp_message(self._smtpd.get_message()) self.assertEqual(headers['Subject'], '[%s] Deleted User: %s' % ( 'testenv%s' % self._testenv.port, 'foo'))
def test_multiline_header(self): """Encoded headers split into multiple lines""" self.env.config.set('notification', 'mime_encoding', 'qp') ticket = Ticket(self.env) ticket['reporter'] = '*****@*****.**' # Forces non-ascii characters ticket['summary'] = u'A_very %s súmmäry' % u' '.join(['long'] * 20) ticket.insert() tn = TicketNotifyEmail(self.env) tn.notify(ticket, newticket=True) message = notifysuite.smtpd.get_message() (headers, body) = parse_smtp_message(message) # Discards the project name & ticket number subject = headers['Subject'] summary = subject[subject.find(':') + 2:] self.failIf(ticket['summary'] != summary)
def test_multiline_header(self): """Encoded headers split into multiple lines""" self.env.config.set("notification", "mime_encoding", "qp") ticket = Ticket(self.env) ticket["reporter"] = "*****@*****.**" # Forces non-ascii characters ticket["summary"] = u"A_very %s súmmäry" % u" ".join(["long"] * 20) ticket.insert() tn = TicketNotifyEmail(self.env) tn.notify(ticket, newticket=True) message = notifysuite.smtpd.get_message() (headers, body) = parse_smtp_message(message) # Discards the project name & ticket number subject = headers["Subject"] summary = subject[subject.find(":") + 2 :] self.failIf(ticket["summary"] != summary)
def _validate_props_format(self, expected, ticket): tn = TicketNotifyEmail(self.env) tn.notify(ticket, newticket=True) message = notifysuite.smtpd.get_message() (headers, body) = parse_smtp_message(message) bodylines = body.splitlines() # Extract ticket properties delim_re = re.compile(r'^\-+\+\-+$') while not delim_re.match(bodylines[0]): bodylines.pop(0) lines = [] for line in bodylines[1:]: if delim_re.match(line): break lines.append(line) self.assertEqual(expected, '\n'.join(lines))
def test_multiline_header(self): """Encoded headers split into multiple lines""" self.env.config.set('notification','mime_encoding', 'qp') ticket = Ticket(self.env) ticket['reporter'] = '*****@*****.**' # Forces non-ascii characters ticket['summary'] = u'A_very %s súmmäry' % u' '.join(['long'] * 20) ticket.insert() tn = TicketNotifyEmail(self.env) tn.notify(ticket, newticket=True) message = notifysuite.smtpd.get_message() (headers, body) = parse_smtp_message(message) # Discards the project name & ticket number subject = headers['Subject'] summary = subject[subject.find(':')+2:] self.failIf(ticket['summary'] != summary)
def _validate_props_format(self, expected, ticket): tn = TicketNotifyEmail(self.env) tn.notify(ticket, newticket=True) message = notifysuite.smtpd.get_message() (headers, body) = parse_smtp_message(message) bodylines = body.splitlines() # Extract ticket properties delim_re = re.compile(r"^\-+\+\-+$") while not delim_re.match(bodylines[0]): bodylines.pop(0) lines = [] for line in bodylines[1:]: if delim_re.match(line): break lines.append(line) self.assertEqual(expected, "\n".join(lines))
def run_bcc_feature(public): # CC list should be private self.env.config.set('notification', 'use_public_cc', public and 'true' or 'false') self.env.config.set('notification', 'smtp_always_bcc', '*****@*****.**') ticket = Ticket(self.env) ticket['reporter'] = '"Joe User" <*****@*****.**>' ticket['summary'] = 'This is a summary' ticket.insert() tn = TicketNotifyEmail(self.env) tn.notify(ticket, newticket=True) message = notifysuite.smtpd.get_message() (headers, body) = parse_smtp_message(message) if public: # Msg should have a To list self.failIf('To' not in headers) # Extract the list of 'To' recipients from the message to = [rcpt.strip() for rcpt in headers['To'].split(',')] else: # Msg should not have a To list self.failIf('To' in headers) # Extract the list of 'To' recipients from the message to = [] # Extract the list of 'Cc' recipients from the message cc = [rcpt.strip() for rcpt in headers['Cc'].split(',')] # Extract the list of the actual SMTP recipients rcptlist = notifysuite.smtpd.get_recipients() # Build the list of the expected 'Cc' recipients ccrcpt = self.env.config.get('notification', 'smtp_always_cc') cclist = [ccr.strip() for ccr in ccrcpt.split(',')] for rcpt in cclist: # Each recipient of the 'Cc' list should appear # in the 'Cc' header self.failIf(rcpt not in cc) # Check the message has actually been sent to the recipients self.failIf(rcpt not in rcptlist) # Build the list of the expected 'Bcc' recipients bccrcpt = self.env.config.get('notification', 'smtp_always_bcc') bcclist = [bccr.strip() for bccr in bccrcpt.split(',')] for rcpt in bcclist: # Check none of the 'Bcc' recipients appears # in the 'To' header self.failIf(rcpt in to) # Check the message has actually been sent to the recipients self.failIf(rcpt not in rcptlist)
def run_bcc_feature(public): # CC list should be private self.env.config.set('notification', 'use_public_cc', 'true' if public else 'false') self.env.config.set('notification', 'smtp_always_bcc', '*****@*****.**') ticket = Ticket(self.env) ticket['reporter'] = '"Joe User" <*****@*****.**>' ticket['summary'] = 'This is a summary' ticket.insert() tn = TicketNotifyEmail(self.env) tn.notify(ticket, newticket=True) message = notifysuite.smtpd.get_message() (headers, body) = parse_smtp_message(message) if public: # Msg should have a To list self.failIf('To' not in headers) # Extract the list of 'To' recipients from the message to = [rcpt.strip() for rcpt in headers['To'].split(',')] else: # Msg should not have a To list self.failIf('To' in headers) # Extract the list of 'To' recipients from the message to = [] # Extract the list of 'Cc' recipients from the message cc = [rcpt.strip() for rcpt in headers['Cc'].split(',')] # Extract the list of the actual SMTP recipients rcptlist = notifysuite.smtpd.get_recipients() # Build the list of the expected 'Cc' recipients ccrcpt = self.env.config.get('notification', 'smtp_always_cc') cclist = [ccr.strip() for ccr in ccrcpt.split(',')] for rcpt in cclist: # Each recipient of the 'Cc' list should appear # in the 'Cc' header self.failIf(rcpt not in cc) # Check the message has actually been sent to the recipients self.failIf(rcpt not in rcptlist) # Build the list of the expected 'Bcc' recipients bccrcpt = self.env.config.get('notification', 'smtp_always_bcc') bcclist = [bccr.strip() for bccr in bccrcpt.split(',')] for rcpt in bcclist: # Check none of the 'Bcc' recipients appears # in the 'To' header self.failIf(rcpt in to) # Check the message has actually been sent to the recipients self.failIf(rcpt not in rcptlist)
def test_admit_domains(self): """SMTP domain inclusion""" self.env.config.set("notification", "admit_domains", "localdomain, server") ticket = Ticket(self.env) ticket["reporter"] = "*****@*****.**" ticket["summary"] = "This is a summary" ticket["cc"] = "joe.user@localdomain, joe.user@unknown, " "joe.user@server" ticket.insert() tn = TicketNotifyEmail(self.env) tn.notify(ticket, newticket=True) message = notifysuite.smtpd.get_message() (headers, body) = parse_smtp_message(message) # Msg should always have a 'To' field self.failIf("Cc" not in headers) cclist = [addr.strip() for addr in headers["Cc"].split(",")] # 'Cc' list should contain addresses with SMTP included domains self.failIf("joe.user@localdomain" not in cclist) self.failIf("joe.user@server" not in cclist) # 'Cc' list should not contain non-FQDN domains self.failIf("joe.user@unknown" in cclist) self.failIf(len(cclist) != 2 + 2)
def test_structure(self): """Basic SMTP message structure (headers, body)""" ticket = Ticket(self.env) ticket["reporter"] = '"Joe User" <*****@*****.**>' ticket["owner"] = "*****@*****.**" ticket["cc"] = "[email protected], [email protected], " "*****@*****.**" ticket["summary"] = "This is a summary" ticket.insert() tn = TicketNotifyEmail(self.env) tn.notify(ticket, newticket=True) message = notifysuite.smtpd.get_message() (headers, body) = parse_smtp_message(message) # checks for header existence self.failIf(not headers) # checks for body existance self.failIf(not body) # checks for expected headers self.failIf("Date" not in headers) self.failIf("Subject" not in headers) self.failIf("Message-ID" not in headers) self.failIf("From" not in headers)
def test_structure(self): """Basic SMTP message structure (headers, body)""" ticket = Ticket(self.env) ticket['reporter'] = '"Joe User" <*****@*****.**>' ticket['owner'] = '*****@*****.**' ticket['cc'] = '[email protected], [email protected], ' \ '*****@*****.**' ticket['summary'] = 'This is a summary' ticket.insert() tn = TicketNotifyEmail(self.env) tn.notify(ticket, newticket=True) message = notifysuite.smtpd.get_message() (headers, body) = parse_smtp_message(message) # checks for header existence self.failIf(not headers) # checks for body existance self.failIf(not body) # checks for expected headers self.failIf('Date' not in headers) self.failIf('Subject' not in headers) self.failIf('Message-ID' not in headers) self.failIf('From' not in headers)
def test_email_map(self): """Login-to-email mapping""" self.env.config.set('notification', 'always_notify_owner', 'false') self.env.config.set('notification', 'always_notify_reporter', 'true') self.env.config.set('notification', 'smtp_always_cc', '*****@*****.**') self.env.known_users = [('joeuser', 'Joe User', '*****@*****.**')] ticket = Ticket(self.env) ticket['reporter'] = 'joeuser' ticket['summary'] = 'This is a summary' ticket.insert() tn = TicketNotifyEmail(self.env) tn.notify(ticket, newticket=True) message = notifysuite.smtpd.get_message() (headers, body) = parse_smtp_message(message) # Msg should always have a 'To' field self.failIf('To' not in headers) tolist = [addr.strip() for addr in headers['To'].split(',')] # 'To' list should have been resolved to the real email address self.failIf('*****@*****.**' not in tolist) self.failIf('joeuser' in tolist)
def runTest(self): """User confirms his address with mailed token""" headers, body = parse_smtp_message(self._smtpd.get_message()) blines = base64.decodestring(body).splitlines() token = [l.split() for l in blines if 'Verification Token' in l][0][-1] tc.find('Logout') # User is logged in from previous test self._tester.go_to_front() tc.find('<strong>Warning:</strong> <span>Your permissions have been ' 'limited until you <a href="/verify_email">verify your email ' 'address</a></span>') tc.go(self._testenv.url + '/verify_email') reg_form_name = 'acctmgr_verify_email' tc.formvalue(reg_form_name, 'token', token) tc.submit('verify') tc.notfind('<strong>Warning:</strong> <span>Your permissions have been ' 'limited until you <a href="/verify_email">verify your email' ' address</a></span>') tc.find('Thank you for verifying your email address') self._tester.go_to_front()
def test_admit_domains(self): """SMTP domain inclusion""" self.env.config.set('notification', 'admit_domains', 'localdomain, server') ticket = Ticket(self.env) ticket['reporter'] = '*****@*****.**' ticket['summary'] = 'This is a summary' ticket['cc'] = 'joe.user@localdomain, joe.user@unknown, ' \ 'joe.user@server' ticket.insert() tn = TicketNotifyEmail(self.env) tn.notify(ticket, newticket=True) message = notifysuite.smtpd.get_message() (headers, body) = parse_smtp_message(message) # Msg should always have a 'To' field self.failIf('Cc' not in headers) cclist = [addr.strip() for addr in headers['Cc'].split(',')] # 'Cc' list should contain addresses with SMTP included domains self.failIf('joe.user@localdomain' not in cclist) self.failIf('joe.user@server' not in cclist) # 'Cc' list should not contain non-FQDN domains self.failIf('joe.user@unknown' in cclist) self.failIf(len(cclist) != 2 + 2)
def runTest(self): """User confirms his address with mailed token""" headers, body = parse_smtp_message(self._smtpd.get_message()) blines = base64.decodestring(body).splitlines() token = [l.split() for l in blines if 'Verification Token' in l][0][-1] tc.find('Logout') # User is logged in from previous test self._tester.go_to_front() tc.find('<strong>Warning:</strong> <span>Your permissions have been ' 'limited until you <a href="/verify_email">verify your email ' 'address</a></span>') tc.go(self._testenv.url + '/verify_email') reg_form_name = 'acctmgr_verify_email' tc.formvalue(reg_form_name, 'token', token) tc.submit('verify') tc.notfind( '<strong>Warning:</strong> <span>Your permissions have been ' 'limited until you <a href="/verify_email">verify your email' ' address</a></span>') tc.find('Thank you for verifying your email address') self._tester.go_to_front()
def runTest(self): """Send out notification on new account registrations""" tc.notfind('Logout') address_to_notify = 'admin@testenv%s.tld' % self._testenv.port new_username = '******' new_username_email = "foo@%s" % address_to_notify.split('@')[1] env = self._testenv.get_trac_environment() env.config.set('account-manager', 'account_changes_notify_addresses', address_to_notify) env.config.set('account-manager', 'notify_actions', 'new,change,delete') env.config.set('account-manager', 'force_passwd_change', 'true') env.config.save() self._tester.register(new_username, new_username_email) headers, body = parse_smtp_message(self._smtpd.get_message()) self.assertEqual(self._smtpd.get_recipients(), [address_to_notify]) self.assertEqual( headers['Subject'], '[%s] New user registration: %s' % ('testenv%s' % self._testenv.port, new_username)) self.assertEqual(headers['X-URL'], self._testenv.url)
def runTest(self): """Send out notification on new account registrations""" tc.notfind('Logout') address_to_notify = 'admin@testenv%s.tld' % self._testenv.port new_username = '******' new_username_email = "foo@%s" % address_to_notify.split('@')[1] env = self._testenv.get_trac_environment() env.config.set('account-manager', 'account_changes_notify_addresses', address_to_notify) env.config.set('account-manager', 'notify_actions', 'new,change,delete') env.config.set('account-manager', 'force_passwd_change', 'true') env.config.save() self._tester.register(new_username, new_username_email) headers, body = parse_smtp_message(self._smtpd.get_message()) self.assertEqual(self._smtpd.get_recipients(), [address_to_notify]) self.assertEqual(headers['Subject'], '[%s] New user registration: %s' % ( 'testenv%s' % self._testenv.port, new_username)) self.assertEqual(headers['X-URL'], self._testenv.url)
def test_admit_domains(self): """SMTP domain inclusion""" self.env.config.set('notification', 'admit_domains', 'localdomain, server') ticket = Ticket(self.env) ticket['reporter'] = '*****@*****.**' ticket['summary'] = 'This is a summary' ticket['cc'] = 'joe.user@localdomain, joe.user@unknown, ' \ 'joe.user@server' ticket.insert() tn = TicketNotifyEmail(self.env) tn.notify(ticket, newticket=True) message = notifysuite.smtpd.get_message() (headers, body) = parse_smtp_message(message) # Msg should always have a 'To' field self.failIf('Cc' not in headers) cclist = [addr.strip() for addr in headers['Cc'].split(',')] # 'Cc' list should contain addresses with SMTP included domains self.failIf('joe.user@localdomain' not in cclist) self.failIf('joe.user@server' not in cclist) # 'Cc' list should not contain non-FQDN domains self.failIf('joe.user@unknown' in cclist) self.failIf(len(cclist) != 2+2)
def _test_updater(disable): if disable: self.env.config.set("notification", "always_notify_updater", "false") ticket = Ticket(self.env) ticket["reporter"] = "*****@*****.**" ticket["summary"] = u"This is a súmmäry" ticket["cc"] = "*****@*****.**" ticket.insert() ticket["component"] = "dummy" now = datetime.now(utc) ticket.save_changes("*****@*****.**", "This is a change", when=now) tn = TicketNotifyEmail(self.env) tn.notify(ticket, newticket=False, modtime=now) message = notifysuite.smtpd.get_message() (headers, body) = parse_smtp_message(message) # checks for header existence self.failIf(not headers) # checks for updater in the 'To' recipient list self.failIf("To" not in headers) tolist = [addr.strip() for addr in headers["To"].split(",")] if disable: self.failIf("*****@*****.**" in tolist) else: self.failIf("*****@*****.**" not in tolist)
def test_from_author(self): """Using the reporter or change author as the notification sender""" self.env.config.set('notification', 'smtp_from', '*****@*****.**') self.env.config.set('notification', 'smtp_from_name', 'My Trac') self.env.config.set('notification', 'smtp_from_author', 'true') self.env.known_users = [ ('joeuser', 'Joe User', '*****@*****.**'), ('jim@domain', 'Jim User', '*****@*****.**'), ('noemail', 'No e-mail', ''), ('noname', '', '*****@*****.**') ] # Ticket creation uses the reporter ticket = Ticket(self.env) ticket['reporter'] = 'joeuser' ticket['summary'] = 'This is a summary' ticket.insert() tn = TicketNotifyEmail(self.env) tn.notify(ticket, newticket=True) message = notifysuite.smtpd.get_message() (headers, body) = parse_smtp_message(message) self.assertEqual('"Joe User" <*****@*****.**>', headers['From']) # Ticket change uses the change author ticket['summary'] = 'Modified summary' ticket.save_changes('jim@domain', 'Made some changes') tn = TicketNotifyEmail(self.env) tn.notify(ticket, newticket=False, modtime=ticket['changetime']) message = notifysuite.smtpd.get_message() (headers, body) = parse_smtp_message(message) self.assertEqual('"Jim User" <*****@*****.**>', headers['From']) # Known author without name uses e-mail address only ticket['summary'] = 'Final summary' ticket.save_changes('noname', 'Final changes') tn = TicketNotifyEmail(self.env) tn.notify(ticket, newticket=False, modtime=ticket['changetime']) message = notifysuite.smtpd.get_message() (headers, body) = parse_smtp_message(message) self.assertEqual('*****@*****.**', headers['From']) # Known author without e-mail uses smtp_from and smtp_from_name ticket['summary'] = 'Other summary' ticket.save_changes('noemail', 'More changes') tn = TicketNotifyEmail(self.env) tn.notify(ticket, newticket=False, modtime=ticket['changetime']) message = notifysuite.smtpd.get_message() (headers, body) = parse_smtp_message(message) self.assertEqual('"My Trac" <*****@*****.**>', headers['From']) # Unknown author with name and e-mail address ticket['summary'] = 'Some summary' ticket.save_changes('Test User <*****@*****.**>', 'Some changes') tn = TicketNotifyEmail(self.env) tn.notify(ticket, newticket=False, modtime=ticket['changetime']) message = notifysuite.smtpd.get_message() (headers, body) = parse_smtp_message(message) self.assertEqual('"Test User" <*****@*****.**>', headers['From']) # Unknown author with e-mail address only ticket['summary'] = 'Some summary' ticket.save_changes('*****@*****.**', 'Some changes') tn = TicketNotifyEmail(self.env) tn.notify(ticket, newticket=False, modtime=ticket['changetime']) message = notifysuite.smtpd.get_message() (headers, body) = parse_smtp_message(message) self.assertEqual('*****@*****.**', headers['From']) # Unknown author uses smtp_from and smtp_from_name ticket['summary'] = 'Better summary' ticket.save_changes('unknown', 'Made more changes') tn = TicketNotifyEmail(self.env) tn.notify(ticket, newticket=False, modtime=ticket['changetime']) message = notifysuite.smtpd.get_message() (headers, body) = parse_smtp_message(message) self.assertEqual('"My Trac" <*****@*****.**>', headers['From'])
def test_from_author(self): """Using the reporter or change author as the notification sender""" self.env.config.set("notification", "smtp_from", "*****@*****.**") self.env.config.set("notification", "smtp_from_name", "My Trac") self.env.config.set("notification", "smtp_from_author", "true") self.env.known_users = [ ("joeuser", "Joe User", "*****@*****.**"), ("jim@domain", "Jim User", "*****@*****.**"), ("noemail", "No e-mail", ""), ("noname", "", "*****@*****.**"), ] # Ticket creation uses the reporter ticket = Ticket(self.env) ticket["reporter"] = "joeuser" ticket["summary"] = "This is a summary" ticket.insert() tn = TicketNotifyEmail(self.env) tn.notify(ticket, newticket=True) message = notifysuite.smtpd.get_message() (headers, body) = parse_smtp_message(message) self.assertEqual('"Joe User" <*****@*****.**>', headers["From"]) # Ticket change uses the change author ticket["summary"] = "Modified summary" ticket.save_changes("jim@domain", "Made some changes") tn = TicketNotifyEmail(self.env) tn.notify(ticket, newticket=False, modtime=ticket["changetime"]) message = notifysuite.smtpd.get_message() (headers, body) = parse_smtp_message(message) self.assertEqual('"Jim User" <*****@*****.**>', headers["From"]) # Known author without name uses e-mail address only ticket["summary"] = "Final summary" ticket.save_changes("noname", "Final changes") tn = TicketNotifyEmail(self.env) tn.notify(ticket, newticket=False, modtime=ticket["changetime"]) message = notifysuite.smtpd.get_message() (headers, body) = parse_smtp_message(message) self.assertEqual("*****@*****.**", headers["From"]) # Known author without e-mail uses smtp_from and smtp_from_name ticket["summary"] = "Other summary" ticket.save_changes("noemail", "More changes") tn = TicketNotifyEmail(self.env) tn.notify(ticket, newticket=False, modtime=ticket["changetime"]) message = notifysuite.smtpd.get_message() (headers, body) = parse_smtp_message(message) self.assertEqual('"My Trac" <*****@*****.**>', headers["From"]) # Unknown author with name and e-mail address ticket["summary"] = "Some summary" ticket.save_changes("Test User <*****@*****.**>", "Some changes") tn = TicketNotifyEmail(self.env) tn.notify(ticket, newticket=False, modtime=ticket["changetime"]) message = notifysuite.smtpd.get_message() (headers, body) = parse_smtp_message(message) self.assertEqual('"Test User" <*****@*****.**>', headers["From"]) # Unknown author with e-mail address only ticket["summary"] = "Some summary" ticket.save_changes("*****@*****.**", "Some changes") tn = TicketNotifyEmail(self.env) tn.notify(ticket, newticket=False, modtime=ticket["changetime"]) message = notifysuite.smtpd.get_message() (headers, body) = parse_smtp_message(message) self.assertEqual("*****@*****.**", headers["From"]) # Unknown author uses smtp_from and smtp_from_name ticket["summary"] = "Better summary" ticket.save_changes("unknown", "Made more changes") tn = TicketNotifyEmail(self.env) tn.notify(ticket, newticket=False, modtime=ticket["changetime"]) message = notifysuite.smtpd.get_message() (headers, body) = parse_smtp_message(message) self.assertEqual('"My Trac" <*****@*****.**>', headers["From"])