# send_mail.py # @author: Abner Coimbre # Copyright (c) 2023 Handmade Cities # ============================ Contributors ========================= # Bug & warning fixes # Jacob Bell (@MysteriousJ) # Asaf Gartner # # Emotional Support # Cucui Ganon Rosario # ========================================================================= # WARNING: send_mail.py requires a companion app.ini file provided by Abner. Without it the script will crash! # QUICK NOTES: # # 1. This script is for Handmade meetup hosts. You can email a meetup invite to your group like so: # # > python3 send_mail.py --subject SUBJECT --body BODY # # where SUBJECT is the subject of your email and BODY is the file containing its contents. Plain text or HTML is supported # # 2. Your emails automatically include fancy Handmade Cities branding with unsubscribe links # # 3. You can dump the mailing list of your meetup group so far: # # > python3 send_mail.py --dump # # This list grows automatically as more people sign up for your city (at handmadecities.com/meetups) import argparse import configparser import requests import json def dump_emails(): headers = { "Content-Type": "application/json", "Authorization": HMC_SHARED_SECRET } target = { "city": HMC_CITY } # Request mailing list from Handmade Cities payload = json.dumps(target) response = requests.post(HMC_API_URL, headers=headers, data=payload) emails = [] # Check if the request was successful (HTTP status code 200) if response.status_code == 200: # Parse the JSON response response_json = response.json() # Check if the 'emails' key exists in the response if 'emails' in response_json: # Extract the 'emails' JSON array emails = response_json['emails'] return emails def sendPostmarkMessage(subject, body, to): headers = { "Accept": "application/json", "Content-Type": "application/json", "X-Postmark-Server-Token": POSTMARK_SERVER_TOKEN } messages = [] # Postmark supports 500 messages per API call. # Split the 'to' list into chunks of 500 or fewer email addresses for i in range(0, len(to), 500): to_chunk = to[i:i+500] for email in to_chunk: message = { "From": POSTMARK_SENDER_EMAIL, "To": email, "TemplateId": POSTMARK_TEMPLATE_ID, "TemplateModel": { "name": SENDER_NAME, "email": POSTMARK_SENDER_EMAIL, "body": body, "subject": subject }, "MessageStream": POSTMARK_MESSAGE_STREAM } messages.append(message) payload = { "Messages": messages } # Debug: # print(json.dumps(payload, indent=4)) result = requests.post(POSTMARK_API_URL, headers=headers, json=payload) print(result.text) # Clear the messages list for the next chunk messages.clear() if __name__ == '__main__': # Create a ConfigParser object and read the INI file config = configparser.ConfigParser() config.read('app.ini') # Read the values and store them in Python variables LIVE = config.getboolean('DEFAULT', 'LIVE') TEST_EMAIL = config.get('DEFAULT', 'TEST_EMAIL') SENDER_NAME = config.get('DEFAULT', 'SENDER_NAME') postmark_section = config['postmark'] POSTMARK_SERVER_TOKEN = postmark_section.get('SERVER_TOKEN') POSTMARK_API_URL = postmark_section.get('API_URL') POSTMARK_TEMPLATE_ID = int(postmark_section.get('TEMPLATE_ID')) POSTMARK_SENDER_EMAIL = postmark_section.get('SENDER_EMAIL') POSTMARK_MESSAGE_STREAM = postmark_section.get('MESSAGE_STREAM') hmc_section = config['hmc'] HMC_API_URL = hmc_section.get('API_URL') HMC_SHARED_SECRET = hmc_section.get('SHARED_SECRET') HMC_CITY = hmc_section.get('CITY') # Parse command-line arguments parser = argparse.ArgumentParser(description="Handmade Meetups v0.1 (handmadecities.com/meetups)") parser.add_argument("--dump", action="store_true", help="print the emails of your meetup group") parser.add_argument("--subject", help="subject of the email you're about to send") parser.add_argument("--body", help="path to the email body content file. HTML or plain text is supported") args = parser.parse_args() # Main: meetup_group = [] if args.dump: meetup_group = dump_emails() for email in meetup_group: print(email) elif args.subject and args.body: subject = args.subject body = '' with open(args.body, 'r') as file: body = file.read() if LIVE: meetup_group = dump_emails() sendPostmarkMessage(subject, body, meetup_group) else: meetup_group.append(TEST_EMAIL) # Send a single email to whichever address is in TEST_EMAIL sendPostmarkMessage(subject, body, meetup_group) else: parser.print_help()