1 |
1 |
import pytest
|
2 |
2 |
|
3 |
3 |
import asyncore
|
4 |
4 |
import dns.resolver
|
5 |
5 |
from dns import name
|
6 |
6 |
from dns.rdtypes.ANY import MX, TXT
|
7 |
7 |
import mock
|
|
8 |
import random
|
8 |
9 |
import smtplib
|
9 |
10 |
import smtpd
|
10 |
11 |
import socket
|
11 |
12 |
import threading
|
12 |
13 |
|
13 |
14 |
from django.core.exceptions import ValidationError
|
14 |
15 |
from django.utils import six
|
15 |
16 |
from django.utils.encoding import force_text
|
16 |
17 |
|
17 |
18 |
from hobo.emails.validators import validate_email_address
|
18 |
19 |
from hobo.environment.models import Variable
|
19 |
20 |
|
20 |
21 |
from test_manager import login
|
21 |
22 |
|
22 |
23 |
|
23 |
24 |
@pytest.fixture
|
24 |
|
def dns_resolver(monkeypatch):
|
|
25 |
def port_available():
|
|
26 |
errno = 0
|
|
27 |
while not errno:
|
|
28 |
port = 49152 + int(random.random() * (65535 - 49152))
|
|
29 |
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
|
30 |
errno = sock.connect_ex(('127.0.0.1', port))
|
|
31 |
sock.close()
|
|
32 |
return port
|
|
33 |
|
|
34 |
|
|
35 |
@pytest.fixture
|
|
36 |
def dns_resolver(monkeypatch, port_available):
|
25 |
37 |
def fn(value, kind):
|
26 |
38 |
if kind == 'MX':
|
27 |
39 |
mx = mock.create_autospec(MX)
|
28 |
40 |
mx.exchange = mock.create_autospec(name.Name)
|
29 |
41 |
mx.exchange.to_text = mock.MagicMock()
|
30 |
|
mx.exchange.to_text.return_value = 'localhost:10025'
|
|
42 |
mx.exchange.to_text.return_value = 'localhost:%s' % port_available
|
31 |
43 |
mx.preference = mock.create_autospec(name.Name)
|
32 |
44 |
mx.preference.to_text = mock.MagicMock()
|
33 |
45 |
mx.preference.to_text.return_value = 10
|
34 |
46 |
return [mx]
|
35 |
47 |
if kind == 'TXT':
|
36 |
48 |
txt = mock.create_autospec(TXT)
|
37 |
49 |
txt.strings = mock.create_autospec(name.Name)
|
38 |
50 |
txt.strings = mock.MagicMock()
|
... | ... | |
42 |
54 |
txt.strings = [b'v=spf1 +all']
|
43 |
55 |
elif value == 'example-invalid-spf.com':
|
44 |
56 |
txt.strings = [b'v=spf1 include:not_allowed_mx.com']
|
45 |
57 |
return [txt]
|
46 |
58 |
monkeypatch.setattr(dns.resolver, 'query', fn)
|
47 |
59 |
|
48 |
60 |
|
49 |
61 |
@pytest.fixture
|
50 |
|
def smtp_server(monkeypatch):
|
|
62 |
def smtp_server(monkeypatch, port_available):
|
51 |
63 |
class RecipientValidatingSMTPChannel(smtpd.SMTPChannel):
|
52 |
64 |
def smtp_RCPT(self, arg):
|
53 |
65 |
if six.PY2:
|
54 |
66 |
address = self._SMTPChannel__getaddr('TO:', arg)
|
55 |
67 |
domain = address.split('@')[-1]
|
56 |
68 |
else:
|
57 |
69 |
address = self._getaddr(arg)
|
58 |
70 |
domain = address[1].split('@')[-1][:-1]
|
... | ... | |
62 |
74 |
else:
|
63 |
75 |
self.push('550 No such user here')
|
64 |
76 |
|
65 |
77 |
class MailServer(smtpd.SMTPServer):
|
66 |
78 |
def handle_accept(self):
|
67 |
79 |
conn, addr = self.accept()
|
68 |
80 |
channel = RecipientValidatingSMTPChannel(self, conn, addr)
|
69 |
81 |
|
70 |
|
server = MailServer(('localhost', 10025), None)
|
|
82 |
server = MailServer(('localhost', port_available), None)
|
71 |
83 |
thread = threading.Thread(target=asyncore.loop, kwargs={'timeout': 1})
|
72 |
84 |
thread.start()
|
73 |
85 |
yield
|
74 |
86 |
server.close()
|
75 |
87 |
thread.join()
|
76 |
88 |
|
77 |
89 |
|
78 |
90 |
def test_validate_email_address_bad_query(monkeypatch):
|
79 |
|
-
|