Skip to content

Commit f880c2a

Browse files
committed
test(send_mail.py): add test cases for send_mail.py
issue pycontw#7
1 parent 3f7b212 commit f880c2a

File tree

3 files changed

+258
-3
lines changed

3 files changed

+258
-3
lines changed

send_mail.py

+24-3
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
import logging
44
import os
55
import smtplib
6+
import pickle
7+
from pathlib import Path
68
from email.mime.application import MIMEApplication
79
from email.mime.multipart import MIMEMultipart
810
from email.mime.text import MIMEText
@@ -69,6 +71,19 @@ def send_mail(mail, user, password, server_config=None):
6971
server.quit()
7072

7173

74+
def dump_mail(mail, suffix):
75+
if suffix:
76+
dump_path = '/tmp/mail_handler/with-separator'
77+
Path(dump_path).mkdir(parents=True, exist_ok=True)
78+
with open(f"{dump_path}/{mail['To']}", "wb") as dumpf:
79+
pickle.dump(mail, dumpf)
80+
else:
81+
dump_path = '/tmp/mail_handler/no-separator'
82+
Path(dump_path).mkdir(parents=True, exist_ok=True)
83+
with open(f"{dump_path}/{mail['To']}", "wb") as dumpf:
84+
pickle.dump(mail, dumpf)
85+
86+
7287
@click.command()
7388
@click.argument("config_path", type=click.Path(exists=True))
7489
@click.option(
@@ -77,14 +92,15 @@ def send_mail(mail, user, password, server_config=None):
7792
default="mails_to_sent",
7893
show_default=True,
7994
)
95+
@click.option("--debug", is_flag=True)
8096
@click.option(
8197
"--separator",
82-
default="",
98+
default=" - ",
8399
show_default=True,
84100
help="Separator used for subject suffix",
85101
)
86102
@click.option("--attachment_file", type=click.Path(exists=False))
87-
def main(mails_path, config_path, separator, attachment_file=None):
103+
def main(mails_path, config_path, debug, separator, attachment_file=None):
88104
if click.confirm(
89105
f'You are about to send the mails under "{mails_path}". Do you want to continue?',
90106
abort=True,
@@ -110,7 +126,12 @@ def main(mails_path, config_path, separator, attachment_file=None):
110126
attachment_file=attachment_file,
111127
suffix=mail_suffix,
112128
)
113-
send_mail(mail, user, password)
129+
130+
if debug:
131+
print("Debug mode is on. Dump mails instead of sending them.")
132+
dump_mail(mail, mail_suffix)
133+
else:
134+
send_mail(mail, user, password)
114135

115136

116137
# pylint: disable=no-value-for-parameter
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
2+
3+
Curabitur pretium tincidunt lacus. Nulla gravida orci a odio. Nullam varius, turpis et commodo pharetra, est eros bibendum elit, nec luctus magna felis sollicitudin mauris. Integer in mauris eu nibh euismod gravida. Duis ac tellus et risus vulputate vehicula. Donec lobortis risus a elit. Etiam tempor. Ut ullamcorper, ligula eu tempor congue, eros est euismod turpis, id tincidunt sapien risus a quam. Maecenas fermentum consequat mi. Donec fermentum. Pellentesque malesuada nulla a mi. Duis sapien sem, aliquet nec, commodo eget, consequat quis, neque. Aliquam faucibus, elit ut dictum aliquet, felis nisl adipiscing sapien, sed malesuada diam lacus eget erat. Cras mollis scelerisque nunc. Nullam arcu. Aliquam consequat. Curabitur augue lorem, dapibus quis, laoreet et, pretium ac, nisi. Aenean magna nisl, mollis quis, molestie eu, feugiat in, orci. In hac habitasse platea dictumst.

tests/test_send_mail.py

