Skip to content

Commit

Permalink
starting a test suite (mail-in-a-box#777)
Browse files Browse the repository at this point in the history
  • Loading branch information
wsteitz committed Dec 11, 2016
1 parent 99d0afd commit 0d4a9bf
Show file tree
Hide file tree
Showing 5 changed files with 325 additions and 0 deletions.
38 changes: 38 additions & 0 deletions test/README.md
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



11 changes: 11 additions & 0 deletions test/settings.py
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)
203 changes: 203 additions & 0 deletions test/test_mail.py
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)
13 changes: 13 additions & 0 deletions test/test_ssh.py
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")
60 changes: 60 additions & 0 deletions test/test_web.py
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

0 comments on commit 0d4a9bf

Please sign in to comment.