This is an automated email from the ASF dual-hosted git repository.

gstein pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/steve.git

commit a8641e51731935f347eb2fa633ed5179209f7a54
Author: Greg Stein <[email protected]>
AuthorDate: Fri Feb 27 08:04:30 2026 -0600

    feat: add mail-voters.py script for emailing eligible voters
    
    Co-authored-by: aider (openrouter/x-ai/grok-code-fast-1) <[email protected]>
---
 v3/server/bin/mail-voters.py | 96 ++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 96 insertions(+)

diff --git a/v3/server/bin/mail-voters.py b/v3/server/bin/mail-voters.py
new file mode 100644
index 0000000..708cefa
--- /dev/null
+++ b/v3/server/bin/mail-voters.py
@@ -0,0 +1,96 @@
+#!/usr/bin/env python3
+
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+"""
+Script to send emails to all eligible voters for a given election.
+Loads the election, renders an email template for each voter, and sends via 
asfpy.messaging.
+"""
+
+import argparse
+import pathlib
+import logging
+
+import asfpy.messaging
+import steve.election
+
+_LOGGER = logging.getLogger(__name__)
+
+THIS_DIR = pathlib.Path(__file__).resolve().parent
+DB_FNAME = THIS_DIR.parent / 'steve.db'
+
+
+def main(eid, template_file):
+    """
+    Main function to load election, get voters, render emails, and send.
+    """
+    # Load the election
+    election = steve.election.Election(DB_FNAME, eid)
+    
+    # Get metadata for context
+    metadata = election.get_metadata()
+    
+    # Get list of eligible voters
+    voters = election.get_voters_for_email()
+    
+    if not voters:
+        _LOGGER.info(f"No eligible voters found for election {eid}")
+        return
+    
+    # Load the EZT template
+    template = asfpy.messaging.load_template(template_file)  # Assuming 
asfpy.messaging has a load_template method; adjust if needed
+    
+    # Send email to each voter
+    for voter in voters:
+        # Render the template with voter data
+        # Note: This is a skeleton; implement template rendering as needed
+        # Example: rendered_body = template.render({'pid': voter.pid, 'name': 
voter.name, 'email': voter.email, 'election': metadata})
+        rendered_body = f"Dear {voter.name},\n\nThis is a test email for 
election {metadata.title}.\n\nRegards,\nElection System"
+        
+        # Send the email
+        asfpy.messaging.mail(
+            sender="Election System <[email protected]>",  # Adjust sender
+            recipient=voter.email,
+            subject=f"Vote in Election: {metadata.title}",
+            message=rendered_body,
+            # Add other parameters as needed (e.g., auth, headers)
+        )
+        
+        _LOGGER.info(f"Sent email to {voter.email} for election {eid}")
+
+
+if __name__ == '__main__':
+    logging.basicConfig(level=logging.INFO)
+
+    parser = argparse.ArgumentParser(
+        formatter_class=argparse.ArgumentDefaultsHelpFormatter,
+        description="Send emails to eligible voters for a given election."
+    )
+    parser.add_argument(
+        '--eid',
+        required=True,
+        help='Election ID to send emails for.'
+    )
+    parser.add_argument(
+        '--template',
+        required=True,
+        help='Path to the .ezt template file for email body.'
+    )
+    args = parser.parse_args()
+    
+    main(args.eid, args.template)

Reply via email to