From 994f9b294a8b834b69bb6af8121c0104103e58c9 Mon Sep 17 00:00:00 2001 From: Silvio Rhatto Date: Thu, 10 Feb 2022 13:39:03 -0300 Subject: Feat: minimailer-csv --- minimailer | 1 + minimailer-csv | 130 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 131 insertions(+) create mode 100755 minimailer-csv diff --git a/minimailer b/minimailer index 8eadd8a..29e30d2 100755 --- a/minimailer +++ b/minimailer @@ -41,6 +41,7 @@ MSMTP_ACCOUNT="$3" # Checks if [ -z "$MSMTP_ACCOUNT" ]; then echo "usage: $BASENAME " + echo "" echo "example: $BASENAME message.tmpl recipients.lst my-provider" echo "check the source code for template and recipient filelist formats" exit 1 diff --git a/minimailer-csv b/minimailer-csv new file mode 100755 index 0000000..802766d --- /dev/null +++ b/minimailer-csv @@ -0,0 +1,130 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# +# Send emails according to a CSV input with fields and templating support. +# +# Copyright (C) 2022 Silvio Rhatto +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published +# by the Free Software Foundation, either version 3 of the License, +# or any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# Dependencies +import argparse +import csv +import sys, os, subprocess + +class MinimailerCSV: + """Send emails according to a CSV input with fields and templating support""" + + def __init__(self, args): + self.args = args + self.data = [] + + if os.path.exists(args.template_file[0]): + with open(args.template_file[0], 'r') as template_file: + self.template = template_file.read() + else: + raise FileNotFoundError('No such file ' + template_file) + + if os.path.exists(args.csv_file[0]): + with open(args.csv_file[0], newline='') as csv_file: + self.csv = csv.DictReader(csv_file, + delimiter=args.delimiter, + quotechar=args.quotechar, + ) + + for row in self.csv: + self.data.append(row) + + else: + raise FileNotFoundError('No such file ' + csv_file) + + def send(self): + for item in self.data: + print('sending message to {}'.format(item[self.args.recipient_field_address])) + + message = self.template.format(**item) + + with subprocess.Popen('{sendmail} {recipient}'.format( + message=message, + sendmail=self.args.sendmail_command, + recipient=item[self.args.recipient_field_address], + ), text=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, shell=True) as proc: + + proc.stdin.write(message) + proc.stdin.close() + +if __name__ == "__main__": + """Process from CLI""" + + epilog = """Examples: + + minimailer-csv message.tmpl data.csv --sendmail-command 'msmtp -a default' + minimailer-csv message.tmpl data.csv --recipient-field-address 'contact' + """ + + description = 'Send emails according to a CSV input with fields and templating support' + parser = argparse.ArgumentParser( + description=description, + epilog=epilog, + formatter_class=argparse.RawDescriptionHelpFormatter, + ) + + parser.add_argument('template_file', nargs=1, help='Message template filename') + parser.add_argument('csv_file', nargs=1, help='CSV filename. It\'s required that the first line in the CSV contain the field names.') + #parser.add_argument('mstmp_account_name', nargs='?', help='MSTMP account name') + + # Defaults + sendmail_command_default = '/usr/bin/msmtp -a default' + recipiend_field_address_default = 'email' + delimiter_default = ',' + quotechar_default = '"' + + parser.add_argument( + '--sendmail-command', + help='Sendmail command invocation. Defaults to ' + sendmail_command_default + ) + + parser.add_argument( + '--recipient-field-address', + help='Email address field in the CSV file. Defaults to ' + recipiend_field_address_default + ) + + parser.add_argument( + '--delimiter', + help='CSV field delimiter. Defaults to' + delimiter_default, + ) + + parser.add_argument( + '--quotechar', + help='CSV quotechar. Defaults to' + quotechar_default, + ) + + # Set defaults + #parser.set_defaults(msmtp_account_name='default') + parser.set_defaults(sendmail_command=sendmail_command_default) + parser.set_defaults(recipiend_field_address=recipiend_field_address_default) + parser.set_defaults(delimiter=delimiter_default) + parser.set_defaults(quotechar=quotechar_default) + + args = parser.parse_args() + + # Dispatch + try: + mailer = MinimailerCSV(args) + + mailer.send() + + except (FileNotFoundError, KeyboardInterrupt, subprocess.SubprocessError) as e: + print(e) + exit(1) -- cgit v1.2.3