Completed
Push — master ( 42fe6f...e79e83 )
by John
02:33
created

smtp_config_generator_username()   A

Complexity

Conditions 2

Size

Total Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
c 0
b 0
f 0
dl 0
loc 10
ccs 4
cts 4
cp 1
crap 2
rs 9.4285
1
#!/usr/bin/env python3
2 4
"""This module is used for dealing with SMTP email sending."""
3
4 4
import smtplib  # smtp connection
5 4
import getpass  # passwords
6 4
from email.mime.text import MIMEText  # email formatting
7 4
from bbarchivist import utilities  # file work
8 4
from bbarchivist import iniconfig  # config parsing
9
10 4
__author__ = "Thurask"
11 4
__license__ = "WTFPL v2"
12 4
__copyright__ = "Copyright 2015-2016 Thurask"
13
14
15 4
def smtp_config_loader(homepath=None):
16
    """
17
    Read a ConfigParser file to get email preferences.
18
19
    :param homepath: Folder containing ini file. Default is user directory.
20
    :type homepath: str
21
    """
22 4
    resultdict = {}
23 4
    smtpini = iniconfig.generic_loader("email", homepath)
24 4
    resultdict['server'] = smtpini.get('server', fallback=None)
25 4
    resultdict['port'] = int(smtpini.getint('port', fallback=0))
26 4
    resultdict['username'] = smtpini.get('username', fallback=None)
27 4
    resultdict['password'] = smtpini.get('password', fallback=None)
28 4
    resultdict['is_ssl'] = smtpini.get('is_ssl', fallback=None)
29 4
    return resultdict
30
31
32 4
def smtp_config_writer_kwargs(kwargs, config, key):
33
    """
34
    Set server/port/username/password config.
35
36
    :param kwargs: Values. Refer to `:func:smtp_config_writer`.
37
    :type kwargs: dict
38
39
    :param config: Configuration dictionary.
40
    :type config: dict
41
42
    :param key: Key for kwargs and config dict.
43
    :type key: str
44
    """
45 4
    if kwargs[key] is not None:
46 4
        config[key] = kwargs[key]
47 4
    return kwargs
48
49
50 4
def smtp_config_writer_ssl(kwargs, config):
51
    """
52
    Set SSL/TLS config.
53
54
    :param kwargs: Values. Refer to `:func:smtp_config_writer`.
55
    :type kwargs: dict
56
57
    :param config: Configuration dictionary.
58
    :type config: dict
59
    """
60 4
    if kwargs['is_ssl'] is not None:
61 4
        config['is_ssl'] = str(kwargs['is_ssl']).lower()
62 4
    return config
63
64
65 4
def smtp_config_writer(**kwargs):
66
    """
67
    Write a ConfigParser file to store email server details.
68
69
    :param server: SMTP email server.
70
    :type server: str
71
72
    :param port: Port to use.
73
    :type port: int
74
75
    :param username: Email address.
76
    :type username: str
77
78
    :param password: Email password, optional.
79
    :type password: str
80
81
    :param is_ssl: True if server uses SSL, False if TLS only.
82
    :type is_ssl: bool
83
84
    :param homepath: Folder containing ini file. Default is user directory.
85
    :type homepath: str
86
    """
87 4
    results = {}
88 4
    results = smtp_config_writer_kwargs(kwargs, results, "server")
89 4
    results = smtp_config_writer_kwargs(kwargs, results, "port")
90 4
    results = smtp_config_writer_kwargs(kwargs, results, "username")
91 4
    results = smtp_config_writer_kwargs(kwargs, results, "password")
92 4
    results = smtp_config_writer_ssl(kwargs, results)
93 4
    iniconfig.generic_writer("email", results, kwargs['homepath'])
94
95
96 4
def smtp_config_generator_str(results, key, inp):
97
    """
98
    Set server/username config.
99
100
    :param kwargs: Values. Refer to `:func:smtp_config_writer`.
101
    :type kwargs: dict
102
103
    :param key: Key for results dict.
104
    :type key: str
105
106
    :param inp: Input question.
107
    :type inp: str
108
    """
109 4
    if results[key] is None:
110 4
        results[key] = input(inp)
111 4
    return results 
0 ignored issues
show
Coding Style introduced by
Trailing whitespace
Loading history...
112
113
114 4
def smtp_config_generator_port(results):
115
    """
116
    Generate port config.
117
118
    :param results: Values. Refer to `:func:smtp_config_writer`.
119
    :type results: dict
120
    """
121 4
    if results['port'] == 0:
122 4
        results['port'] = input("SMTP SERVER PORT: ")
123 4
    return results
124
125
126 4
def smtp_config_generator_password(results):
127
    """
128
    Generate password config.
129
130
    :param results: Values. Refer to `:func:smtp_config_writer`.
131
    :type results: dict
132
    """
133 4
    if results['password'] is None:
134 4
        results['password'] = getpass.getpass(prompt="PASSWORD: ")
135 4
    return results
136
137
138 4
def smtp_config_generator_ssl(results):
139
    """
140
    Generate SSL/TLS config.
141
142
    :param results: Values. Refer to `:func:smtp_config_writer`.
143
    :type results: dict
144
    """
145 4
    if results['is_ssl'] is None:
146 4
        use_ssl = utilities.s2b(input("Y: SSL, N: TLS (Y/N): "))
147 4
        results['is_ssl'] = "true" if use_ssl else "false"
