From 04d97a11e9aab8b8823107082e149aa46cde82ea Mon Sep 17 00:00:00 2001 From: Joshua Tauberer Date: Thu, 17 Apr 2014 20:17:45 -0400 Subject: [PATCH] new tests for DNS and IMAP/SMTP --- .gitignore | 1 + tests/dns.py | 58 ++++++++++++++++++++++++++++++ tests/imap.py | 20 ----------- tests/mail.py | 78 ++++++++++++++++++++++++++++++++++++++++ tests/smtp_submission.py | 22 ------------ 5 files changed, 137 insertions(+), 42 deletions(-) create mode 100755 tests/dns.py delete mode 100755 tests/imap.py create mode 100755 tests/mail.py delete mode 100755 tests/smtp_submission.py diff --git a/.gitignore b/.gitignore index b25c15b..bb6fa70 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ *~ +tests/__pycache__/ diff --git a/tests/dns.py b/tests/dns.py new file mode 100755 index 0000000..7a9b0b4 --- /dev/null +++ b/tests/dns.py @@ -0,0 +1,58 @@ +#!/usr/bin/python3 +# Test DNS configuration. +# +# tests/dns.py ipaddr hostname + +import sys, subprocess, re, difflib + +if len(sys.argv) < 3: + print("Usage: tests/dns.py ipaddress hostname") + sys.exit(1) + +ipaddr, hostname = sys.argv[1:] + +def dig(digargs): + # run dig and clean the output + response = subprocess.check_output(['dig', '@' + ipaddr] + digargs).decode('utf8') + response = re.sub('[\r\n]+', '\n', response) # remove blank lines + response = re.sub('\n;.*', '', response) # remove comments + response = response.strip() + "\n" + return response + +# call dig a few times with different parameters +digoutput = \ + dig([hostname])\ + + dig(["www." + hostname, "+noadditional", "+noauthority"]) \ + + dig(["mx", hostname, "+noadditional", "+noauthority"]) \ + + dig(["txt", hostname, "+noadditional", "+noauthority"]) \ + + dig(["txt", "mail._domainkey." + hostname, "+noadditional", "+noauthority"]) + +# normalize DKIM key +digoutput = re.sub(r"(\"p=).*(\")", r"\1__KEY__\2", digoutput) + +# construct the expected output +subs = { "ipaddr": ipaddr, "hostname": hostname } +expected = """ +{hostname}. 86400 IN A {ipaddr} +{hostname}. 86400 IN NS ns1.{hostname}. +{hostname}. 86400 IN NS ns2.{hostname}. +ns1.{hostname}. 86400 IN A {ipaddr} +ns2.{hostname}. 86400 IN A {ipaddr} +www.{hostname}. 86400 IN A {ipaddr} +{hostname}. 86400 IN MX 10 {hostname}. +{hostname}. 300 IN TXT "v=spf1 mx -all" +mail._domainkey.{hostname}. 86400 IN TXT "v=DKIM1\; k=rsa\; s=email\; " "p=__KEY__" +""".format(**subs).strip() + "\n" + +# Show a diff if there are any changes +has_diff = False +def split(s): return [line+"\n" for line in s.split("\n")] +for line in difflib.unified_diff(split(expected), split(digoutput), fromfile='expected DNS settings', tofile='output from dig'): + sys.stdout.write(line) + has_diff = True + +if not has_diff: + print("DNS is OK.") + sys.exit(0) + +sys.exit(1) diff --git a/tests/imap.py b/tests/imap.py deleted file mode 100755 index 167a1b5..0000000 --- a/tests/imap.py +++ /dev/null @@ -1,20 +0,0 @@ -#!/usr/bin/python3 -import imaplib, sys - -if len(sys.argv) < 3: - print("Usage: tests/imap.py host username password") - sys.exit(1) - -host, username, pw = sys.argv[1:4] - -M = imaplib.IMAP4_SSL(host) -M.login(username, pw) -print("Login successful.") -M.select() -typ, data = M.search(None, 'ALL') -for num in data[0].split(): - typ, data = M.fetch(num, '(RFC822)') - print('Message %s\n%s\n' % (num, data[0][1])) -M.close() -M.logout() - diff --git a/tests/mail.py b/tests/mail.py new file mode 100755 index 0000000..1141f5b --- /dev/null +++ b/tests/mail.py @@ -0,0 +1,78 @@ +#!/usr/bin/python3 +# Tests sending and receiving mail by sending a test message to yourself. + +import sys, imaplib, smtplib, uuid, time, dkim + +if len(sys.argv) < 3: + print("Usage: tests/mail.py hostname emailaddress password") + sys.exit(1) + +host, emailaddress, pw = sys.argv[1:4] + +# Attempt to login with IMAP. Our setup uses email addresses +# as IMAP/SMTP usernames. +M = imaplib.IMAP4_SSL(host) +M.login(emailaddress, pw) +M.select() +print("IMAP login is OK.") + +# Attempt to send a mail to ourself. +mailsubject = "Mail-in-a-Box Automated Test Message " + uuid.uuid4().hex +emailto = emailaddress +msg = """From: {emailaddress} +To: {emailto} +Subject: {subject} + +This is a test message. It should be automatically deleted by the test script.""".format( + emailaddress=emailaddress, + emailto=emailto, + subject=mailsubject, + ) +server = smtplib.SMTP(host, 587) +#server.set_debuglevel(1) +server.starttls() +server.login(emailaddress, pw) +server.sendmail(emailaddress, [emailto], msg) +server.quit() +print("SMTP submission is OK.") + +while True: + # Wait so the message can propagate to the inbox. + time.sleep(10) + + # Read the subject lines of all of the emails in the inbox + # to find our test message, and then delete it. + found = False + typ, data = M.search(None, 'ALL') + for num in data[0].split(): + typ, data = M.fetch(num, '(BODY[HEADER.FIELDS (SUBJECT)])') + imapsubjectline = data[0][1].strip().decode("utf8") + if imapsubjectline == "Subject: " + mailsubject: + # We found our test message. + found = True + + # To test DKIM, download the whole mssage body. Unfortunately, + # pydkim doesn't actually work. + # You must 'sudo apt-get install python3-dkim python3-dnspython' first. + #typ, msgdata = M.fetch(num, '(RFC822)') + #msg = msgdata[0][1] + #if dkim.verify(msg): + # print("DKIM signature on the test message is OK (verified).") + #else: + # print("DKIM signature on the test message failed verification.") + + # Delete the test message. + M.store(num, '+FLAGS', '\\Deleted') + M.expunge() + + break + + if found: + break + + print("Test message not present in the inbox yet...") + +M.close() +M.logout() + +print("Test message sent & received successfully.") diff --git a/tests/smtp_submission.py b/tests/smtp_submission.py deleted file mode 100755 index e2cf455..0000000 --- a/tests/smtp_submission.py +++ /dev/null @@ -1,22 +0,0 @@ -#!/usr/bin/python3 -import smtplib, sys - -if len(sys.argv) < 3: - print("Usage: tests/smtp_submission.py host email.from pw email.to") - sys.exit(1) - -host, fromaddr, pw, toaddr = sys.argv[1:5] -msg = """From: %s -To: %s -Subject: SMTP server test - -This is a test message.""" % (fromaddr, toaddr) - -server = smtplib.SMTP(host, 587) -server.set_debuglevel(1) -server.starttls() -server.login(fromaddr, pw) -server.sendmail(fromaddr, [toaddr], msg) -server.quit() - -