starting a test suite (#777)
This commit is contained in:
parent
2c86fa3755
commit
670c96b0b5
|
@ -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
|
||||
|
||||
|
||||
|
|
@ -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 = "someone@example.com"
|
||||
|
||||
socket.setdefaulttimeout(5)
|
|
@ -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)
|
|
@ -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")
|
|
@ -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
|
Loading…
Reference in New Issue