diff --git a/reaction-mailcreate/createMails.py b/reaction-mailcreate/createMails.py index 966ab9f1f4cf5db9d16b93e5e3453cb296131dba..97d87aebdedf4197d5aeb5f48826e89896341b81 100755 --- a/reaction-mailcreate/createMails.py +++ b/reaction-mailcreate/createMails.py @@ -52,7 +52,7 @@ parser.add_argument('-f', '--from', dest='sender', default='Nobody <no parser.add_argument('-F', '--force', dest='force', default=False, action='store_true', help='force insecure login without TLS/SSL (default: False)') parser.add_argument('-H', '--hashstring', dest='hashstring', default='{salt}{campaign}{infix}-{site}', help='string to be hashed for the URL (default: "{salt}{campaign}{infix}-{site}" where "{salt}" is a random string)') parser.add_argument('-i', '--input', dest='input', default='{basedir}/{campaign}/Input{infix}.lst', help='input file (default: "{basedir}/{campaign}/Input{infix}.lst")') -parser.add_argument('-o', '--output', dest='output', default='{basedir}/{campaign}/{site}/Mail{infix}.eml', help='output file name template (default: "{basedir}/{campaign}/{site}/Mail{infix}.eml")') +parser.add_argument('-o', '--output', dest='output', default='{basedir}/{campaign}/{site}/{timestamp}{infix}.eml', help='output file name template (default: "{basedir}/{campaign}/{site}/{timestamp}{infix}.eml")') parser.add_argument('-R', '--reply-to', dest='replyto', default=None, help='reply-to mail address (default: None)') parser.add_argument( '--salt', dest='salt', default=None, help='salt to use for hashing (default: random 8-byte hex string)') parser.add_argument( '--sign', dest='sign', default='', choices=['', 'gpg', 'gpgsm', 'openssl'], help='signature method (one of "", "gpg", "gpgsm", "openssl"; default: "")') @@ -64,6 +64,7 @@ parser.add_argument( '--smtpuser', dest='smtpuser', default=None, help= parser.add_argument( '--smtppass', dest='smtppass', default=None, help='SMTP password to login with (default: none); implies TLS (port 465) unless STARTTLS is set as well; will be queried interactively if set to "-"') parser.add_argument( '--starttls', dest='starttls', default=False, action='store_true', help='login using STARTTLS (default: False); implies port 587') parser.add_argument('-t', '--template', dest='template', default='{basedir}/{campaign}/Mail.template', help='mail template file (default: "{basedir}/{campaign}/Mail.template")') +parser.add_argument( '--timestamp', dest='timestamp', default='%Y-%m-%dT%H:%M:%SZ', help='timestamp format used for {timestamp} keyword (default: "%Y-%m-%dT%H:%M:%SZ")') parser.add_argument('-T', '--to', dest='to', default='{firstname} {lastname} <{email}>', help='recipient mail address (default: "{firstname} {lastname} <{email}>")') parser.add_argument('-u', '--url', dest='url', default='{webserver}/{campaign}{infix}-{hash}', help='URL template to use (default: "{webserver}/{campaign}{infix}-{hash}"') parser.add_argument('-U', '--createurl', dest='createurl', default='{webserver}/{campaign}{infix}-{hash}/create', help='URL template to use for creation URL (default: "{webserver}/{campaign}{infix}-{hash}/create"') @@ -167,6 +168,7 @@ if args.verbose: print(f'Using no signature method.') print(f'Using "{args.subject.format_map(SafeDict(basedir=args.basedir, campaign=args.campaign, infix=args.infix, webserver=args.webserver, salt=args.salt))}" as mail subject.') print(f'Using "{args.template.format_map(SafeDict(basedir=args.basedir, campaign=args.campaign, infix=args.infix, webserver=args.webserver, salt=args.salt))}" as template file.') + print(f'Using "{args.timestamp.format_map(SafeDict(basedir=args.basedir, campaign=args.campaign, infix=args.infix, webserver=args.webserver, salt=args.salt))}" as timestamp format.') print(f'Using "{args.to.format_map(SafeDict(basedir=args.basedir, campaign=args.campaign, infix=args.infix, webserver=args.webserver, salt=args.salt))}" as recipient mail address.') print(f'Using "{args.url.format_map(SafeDict(basedir=args.basedir, campaign=args.campaign, infix=args.infix, webserver=args.webserver, salt=args.salt))}" as URL template.') print(f'Using "{args.createurl.format_map(SafeDict(basedir=args.basedir, campaign=args.campaign, infix=args.infix, webserver=args.webserver, salt=args.salt))}" as URL template.') @@ -247,7 +249,7 @@ def signMail(message): # Assemble and send the actual mail def createMail(data): - output = args.output.format_map(SafeDict(basedir=args.basedir, campaign=args.campaign, infix=args.infix, webserver=args.webserver, salt=args.salt, site=data['site'], firstname=data['firstname'], lastname=data['lastname'], email=data['email'], hash=data['hash'], URL=data['URL'])) + output = args.output.format_map(SafeDict(basedir=args.basedir, campaign=args.campaign, infix=args.infix, webserver=args.webserver, salt=args.salt, site=data['site'], firstname=data['firstname'], lastname=data['lastname'], email=data['email'], hash=data['hash'], URL=data['URL'], timestamp=data['timestamp'])) directory = os.path.dirname(output) # Generate email body and attachments @@ -261,15 +263,15 @@ def createMail(data): message = signMail(message) message['Date'] = formatdate(localtime=True) - message['Subject'] = args.subject.format_map(SafeDict(basedir=args.basedir, campaign=args.campaign, infix=args.infix, webserver=args.webserver, salt=args.salt, site=data['site'], firstname=data['firstname'], lastname=data['lastname'], email=data['email'], hash=data['hash'], URL=data['URL'])) - message['From'] = args.sender.format_map(SafeDict(basedir=args.basedir, campaign=args.campaign, infix=args.infix, webserver=args.webserver, salt=args.salt, site=data['site'], firstname=data['firstname'], lastname=data['lastname'], email=data['email'], hash=data['hash'], URL=data['URL'])) + message['Subject'] = args.subject.format_map(SafeDict(basedir=args.basedir, campaign=args.campaign, infix=args.infix, webserver=args.webserver, salt=args.salt, site=data['site'], firstname=data['firstname'], lastname=data['lastname'], email=data['email'], hash=data['hash'], URL=data['URL'], timestamp=data['timestamp'])) + message['From'] = args.sender.format_map(SafeDict(basedir=args.basedir, campaign=args.campaign, infix=args.infix, webserver=args.webserver, salt=args.salt, site=data['site'], firstname=data['firstname'], lastname=data['lastname'], email=data['email'], hash=data['hash'], URL=data['URL'], timestamp=data['timestamp'])) if args.replyto: - message['Reply-To'] = args.replyto.format_map(SafeDict(basedir=args.basedir, campaign=args.campaign, infix=args.infix, webserver=args.webserver, salt=args.salt, site=data['site'], firstname=data['firstname'], lastname=data['lastname'], email=data['email'], hash=data['hash'], URL=data['URL'])) - message['To'] = args.to.format_map(SafeDict(basedir=args.basedir, campaign=args.campaign, infix=args.infix, webserver=args.webserver, salt=args.salt, site=data['site'], firstname=data['firstname'], lastname=data['lastname'], email=data['email'], hash=data['hash'], URL=data['URL'])) + message['Reply-To'] = args.replyto.format_map(SafeDict(basedir=args.basedir, campaign=args.campaign, infix=args.infix, webserver=args.webserver, salt=args.salt, site=data['site'], firstname=data['firstname'], lastname=data['lastname'], email=data['email'], hash=data['hash'], URL=data['URL'], timestamp=data['timestamp'])) + message['To'] = args.to.format_map(SafeDict(basedir=args.basedir, campaign=args.campaign, infix=args.infix, webserver=args.webserver, salt=args.salt, site=data['site'], firstname=data['firstname'], lastname=data['lastname'], email=data['email'], hash=data['hash'], URL=data['URL'], timestamp=data['timestamp'])) if args.cc: - message['Cc'] = ', '.join(args.cc).format_map(SafeDict(basedir=args.basedir, campaign=args.campaign, infix=args.infix, webserver=args.webserver, salt=args.salt, site=data['site'], firstname=data['firstname'], lastname=data['lastname'], email=data['email'], hash=data['hash'], URL=data['URL'])) + message['Cc'] = ', '.join(args.cc).format_map(SafeDict(basedir=args.basedir, campaign=args.campaign, infix=args.infix, webserver=args.webserver, salt=args.salt, site=data['site'], firstname=data['firstname'], lastname=data['lastname'], email=data['email'], hash=data['hash'], URL=data['URL'], timestamp=data['timestamp'])) if args.bcc: - message['Bcc'] = ', '.join(args.bcc).format_map(SafeDict(basedir=args.basedir, campaign=args.campaign, infix=args.infix, webserver=args.webserver, salt=args.salt, site=data['site'], firstname=data['firstname'], lastname=data['lastname'], email=data['email'], hash=data['hash'], URL=data['URL'])) + message['Bcc'] = ', '.join(args.bcc).format_map(SafeDict(basedir=args.basedir, campaign=args.campaign, infix=args.infix, webserver=args.webserver, salt=args.salt, site=data['site'], firstname=data['firstname'], lastname=data['lastname'], email=data['email'], hash=data['hash'], URL=data['URL'], timestamp=data['timestamp'])) # Record mail print(f'Writing mail to {output}') @@ -307,11 +309,12 @@ def createMail(data): requests.get(f'{data["CreateURL"]}') -# Generate hash, URL, and CreateURL -def generateHashAndURL(data): +# Generate site-specific data: hash, URL, CreateURL, timestamp +def generateIndividualData(data): data['hash'] = hashlib.sha256(args.hashstring.format_map(SafeDict(basedir=args.basedir, campaign=args.campaign, infix=args.infix, webserver=args.webserver, salt=args.salt, site=data['site'], firstname=data['firstname'], lastname=data['lastname'], email=data['email'])).encode('utf-8')).hexdigest() data['URL'] = args.url.format_map(SafeDict(basedir=args.basedir, campaign=args.campaign, infix=args.infix, webserver=args.webserver, salt=args.salt, site=data['site'], firstname=data['firstname'], lastname=data['lastname'], email=data['email'], hash=data['hash'])) data['CreateURL'] = args.createurl.format_map(SafeDict(basedir=args.basedir, campaign=args.campaign, infix=args.infix, webserver=args.webserver, salt=args.salt, site=data['site'], firstname=data['firstname'], lastname=data['lastname'], email=data['email'], hash=data['hash'])) + data['timestamp'] = datetime.datetime.now(datetime.UTC).strftime(args.timestamp) # Main loop @@ -322,5 +325,5 @@ with open(args.input.format_map(SafeDict(basedir=args.basedir, campaign=args.cam (row['firstname'] != 'firstname') or \ (row['lastname'] != 'lastname') or \ (row['email'] != 'email'): - generateHashAndURL(row) + generateIndividualData(row) createMail(row)