-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.py
executable file
·170 lines (157 loc) · 5.73 KB
/
main.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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
#!/usr/bin/env python
import argparse
from getpass import getpass
from os import getenv
import pathlib
import re as regex
from secret_santa.Participant import create_participant_hash
from secret_santa.selections import make_selections
from secret_santa.email import invite_participants, email_participants
from send_email.gmail_api import GmailApiSender
from send_email.aws_ses import AwsSesSender
from send_email.gmail_smtp import GmailSMTPSender
"""
Informs Secret Santa participants of their Secret Santa via email
"""
def process_commandline_parameters():
"""
Processes commandline parameters for dynamic use of email, password, csv files, and exchange date.
Not adaptable to other scripts in its hard-coded form.
Returns
-------
tuple: (Object, str, str, str, function)
Class object for sending emails, names csv, exceptions csv, exchange date, and function for sending emails
"""
parser = argparse.ArgumentParser()
parser.add_argument("-e", "--email", help="Sender's Email address")
parser.add_argument(
"-p",
"--password",
help="Sender's Email password; only necessary for SMTP through Gmail",
)
parser.add_argument(
"-m",
"--method",
help="Method for sending emails; One of gmailapi (default), ses, or smtp.",
)
parser.add_argument(
"-n", "--names", help="CSV containing participants names and email addresses"
)
parser.add_argument(
"-x",
"--exceptions",
help="CSV containing participant's name followed by people they should not be paired with",
)
parser.add_argument("-d", "--date", help="Date of the Secret Santa exchange")
parser.add_argument(
"-i",
"--invitation",
help="Sends an invitation email instead of pairing participants for the exchange",
action="store_true",
)
args = parser.parse_args()
if args.email:
email = args.email
else:
email = input("Sender's email: ").strip()
if args.method:
if args.method.casefold() == "gmailapi".casefold():
cred_path, token_path = get_gmail_api_env_vars()
sender_object = GmailApiSender(email, cred_path, token_path)
elif args.method.casefold() == "ses".casefold():
sender_object = AwsSesSender(email)
elif args.method.casefold() == "smtp".casefold():
if args.password:
password = args.password
else:
password = getpass("Password for sender's email: ").strip()
sender_object = GmailSMTPSender(email, password)
else:
raise ValueError(
"Invalid send method specified; must be one of gmailapi, ses, or smtp"
)
else:
cred_path, token_path = get_gmail_api_env_vars()
sender_object = GmailApiSender(email, cred_path, token_path)
if args.names:
names_filename = args.names
else:
generic_names_file = pathlib.Path("pii/names.csv")
if generic_names_file.is_file():
print("Using pii/names.csv from cwd")
names_filename = "pii/names.csv"
else:
names_filename = input("File containing names,emails: ").strip()
if args.exceptions:
exceptions_filename = args.exceptions
else:
generic_exceptions_file = pathlib.Path("pii/exceptions.csv")
if generic_exceptions_file.is_file():
print("Using pii/exceptions.csv from cwd")
exceptions_filename = "pii/exceptions.csv"
else:
confirm_exceptions_file = input(
"No exceptions file provided (-x). Would you like to use one? "
).strip()
if regex.match("[Yy]", confirm_exceptions_file):
exceptions_filename = input("File name: ").strip()
else:
exceptions_filename = None
if args.date:
exchange_date_string = args.date
elif not args.invitation:
confirm_exchange_date = input(
"Would you like to specify an exchange date?"
).strip()
if regex.match("[Yy]", confirm_exchange_date):
exchange_date_string = input(
"Specify the date however you would like it displayed: "
).strip()
else:
exchange_date_string = None
else:
exchange_date_string = None
return (
sender_object,
names_filename,
exceptions_filename,
exchange_date_string,
args.invitation,
)
def get_gmail_api_env_vars():
"""
Checks for necessary environment variables for the Gmail API, and raises an error if not present
Returns
-------
str, str
Path to Google Project credentials, path to save token
"""
errors = None
if not (cred_path := getenv("CRED_PATH")):
errors = "CRED_PATH variable is not set"
if not (token_path := getenv("TOKEN_PATH")):
if errors:
errors = "CRED_PATH and TOKEN_PATH variables are not set"
else:
errors = "TOKEN_PATH variable is not set"
if errors:
raise RuntimeError(errors)
return cred_path, token_path
if __name__ == "__main__":
(
sender,
names_fname,
exceptions_fname,
exchange_date,
invitation,
) = process_commandline_parameters()
participants = create_participant_hash(names_fname, exceptions_fname)
if invitation:
email_status = invite_participants(sender, participants)
else:
order = make_selections(participants) # The Algorithm
email_status = email_participants(sender, participants, order, exchange_date)
if all(email_status):
print("All emails sent successfully")
else:
print("There was an error sending one or more emails")