-
Notifications
You must be signed in to change notification settings - Fork 0
/
mailer.py
110 lines (90 loc) · 4 KB
/
mailer.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
import argparse, base64, time
from csv import DictReader
from email.mime.base import MIMEBase
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from string import Template
from io import StringIO
from google.auth.transport.requests import Request
from google.oauth2.credentials import Credentials
from google_auth_oauthlib.flow import InstalledAppFlow
from googleapiclient.discovery import build
from googleapiclient.errors import HttpError
parser = argparse.ArgumentParser(description="A followup program for easily send out access information for their Nested-Linux container.")
parser.add_argument('nested_file', type=argparse.FileType('r', encoding='UTF-8-sig'), help="Path to csv file generated by Linux-Nester.")
parser.add_argument('host', type=str, help="Host IP of the LXD instance.")
parser.add_argument('secretfile', type=str, help="Path to your secret file.")
# Headers of input-file
_ssh_port_cname = "ssh_port"
_web_port_cname = "web_port"
_user_cname = "user"
_email_cname = "e_mail"
_key64_cname = "key64"
# API variables
SCOPES = ["openid", "https://www.googleapis.com/auth/gmail.send", "https://www.googleapis.com/auth/gmail.metadata"]
# Message
SUBJECT = "Your Linux Access Details"
TEMPLATE = Template('''Hello Participant,
Here are your access details for your Linux Container:
HOST-IP: $ip
SSH-Port: $ssh
Username: $username
You also get a web-port to test web applications with: $web
Open port 80 in your container and then use http with your port above.
Included is the private key file needed to login.
DON'T USE THIS KEY FOR ANYTHING ELSE, but loggin into this server. This key is known to us, and should be considered leaked.
Have fun!
Your Learning Coach
(This message was send automatically, ask your LC if you are interested how.)
'''
)
def main(args):
print("TG Nest-Mailer, making mailing access keys easier.")
### Pre-loop Preparations
# Getting reader from input file
reader = DictReader(args.nested_file, delimiter=",")
# Get access to senders GMAIL account
creds = InstalledAppFlow.from_client_secrets_file(args.secretfile, SCOPES).run_local_server(port=0)
service = None
try:
service = build('gmail', 'v1', credentials=creds)
except HttpError as err:
print(err)
input("Authentication complete. Press enter to start sending the emails...")
### Main loop
for row in reader:
### Preperations inside loop
# Prepare message
message = MIMEMultipart()
message['from'] = service.users().getProfile(userId="me").execute()["emailAddress"]
message['to'] = row[_email_cname]
message['subject'] = SUBJECT
message.attach(MIMEText(TEMPLATE.substitute({
"ip": args.host,
"ssh": row[_ssh_port_cname],
"username": row[_user_cname],
"web": row[_web_port_cname]
})))
# Prepare key for attachment
virtual_file = StringIO()
virtual_file.write(base64.b64decode(row[_key64_cname]).decode("UTF-8"))
virtual_file.seek(0)
# Prepare the key metadata
attachment = MIMEBase("application", "x-pem-file") # Filetype for .Pem files: https://pki-tutorial.readthedocs.io/en/latest/mime.html
attachment.set_payload(virtual_file.getvalue())
attachment.add_header('Content-Disposition', 'attachment', filename="access_key.pem")
# Attach file to message
message.attach(attachment)
# Close buffers
virtual_file.close()
### Send
try:
mail = service.users().messages().send(userId="me", body={ "raw": base64.urlsafe_b64encode(message.as_bytes()).decode('ascii') }).execute()
print("Message Id: {} to: {}".format(mail['id'], row[_email_cname]))
except HttpError as error:
print('An error occurred: {}'.format(error))
exit(1) # Hard exit to prevent mixed results
# Backoff for a second to prevent API overloading
time.sleep(1)
if __name__ == '__main__':
main(parser.parse_args())