Completed
Push — master ( d56c20...c7f92e )
by John
01:16
created

smtp_config_homepath()   A

Complexity

Conditions 2

Size

Total Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

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