Sign inSign up

dogaar/mass-mailer

By dogaar

•Updated over 5 years ago

A mass mailer script for SMTP services.

Image
1

353

dogaar/mass-mailer repository overview

⁠Description

A mass mailer script for SMTP services. If the service imposes a sending quota, then this script pauses and resumes automatically as needed.

⁠Usage

Containers derived from this image are supposed to be bind-mounted to the user's home directory. If you want to restrict access any further, then I recommend that you create another user on your machine just for mass mailing purposes.

Usage:
  docker run --volume "$HOME:/workspace:ro" --rm dogaar/mass-mailer [options] 

Options:
    -c, --config PATH                Absolute path to config file inside $HOME. Default value is "~/config.yaml".
                                     Use ~ for the home directory, and enclose the config filename with ""
                                     to ensure ~ expansion by the container.
    -q, --quota-spent QUOTA_SPENT    Mail-sending quota that has already been spent for current period. 
                                     This option is useful if the online mailing service imposes quotas, 
                                     and if this script is being called more than once for the same 
                                     sending period. Default value is 0.
    -v, --[no-]verbose               Run verbosely.
    -h, --help                       Display this help message and exit.

Usage example:
    docker run --volume "$HOME:/workspace:ro" --rm dogaar/mass-mailer --config "~/config.yaml" --quota-spent 110 --verbose

config.yaml:
------------
mailer_config_file: ~/path/to/mailer-config.yaml
mailing_list_file: ./mailinglist.json
mail:
  subject: Test mail
  body_file: ./email.html # If the file extension is not HTML then the file type is assumed to be plain text.

mailinglist.json:
-----------------
[
  [
    "name",
    "email"
  ],
  [
    "Recipient name",
    "[email protected]"
  ],
  [
    "2nd recipient name",
    "[email protected]"
  ]
]

mailer-config.yaml:
------------------
name: Mail Bridge

# Required
smtp:
  address: 127.0.0.1
  port: 1025
  domain: example.com
  authentication: plain
  enable_starttls_auto: true
  user_name: [email protected]
  password: a_password

# Optional
constraints:
  max_mails_per_period: 300
  period_length_in_seconds: 86400.0 # 1 day

⁠About the resolution of file name arguments

The container script tries to behave like a native script, notably in terms of file name resolution. But there are restrictions for file name arguments:

  • Files must be located within the current user's home directory.
  • File names must be absolute names prefixed with ~.
  • File name arguments must be wrapped in "" in order to defer file name resolution to the container.
  • Also, apparently file paths must not contain symbolic links as I have discovered recently.

⁠Frontend scripts

Although you can call docker run directly, to make this image even more practical you can write a small local frontend script that allows relative filenames as arguments as well, and then formulates the docker run command behind the scenes. Using this image then becomes exactly like calling a local script when working inside the home directory, and this is the recommended way of using this image.

Here is a sample frontend script:

#! /usr/bin/env ruby

# require 'fileutils'
require 'pathname'

# A mass mailer script

APP_VERSION = "1.0.0"

# MODE = :development
MODE = :production

# read the yaml data at the end of this file
require "yaml"; TEXT = YAML.load DATA.read 

def log message
  $stderr.puts "#{message}" if OPTIONS[:verbose]
end

########################################################################
# Command line options and arguments

OPTIONS = {
  config:      nil, # Path relative to home directory
  quota_spent: 0, # Emails already sent for current period
  verbose:     false,
}

require "optparse"

def format_helptext text
  # TODO
end

OptionParser.new do |c|
  c.banner = TEXT[:cli][:description].gsub('$script', $0)
  c.separator ""
  c.separator "Options:"

  c.on("-c", "--config PATH", String,
    *(TEXT[:cli][:options][:config].split("\n").map{|line| line.chomp})) do |e|
    absolute_path = (Pathname.pwd + e).to_s
    home_path = "#{ENV['HOME']}"
    unless absolute_path.index(home_path) == 0
      $stderr.puts "File is outside of home directory" 
      exit 1
    end
    home_relative_path = 
    OPTIONS[:config] = absolute_path[home_path.size + 1, absolute_path.size - home_path.size - 1]
    log "Config file: #{OPTIONS[:config]}"
  end

  c.on("-q", "--quota-spent QUOTA_SPENT", Fixnum,
    *(TEXT[:cli][:options][:quota_spent].split("\n").map{|line| line.chomp})) do |e|
    e = 0 unless e > 0
    OPTIONS[:quota_spent] = e
  end

  c.on("-v", "--[no-]verbose", 
    *(TEXT[:cli][:options][:verbose].split("\n").map{|line| line.chomp})) do |e|
    OPTIONS[:verbose] = e
  end
  c.on("-h", "--help", 
    *(TEXT[:cli][:options][:help].split("\n").map{|line| line.chomp})) do
    puts c.to_s
    exit
  end
  c.separator ""
  c.separator "Usage example:"
  c.separator "    #{TEXT[:cli][:usage_example].gsub '$script', $0 }"
  c.separator ""
end.parse!


########################################################################
# Main

status =
system "docker run --volume \"$HOME:/workspace:ro\" --rm dogaar/mass-mailer --config \"~/#{OPTIONS[:config]}\" --quota-spent #{OPTIONS[:quota_spent]} --verbose"

unless status
  $stderr.puts "Call returned an error." 
end

__END__
# YAML data
#
# Notes:
# * if keys start with ':', then they are read as ruby symbols
# * uses spaces for indentation; tabs are not allowed
# * "|" preserves line breaks in multiline text
# * ">" concatenates adjascent non-empty lines in multiline text

:cli: 
  :description: |
    A mass mailer script for SMTP services. If the service imposes a sending quota, then this script pauses and resumes automatically as needed.
    
    Usage:
        $script [options] 

  :options: 
    :config: |
      Path to config file.

    :quota_spent: |
      Mail-sending quota that has already been spent for current period. 
      This option is useful if the online mailing service imposes quotas, 
      and if this script is being called more than once for the same 
      sending period.

    :verbose: |
      Run verbosely.

    :help: |
      Display this help message and exit.
      
  :usage_example: |
    $script --config config.yaml --quota-spent 110 --verbose

    config.yaml:
    ------------
    mailing_list_file: ./mailinglist.json
    mail:
      subject: Test mail
      body_file: ./email.html
    mailer_config_file: ./mailer.yaml
    
    mailinglist.json:
    -----------------
    [
      [
        "name",
        "email"
      ],
      [
        "Recipient name",
        "[email protected]"
      ],
      [
        "2nd recipient name",
        "[email protected]"
      ]
    ]

    mailer.yaml:
    ------------
    name: Mail Bridge

    # Required
    smtp:
      address: 127.0.0.1
      port: 1025
      domain: example.com
      authentication: plain
      enable_starttls_auto: true
      user_name: [email protected]
      password: a_password

    # Optional
    constraints:
      max_mails_per_period: 300
      period_length_in_seconds: 86400.0 # 1 day

Tag summary

Content type

Image

Digest

Size

37.4 MB

Last updated

over 5 years ago

docker pull dogaar/mass-mailer