]> gitweb.fluxo.info Git - utils-mail.git/commitdiff
Feat: minimailer-csv
authorSilvio Rhatto <rhatto@riseup.net>
Thu, 10 Feb 2022 16:39:03 +0000 (13:39 -0300)
committerSilvio Rhatto <rhatto@riseup.net>
Thu, 10 Feb 2022 16:39:03 +0000 (13:39 -0300)
minimailer
minimailer-csv [new file with mode: 0755]

index 8eadd8ab766a631aea459bc37062419fe9069682..29e30d2c7d60ee3027072d973b0e4fcd9e085351 100755 (executable)
@@ -41,6 +41,7 @@ MSMTP_ACCOUNT="$3"
 # Checks
 if [ -z "$MSMTP_ACCOUNT" ]; then
   echo "usage: $BASENAME <template-file> <recipients-filelist> <msmtp-account-name>"
+  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 (executable)
index 0000000..802766d
--- /dev/null
@@ -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 <rhatto@riseup.net>
+#
+# 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 <http://www.gnu.org/licenses/>.
+
+# 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)