1"""
2Return salt data via email
3
4The following fields can be set in the minion conf file:
5
6    smtp.from (required)
7    smtp.to (required)
8    smtp.host (required)
9    smtp.port (optional, defaults to 25)
10    smtp.username (optional)
11    smtp.password (optional)
12    smtp.tls (optional, defaults to False)
13    smtp.subject (optional, but helpful)
14    smtp.gpgowne' (optional)
15    smtp.fields (optional)
16    smtp.content (optional)
17
18There are a few things to keep in mind:
19
20* If a username is used, a password is also required. It is recommended (but
21  not required) to use the TLS setting when authenticating.
22* You should at least declare a subject, but you don't have to.
23* The use of encryption, i.e. setting gpgowner in your settings, requires
24  python-gnupg to be installed.
25* The field gpgowner specifies a user's ~/.gpg directory. This must contain a
26  gpg public key matching the address the mail is sent to. If left unset, no
27  encryption will be used.
28"""
29
30import logging
31import os
32import smtplib
33from email.utils import formatdate
34
35try:
36    import gnupg
37
38    HAS_GNUPG = True
39except ImportError:
40    HAS_GNUPG = False
41
42
43log = logging.getLogger(__name__)
44
45
46def send(kwargs, opts):
47    """
48    Send an email with the data
49    """
50    opt_keys = (
51        "smtp.to",
52        "smtp.from",
53        "smtp.host",
54        "smtp.port",
55        "smtp.tls",
56        "smtp.username",
57        "smtp.password",
58        "smtp.subject",
59        "smtp.gpgowner",
60        "smtp.content",
61    )
62
63    config = {}
64    for key in opt_keys:
65        config[key] = opts.get(key, "")
66
67    config.update(kwargs)
68
69    if not config["smtp.port"]:
70        config["smtp.port"] = 25
71
72    log.debug("SMTP port has been set to %s", config["smtp.port"])
73    log.debug("smtp_return: Subject is '%s'", config["smtp.subject"])
74
75    if HAS_GNUPG and config["smtp.gpgowner"]:
76        gpg = gnupg.GPG(
77            gnupghome=os.path.expanduser("~{}/.gnupg".format(config["smtp.gpgowner"])),
78            options=["--trust-model always"],
79        )
80        encrypted_data = gpg.encrypt(config["smtp.content"], config["smtp.to"])
81        if encrypted_data.ok:
82            log.debug("smtp_return: Encryption successful")
83            config["smtp.content"] = str(encrypted_data)
84        else:
85            log.error("SMTP: Encryption failed, only an error message will be sent")
86            config[
87                "smtp.content"
88            ] = "Encryption failed, the return data was not sent.\r\n\r\n{}\r\n{}".format(
89                encrypted_data.status, encrypted_data.stderr
90            )
91
92    message = "From: {}\r\nTo: {}\r\nDate: {}\r\nSubject: {}\r\n\r\n{}".format(
93        config["smtp.from"],
94        config["smtp.to"],
95        formatdate(localtime=True),
96        config["smtp.subject"],
97        config["smtp.content"],
98    )
99
100    log.debug("smtp_return: Connecting to the server...")
101    server = smtplib.SMTP(config["smtp.host"], int(config["smtp.port"]))
102
103    if config["smtp.tls"] is True:
104        server.starttls()
105        log.debug("smtp_return: TLS enabled")
106
107    if config["smtp.username"] and config["smtp.password"]:
108        server.login(config["smtp.username"], config["smtp.password"])
109        log.debug("smtp_return: Authenticated")
110
111    server.sendmail(config["smtp.from"], config["smtp.to"], message)
112    log.debug("smtp_return: Message sent.")
113    server.quit()
114