148 4
    return results
149
150
151 4
def smtp_config_generator(results):
152
    """
153
    Take user input to create the SMTP config settings.
154
155
    :param results: The results to put in bbarchivist.ini.
156
    :type results: dict
157
    """
158 4
    results = smtp_config_generator_str(results, "server", "SMTP SERVER ADDRESS: ")
159 4
    results = smtp_config_generator_port(results)
160 4
    results = smtp_config_generator_str(results, "username", "EMAIL ADDRESS: ")
161 4
    results = smtp_config_generator_password(results)
162 4
    results = smtp_config_generator_ssl(results)
163 4
    return results
164
165
166 4
def send_email(kwargs):
167
    """
168
    Wrap email sending based on SSL/TLS.
169
170
    :param server: SMTP email server.
171
    :type server: str
172
173
    :param port: Port to use.
174
    :type port: int
175
176
    :param username: Email address.
177
    :type username: str
178
179
    :param password: Email password, optional.
180
    :type password: str
181
182
    :param is_ssl: True if server uses SSL, False if TLS only.
183
    :type is_ssl: bool
184
185
    :param software: Software release.
186
    :type software: str
187
188
    :param os: OS version.
189
    :type os: str
190
191
    :param body: Email message body.
192
    :type body: str
193
    """
194 4
    password = smtp_config_generator_password(kwargs)
195 4
    server, username, port, password = parse_kwargs(kwargs)
196 4
    subject = generate_subject(kwargs['software'], kwargs['os'])
197 4
    message = generate_message(kwargs['body'], username, subject)
198 4
    payload = {
199
        "server": server,
200
        "port": port,
201
        "username": username,
202
        "password": password,
203
        "message": message,
204
        "is_ssl": utilities.s2b(kwargs["is_ssl"])
205
    }
206 4
    send_email_post(payload)
207
208
209 4
def prep_smtp_instance(kwargs):
210
    """
211
    Prepare a smtplib.SMTP/SMTP_SSL instance.
212
213
    :param is_ssl: True if server uses SSL, False if TLS only.
214
    :type is_ssl: bool
215
216
    :param server: SMTP email server.
217
    :type server: str
218
219
    :param port: Port to use.
220
    :type port: int
221
    """
222 4
    args = kwargs['server'], kwargs['port']
223 4
    smt = smtplib.SMTP_SSL(*args) if kwargs['is_ssl'] else smtplib.SMTP(*args)
224 4
    return smt
225
226
227 4
def send_email_post(kwargs):
228
    """
229
    Send email through SSL/TLS.
230
231
    :param server: SMTP email server.
232
    :type server: str
233
234
    :param port: Port to use.
235
    :type port: int
236
237
    :param username: Email address.
238
    :type username: str
239
240
    :param password: Email password.
241
    :type password: str
242
243
    :param message: Message to send, with body and subject.
244
    :type message: MIMEText
245
    """
246 4
    smt = prep_smtp_instance(kwargs)
247 4
    smt.ehlo()
248 4
    if not kwargs['is_ssl']:
249 4
        smt.starttls()
250 4
    smt.login(kwargs['username'], kwargs['password'])
251 4
    smt.sendmail(kwargs['username'], kwargs['username'], kwargs['message'].as_string())
252 4
    smt.quit()
253
254
255 4
def parse_kwargs(kwargs):
256
    """
257
    Extract variables from kwargs.
258
259
    :param server: SMTP email server.
260
    :type server: str
261
262
    :param port: Port to use.
263
    :type port: int
264
265
    :param username: Email address.
266
    :type username: str
267
268
    :param password: Email password, optional.
269
    :type password: str
270
    """
271 4
    server = kwargs['server']
272 4
    username = kwargs['username']
273 4
    port = kwargs['port']
274 4
    password = kwargs['password']
275 4
    return server, username, port, password
276
277
278 4
def generate_message(body, username, subject):
279
    """
280
    Generate message body/headers.
281
282
    :param body: Body of text.
283
    :type body: str
284
285
    :param username: Address to send to and from.
286
    :type username: str
287
288
    :param subject: Subject of message.
289
    :type subject: str
290
    """
291 4
    msg = MIMEText(body)
292 4
    msg['Subject'] = subject
293 4
    msg['From'] = username
294 4
    msg['To'] = username
295 4
    return msg
296
297
298 4
def generate_subject(softwarerelease, osversion):
299
    """
300
    Generate message subject.
301
302
    :param softwarerelease: Software version.
303
    :type softwarerelease: str
304
305
    :param osversion: OS version.
306
    :type osversion: str
307
    """
308 4
    return "SW {0} - OS {1} available!".format(softwarerelease, osversion)
309
310
311 4
def prep_email(osversion, softwarerelease, password=None):
312
    """
313
    Bootstrap the whole process.
314
315
    :param osversion: OS version.
316
    :type osversion: str
317
318
    :param softwarerelease: Software version.
319
    :type softwarerelease: str
320
321
    :param password: Email password. None to prompt later.
322
    :type password: str
323
    """
324 4
    results = smtp_config_loader()
325 4
    results['homepath'] = None
326 4
    smtp_config_writer(**results)
327 4
    results['software'] = softwarerelease
328 4
    results['os'] = osversion
329 4
    results['body'] = utilities.return_and_delete("TEMPFILE.txt")
330 4
    if password is not None:
331 4
        results['password'] = password
332
    send_email(results)
333