+231
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,231 @@
1+
import pickle
2+
import glob
3+
import json
4+
import os
5+
import pytest
6+
7+
from click.testing import CliRunner
8+
from send_mail import main
9+
10+
11+
path_mail_config = "./examples/sponsorship/spam_sponsors_2020_mail_config.json"
12+
path_receivers = "./examples/sponsorship/spam_sponsors_2020.json"
13+
path_pre_rendered_mails_no_separator = "./tests/data/no-separator"
14+
path_pre_rendered_mails_with_separator = "./tests/data/with-separator"
15+
path_attachment = "./tests/data/attachment-file/attachment01.txt"
16+
17+
18+
@pytest.fixture
19+
def all_mails_base_no_separator():
20+
return get_all_mail_names_from_path(
21+
glob.glob("/".join((path_pre_rendered_mails_no_separator, "*@*")))
22+
)
23+
24+
25+
@pytest.fixture
26+
def all_mails_base_with_separator():
27+
return get_all_mail_names_from_path(
28+
glob.glob("/".join((path_pre_rendered_mails_with_separator, "*@*")))
29+
)
30+
31+
32+
def get_mail_config():
33+
with open(path_mail_config, "rb") as f:
34+
return json.load(f)
35+
36+
37+
def get_receivers():
38+
with open(path_receivers, "rb") as f:
39+
return json.load(f)
40+
41+
42+
def get_all_mail_names_from_path(mails):
43+
all_mail_names = []
44+
for mail in mails:
45+
all_mail_names.append(os.path.basename(mail))
46+
47+
return all_mail_names
48+
49+
50+
def compare_on_sending_mail_all(
51+
targets, target_prefix="../examples", separator=" - ",
52+
):
53+
receivers = get_receivers()
54+
receiver_emails = []
55+
for mail_name in targets:
56+
for receiver in receivers['unique_data']:
57+
mail_addr, *mail_suffix_and_more = mail_name.split(
58+
separator, maxsplit=1
59+
)
60+
mail_suffix = mail_suffix_and_more[0] if mail_suffix_and_more else None
61+
if receiver['receiver_email'] == mail_addr:
62+
receiver_emails.append(mail_name)
63+
64+
# Not all target emails could have the corresponding answers
65+
if len(receiver_emails) != len(targets):
66+
return False
67+
68+
for mail_name in targets:
69+
for receiver in receivers['unique_data']:
70+
if receiver['receiver_email'] == mail_name:
71+
if not compare_on_sending_mail("/".join((target_prefix, mail_name)), receivers):
72+
return False
73+
74+
return True
75+
76+
77+
def compare_on_sending_mail(target, receivers):
78+
mail_name = os.path.basename(target)
79+
mail_config = get_mail_config()
80+
81+
with open(target, "rb") as f:
82+
target_content = pickle.load(f)
83+
if target_content['From'] != mail_config['From']:
84+
return False
85+
86+
if mail_name != target_content['To']:
87+
return False
88+
89+
if target_content['CC'] != mail_config['CC']:
90+
return False
91+
92+
for receiver in receivers['unique_data']:
93+
if receiver['receiver_email'] == target_content['To']:
94+
receiver_name = receiver['receiver_name']
95+
96+
if 'no-separator' in target and mail_config['Subject'] != target_content['Subject']:
97+
return False
98+
99+
if 'with-separator' in target:
100+
subject = ' - '.join((mail_config['Subject'], receiver_name))
101+
if subject != target_content['Subject']:
102+
return False
103+
104+
if not is_attachment_expected(target_content):
105+
return False
106+
107+
return True
108+
109+
110+
def is_attachment_expected(target_content):
111+
for part in target_content.walk():
112+
content_disposition = part.get("Content-Disposition", None)
113+
if content_disposition:
114+
dispositions = content_disposition.strip().split(";")
115+
if bool(content_disposition and dispositions[0].lower() == "attachment"):
116+
target_data = part.get_payload(decode=True)
117+
with open(path_attachment, "rb") as fattachment:
118+
base_data = fattachment.readlines()
119+
data_str_target = target_data.decode('utf-8')
120+
base_data_tmp = []
121+
122+
for line in base_data:
123+
base_data_tmp.append(line.decode('utf-8'))
124+
data_str_base = ''.join(base_data_tmp)
125+
126+
if data_str_base != data_str_target:
127+
return False
128+
129+
return True
130+
131+
132+
def test_send_mail_no_separator_no_attachment(all_mails_base_no_separator):
133+
runner = CliRunner()
134+
result = runner.invoke(
135+
main,
136+
[
137+
"--debug",
138+
"--mails_path",
139+
path_pre_rendered_mails_no_separator,
140+
path_mail_config
141+
],
142+
input='y\nusername\npassword\n'
143+
)
144+
145+
targets = get_all_mail_names_from_path(all_mails_base_no_separator)
146+
147+
assert result.exit_code == 0
148+
assert compare_on_sending_mail_all(
149+
targets,
150+
target_prefix="/tmp/mail_handler/no-separator"
151+
)
152+
153+
154+
def test_send_mail_no_separator_with_attachment(all_mails_base_no_separator):
155+
runner = CliRunner()
156+
result = runner.invoke(
157+
main,
158+
[
159+
"--debug",
160+
"--mails_path",
161+
path_pre_rendered_mails_no_separator,
162+
"--attachment_file",
163+
path_attachment,
164+
path_mail_config
165+
],
166+
input='y\nusername\npassword\n'
167+
)
168+
169+
targets = get_all_mail_names_from_path(all_mails_base_no_separator)
170+
171+
assert result.exit_code == 0
172+
assert compare_on_sending_mail_all(
173+
targets,
174+
target_prefix="/tmp/mail_handler/no-separator"
175+
)
176+
177+
178+
def test_send_mail_with_separator_dash_no_attachment(all_mails_base_with_separator):
179+
separator = " - "
180+
181+
runner = CliRunner()
182+
result = runner.invoke(
183+
main,
184+
[
185+
"--debug",
186+
"--separator",
187+
separator,
188+
"--mails_path",
189+
path_pre_rendered_mails_with_separator,
190+
path_mail_config
191+
],
192+
input='y\nusername\npassword\n'
193+
)
194+
195+
targets = get_all_mail_names_from_path(all_mails_base_with_separator)
196+
197+
assert result.exit_code == 0
198+
assert compare_on_sending_mail_all(
199+
targets,
200+
target_prefix="/tmp/mail_handler/with-separator",
201+
separator=separator
202+
)
203+
204+
205+
def test_send_mail_with_separator_dash_with_attachment(all_mails_base_with_separator):
206+
separator = " - "
207+
208+
runner = CliRunner()
209+
result = runner.invoke(
210+
main,
211+
[
212+
"--debug",
213+
"--separator",
214+
separator,
215+
"--mails_path",
216+
path_pre_rendered_mails_with_separator,
217+
"--attachment_file",
218+
path_attachment,
219+
path_mail_config
220+
],
221+
input='y\nusername\npassword\n'
222+
)
223+
224+
targets = get_all_mail_names_from_path(all_mails_base_with_separator)
225+
226+
assert result.exit_code == 0
227+
assert compare_on_sending_mail_all(
228+
targets,
229+
target_prefix="/tmp/mail_handler/with-separator",
230+
separator=separator
231+
)

0 commit comments

Comments
 (0)