forked from mail-in-a-box/mailinabox
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
starting a test suite (mail-in-a-box#777)
- Loading branch information
Showing
5 changed files
with
325 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
This is the mailinabox test suite. IT uses the excellent pytest module to check the functionality | ||
of the different services. | ||
|
||
Usage | ||
===== | ||
|
||
start-up a vagrant box | ||
|
||
vagrant up | ||
|
||
install pytest | ||
|
||
pip install pytest | ||
|
||
run the tests | ||
|
||
pytest | ||
|
||
to just run a subset of the tests (e.g. the ssh related ones): | ||
|
||
pytest test_ssh.py | ||
|
||
|
||
Contributing | ||
============ | ||
|
||
pytest auto-discovers all tests in this directory. The test functions need to be named "test_..." | ||
and there needs to be at least one assert statement. | ||
|
||
|
||
TODO | ||
===== | ||
* calendar | ||
* contacts | ||
* dns | ||
|
||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
import socket | ||
|
||
TEST_SERVER = '127.0.0.1' | ||
TEST_DOMAIN = 'mailinabox.lan' | ||
TEST_PORT = 2222 | ||
TEST_PASSWORD = '1234' | ||
TEST_USER = 'me' | ||
TEST_ADDRESS = TEST_USER + '@' + TEST_DOMAIN | ||
TEST_SENDER = "[email protected]" | ||
|
||
socket.setdefaulttimeout(5) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,203 @@ | ||
from time import sleep | ||
import uuid | ||
import requests | ||
import os | ||
import pytest | ||
import imaplib | ||
import poplib | ||
import smtplib | ||
from email.mime.text import MIMEText | ||
|
||
from settings import * | ||
|
||
|
||
def new_message(from_email, to_email): | ||
"""Creates an email (headers & body) with a random subject""" | ||
msg = MIMEText('Testing') | ||
msg['Subject'] = uuid.uuid4().hex[:8] | ||
msg['From'] = from_email | ||
msg['To'] = to_email | ||
return msg.as_string(), msg['subject'] | ||
|
||
|
||
def assert_imap_received(subject): | ||
"""Connects with IMAP and asserts the existence of an email, then deletes it""" | ||
|
||
sleep(3) | ||
|
||
# Login to IMAP | ||
m = imaplib.IMAP4_SSL(TEST_DOMAIN, 993) | ||
m.login(TEST_ADDRESS, TEST_PASSWORD) | ||
m.select() | ||
|
||
# Assert the message exists | ||
typ, data = m.search(None, '(SUBJECT \"{}\")'.format(subject)) | ||
assert len(data[0].split()) == 1 | ||
|
||
# Delete it & logout | ||
m.store(data[0].strip(), '+FLAGS', '\\Deleted') | ||
m.expunge() | ||
m.close() | ||
m.logout() | ||
|
||
|
||
def assert_pop3_received(subject): | ||
"""Connects with POP3S and asserts the existence of an email, then deletes it""" | ||
|
||
sleep(3) | ||
|
||
# Login to POP3 | ||
mail = poplib.POP3_SSL(TEST_DOMAIN, 995) | ||
mail.user(TEST_ADDRESS) | ||
mail.pass_(TEST_PASSWORD) | ||
|
||
# Assert the message exists | ||
num = len(mail.list()[1]) | ||
resp, text, octets = mail.retr(num) | ||
assert "Subject: " + subject in text | ||
|
||
# Delete it and log out | ||
mail.dele(num) | ||
mail.quit() | ||
|
||
|
||
def test_imap_requires_ssl(): | ||
"""IMAP without SSL is NOT available""" | ||
with pytest.raises(socket.timeout): | ||
imaplib.IMAP4(TEST_DOMAIN, 143) | ||
|
||
|
||
def test_pop3_requires_ssl(): | ||
"""POP3 without SSL is NOT available""" | ||
with pytest.raises(socket.timeout): | ||
poplib.POP3(TEST_DOMAIN, 110) | ||
|
||
|
||
def test_smtps(): | ||
"""Email sent from an MUA via SMTPS is delivered""" | ||
msg, subject = new_message(TEST_ADDRESS, TEST_ADDRESS) | ||
s = smtplib.SMTP(TEST_DOMAIN, 587) | ||
s.starttls() | ||
s.login(TEST_ADDRESS, TEST_PASSWORD) | ||
s.sendmail(TEST_ADDRESS, [TEST_ADDRESS], msg) | ||
s.quit() | ||
assert_imap_received(subject) | ||
|
||
|
||
def test_smtps_tag(): | ||
"""Email sent to address with tag is delivered""" | ||
mail_address = TEST_ADDRESS.replace("@", "+sometag@") | ||
msg, subject = new_message(TEST_ADDRESS, mail_address) | ||
s = smtplib.SMTP(TEST_DOMAIN, 587) | ||
s.starttls() | ||
s.login(TEST_ADDRESS, TEST_PASSWORD) | ||
s.sendmail(TEST_ADDRESS, [mail_address], msg) | ||
s.quit() | ||
assert_imap_received(subject) | ||
|
||
|
||
def test_smtps_requires_auth(): | ||
"""SMTPS with no authentication is rejected""" | ||
import smtplib | ||
s = smtplib.SMTP(TEST_DOMAIN, 587) | ||
s.starttls() | ||
|
||
#FIXME why does this work without login? | ||
|
||
with pytest.raises(smtplib.SMTPRecipientsRefused): | ||
s.sendmail(TEST_ADDRESS, [TEST_ADDRESS], 'Test') | ||
|
||
s.quit() | ||
|
||
|
||
def test_smtp(): | ||
"""Email sent from an MTA is delivered""" | ||
import smtplib | ||
msg, subject = new_message(TEST_SENDER, TEST_ADDRESS) | ||
s = smtplib.SMTP(TEST_DOMAIN, 25) | ||
s.sendmail(TEST_SENDER, [TEST_ADDRESS], msg) | ||
s.quit() | ||
assert_imap_received(subject) | ||
|
||
|
||
def test_smtp_tls(): | ||
"""Email sent from an MTA via SMTP+TLS is delivered""" | ||
msg, subject = new_message(TEST_SENDER, TEST_ADDRESS) | ||
s = smtplib.SMTP(TEST_DOMAIN, 25) | ||
s.starttls() | ||
s.sendmail(TEST_SENDER, [TEST_ADDRESS], msg) | ||
s.quit() | ||
assert_imap_received(subject) | ||
|
||
|
||
# FIXME | ||
#def test_smtps_headers(): | ||
# """Email sent from an MUA has DKIM and TLS headers""" | ||
# import smtplib | ||
# import imaplib | ||
# | ||
# # Send a message to admin | ||
# mail_address = "admin@" + TEST_DOMAIN | ||
# msg, subject = new_message(TEST_ADDRESS, mail_address) | ||
# s = smtplib.SMTP(TEST_DOMAIN, 587) | ||
# s.starttls() | ||
# s.login(TEST_ADDRESS, TEST_PASSWORD) | ||
# s.sendmail(TEST_ADDRESS, [mail_address], msg) | ||
# s.quit() | ||
# | ||
# sleep(3) | ||
# | ||
# # Get the message | ||
# m = imaplib.IMAP4_SSL(TEST_DOMAIN, 993) | ||
# m.login(TEST_ADDRESS, TEST_PASSWORD) | ||
# m.select() | ||
# _, res = m.search(None, '(SUBJECT \"{}\")'.format(subject)) | ||
# _, data = m.fetch(res[0], '(RFC822)') | ||
# | ||
# assert 'DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=mailinabox.lan;' in data[0][1] | ||
# | ||
# assert 'ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)' in data[0][1] | ||
# | ||
# # Clean up | ||
# m.store(res[0].strip(), '+FLAGS', '\\Deleted') | ||
# m.expunge() | ||
# m.close() | ||
# m.logout() | ||
|
||
|
||
def test_smtp_headers(): | ||
"""Email sent from an MTA via SMTP+TLS has TLS headers""" | ||
# Send a message to root | ||
msg, subject = new_message(TEST_SENDER, TEST_ADDRESS) | ||
s = smtplib.SMTP(TEST_DOMAIN, 25) | ||
s.starttls() | ||
s.sendmail(TEST_SENDER, [TEST_ADDRESS], msg) | ||
s.quit() | ||
|
||
sleep(3) | ||
|
||
# Get the message | ||
m = imaplib.IMAP4_SSL(TEST_DOMAIN, 993) | ||
m.login(TEST_ADDRESS, TEST_PASSWORD) | ||
m.select() | ||
_, res = m.search(None, '(SUBJECT \"{}\")'.format(subject)) | ||
_, data = m.fetch(res[0], '(RFC822)') | ||
|
||
assert 'ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)' in data[0][1] | ||
|
||
# Clean up | ||
m.store(res[0].strip(), '+FLAGS', '\\Deleted') | ||
m.expunge() | ||
m.close() | ||
m.logout() | ||
|
||
|
||
def test_pop3s(): | ||
"""Connects with POP3S and asserts the existance of an email, then deletes it""" | ||
msg, subject = new_message(TEST_ADDRESS, TEST_ADDRESS) | ||
s = smtplib.SMTP(TEST_DOMAIN, 587) | ||
s.starttls() | ||
s.login(TEST_ADDRESS, TEST_PASSWORD) | ||
s.sendmail(TEST_ADDRESS, [TEST_ADDRESS], msg) | ||
s.quit() | ||
assert_pop3_received(subject) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import pytest | ||
|
||
from settings import * | ||
|
||
|
||
def test_ssh_banner(): | ||
"""SSH is responding with its banner""" | ||
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) | ||
s.connect((TEST_SERVER, TEST_PORT)) | ||
data = s.recv(1024) | ||
s.close() | ||
|
||
assert data.startswith("SSH-2.0-OpenSSH") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
from time import sleep | ||
import requests | ||
import os | ||
import pytest | ||
|
||
from settings import * | ||
|
||
|
||
def test_web_hosting_http(): | ||
"""web hosting is redirecting to https""" | ||
url = 'http://' + TEST_DOMAIN | ||
r = requests.get(url, verify=False) | ||
|
||
# We should be redirected to https | ||
assert r.history[0].status_code == 301 | ||
assert r.url == url.replace("http", "https") + "/" | ||
|
||
assert r.status_code == 200 | ||
assert "this is a mail-in-a-box" in r.content | ||
|
||
|
||
def test_admin_http(): | ||
"""Admin page is redirecting to https""" | ||
url = 'http://' + TEST_DOMAIN + "/admin" | ||
r = requests.get(url, verify=False) | ||
|
||
# We should be redirected to https | ||
assert r.history[0].status_code == 301 | ||
assert r.url == url.replace("http", "https") | ||
|
||
assert r.status_code == 200 | ||
assert "Log in here for your Mail-in-a-Box control panel" in r.content | ||
|
||
|
||
def test_webmail_http(): | ||
"""Webmail is redirecting to https and displaying login page""" | ||
url = 'http://' + TEST_DOMAIN + "/mail" | ||
r = requests.get(url, verify=False) | ||
|
||
# We should be redirected to https | ||
assert r.history[0].status_code == 301 | ||
assert r.url == url.replace("http", "https") + "/" | ||
|
||
# 200 - We should be at the login page | ||
assert r.status_code == 200 | ||
assert 'Welcome to ' + TEST_DOMAIN + ' Webmail' in r.content | ||
|
||
|
||
def test_owncloud_http(): | ||
"""ownCloud is redirecting to https and displaying login page""" | ||
url = 'http://' + TEST_DOMAIN + '/cloud' | ||
r = requests.get(url, verify=False) | ||
|
||
# We should be redirected to https | ||
assert r.history[0].status_code == 301 | ||
assert r.url == url.replace("http", "https") + "/index.php/login" | ||
|
||
# 200 - We should be at the login page | ||
assert r.status_code == 200 | ||
assert 'ownCloud' in r.content |