commit
eb2bdc8db9
133 changed files with 15657 additions and 0 deletions
@ -0,0 +1 @@ |
|||||
|
ruby-3.0.6 |
||||
@ -0,0 +1,79 @@ |
|||||
|
source "https://rubygems.org" |
||||
|
git_source(:github) { |repo| "https://github.com/#{repo}.git" } |
||||
|
|
||||
|
ruby "3.1.4" |
||||
|
|
||||
|
|
||||
|
# Bundle edge Rails instead: gem "rails", github: "rails/rails", branch: "main" |
||||
|
gem "rails", "~> 7.0.8", ">= 7.0.8.1" |
||||
|
|
||||
|
# The original asset pipeline for Rails [https://github.com/rails/sprockets-rails] |
||||
|
gem "sprockets-rails" |
||||
|
|
||||
|
# Use sqlite3 as the database for Active Record |
||||
|
gem "sqlite3", "~> 1.4" |
||||
|
gem "json" |
||||
|
gem "mysql2" |
||||
|
|
||||
|
# Use the Puma web server [https://github.com/puma/puma] |
||||
|
gem "puma" |
||||
|
|
||||
|
# Use JavaScript with ESM import maps [https://github.com/rails/importmap-rails] |
||||
|
gem "importmap-rails" |
||||
|
|
||||
|
# Hotwire's SPA-like page accelerator [https://turbo.hotwired.dev] |
||||
|
gem "turbo-rails" |
||||
|
|
||||
|
# Hotwire's modest JavaScript framework [https://stimulus.hotwired.dev] |
||||
|
gem "stimulus-rails" |
||||
|
|
||||
|
# Build JSON APIs with ease [https://github.com/rails/jbuilder] |
||||
|
gem "jbuilder" |
||||
|
|
||||
|
# Use Redis adapter to run Action Cable in production |
||||
|
gem "redis", "~> 4.0" |
||||
|
|
||||
|
# Use Kredis to get higher-level data types in Redis [https://github.com/rails/kredis] |
||||
|
# gem "kredis" |
||||
|
|
||||
|
# Use Active Model has_secure_password [https://guides.rubyonrails.org/active_model_basics.html#securepassword] |
||||
|
# gem "bcrypt", "~> 3.1.7" |
||||
|
|
||||
|
# Windows does not include zoneinfo files, so bundle the tzinfo-data gem |
||||
|
gem "tzinfo-data", platforms: %i[ mingw mswin x64_mingw jruby ] |
||||
|
|
||||
|
# Reduces boot times through caching; required in config/boot.rb |
||||
|
gem "bootsnap", require: false |
||||
|
gem 'pagy', '~> 9.2' |
||||
|
gem 'bootstrap', '~> 5.3.3' |
||||
|
gem "sass-rails", "~> 6.0" |
||||
|
gem "jquery-rails", "~> 4.6" |
||||
|
|
||||
|
# Use Sass to process CSS |
||||
|
# gem "sassc-rails" |
||||
|
|
||||
|
# Use Active Storage variants [https://guides.rubyonrails.org/active_storage_overview.html#transforming-images] |
||||
|
# gem "image_processing", "~> 1.2" |
||||
|
|
||||
|
group :development, :test do |
||||
|
# See https://guides.rubyonrails.org/debugging_rails_applications.html#debugging-with-the-debug-gem |
||||
|
gem "debug", platforms: %i[ mri mingw x64_mingw ] |
||||
|
end |
||||
|
|
||||
|
group :development do |
||||
|
# Use console on exceptions pages [https://github.com/rails/web-console] |
||||
|
gem "web-console" |
||||
|
|
||||
|
# Add speed badges [https://github.com/MiniProfiler/rack-mini-profiler] |
||||
|
# gem "rack-mini-profiler" |
||||
|
|
||||
|
# Speed up commands on slow machines / big apps [https://github.com/rails/spring] |
||||
|
# gem "spring" |
||||
|
end |
||||
|
|
||||
|
group :test do |
||||
|
# Use system testing [https://guides.rubyonrails.org/testing.html#system-testing] |
||||
|
gem "capybara" |
||||
|
gem "selenium-webdriver" |
||||
|
|
||||
|
end |
||||
@ -0,0 +1,277 @@ |
|||||
|
GEM |
||||
|
remote: https://rubygems.org/ |
||||
|
specs: |
||||
|
actioncable (7.0.8.4) |
||||
|
actionpack (= 7.0.8.4) |
||||
|
activesupport (= 7.0.8.4) |
||||
|
nio4r (~> 2.0) |
||||
|
websocket-driver (>= 0.6.1) |
||||
|
actionmailbox (7.0.8.4) |
||||
|
actionpack (= 7.0.8.4) |
||||
|
activejob (= 7.0.8.4) |
||||
|
activerecord (= 7.0.8.4) |
||||
|
activestorage (= 7.0.8.4) |
||||
|
activesupport (= 7.0.8.4) |
||||
|
mail (>= 2.7.1) |
||||
|
net-imap |
||||
|
net-pop |
||||
|
net-smtp |
||||
|
actionmailer (7.0.8.4) |
||||
|
actionpack (= 7.0.8.4) |
||||
|
actionview (= 7.0.8.4) |
||||
|
activejob (= 7.0.8.4) |
||||
|
activesupport (= 7.0.8.4) |
||||
|
mail (~> 2.5, >= 2.5.4) |
||||
|
net-imap |
||||
|
net-pop |
||||
|
net-smtp |
||||
|
rails-dom-testing (~> 2.0) |
||||
|
actionpack (7.0.8.4) |
||||
|
actionview (= 7.0.8.4) |
||||
|
activesupport (= 7.0.8.4) |
||||
|
rack (~> 2.0, >= 2.2.4) |
||||
|
rack-test (>= 0.6.3) |
||||
|
rails-dom-testing (~> 2.0) |
||||
|
rails-html-sanitizer (~> 1.0, >= 1.2.0) |
||||
|
actiontext (7.0.8.4) |
||||
|
actionpack (= 7.0.8.4) |
||||
|
activerecord (= 7.0.8.4) |
||||
|
activestorage (= 7.0.8.4) |
||||
|
activesupport (= 7.0.8.4) |
||||
|
globalid (>= 0.6.0) |
||||
|
nokogiri (>= 1.8.5) |
||||
|
actionview (7.0.8.4) |
||||
|
activesupport (= 7.0.8.4) |
||||
|
builder (~> 3.1) |
||||
|
erubi (~> 1.4) |
||||
|
rails-dom-testing (~> 2.0) |
||||
|
rails-html-sanitizer (~> 1.1, >= 1.2.0) |
||||
|
activejob (7.0.8.4) |
||||
|
activesupport (= 7.0.8.4) |
||||
|
globalid (>= 0.3.6) |
||||
|
activemodel (7.0.8.4) |
||||
|
activesupport (= 7.0.8.4) |
||||
|
activerecord (7.0.8.4) |
||||
|
activemodel (= 7.0.8.4) |
||||
|
activesupport (= 7.0.8.4) |
||||
|
activestorage (7.0.8.4) |
||||
|
actionpack (= 7.0.8.4) |
||||
|
activejob (= 7.0.8.4) |
||||
|
activerecord (= 7.0.8.4) |
||||
|
activesupport (= 7.0.8.4) |
||||
|
marcel (~> 1.0) |
||||
|
mini_mime (>= 1.1.0) |
||||
|
activesupport (7.0.8.4) |
||||
|
concurrent-ruby (~> 1.0, >= 1.0.2) |
||||
|
i18n (>= 1.6, < 2) |
||||
|
minitest (>= 5.1) |
||||
|
tzinfo (~> 2.0) |
||||
|
addressable (2.8.6) |
||||
|
public_suffix (>= 2.0.2, < 6.0) |
||||
|
autoprefixer-rails (10.4.19.0) |
||||
|
execjs (~> 2) |
||||
|
base64 (0.2.0) |
||||
|
bindex (0.8.1) |
||||
|
bootsnap (1.18.3) |
||||
|
msgpack (~> 1.2) |
||||
|
bootstrap (5.3.3) |
||||
|
autoprefixer-rails (>= 9.1.0) |
||||
|
popper_js (>= 2.11.8, < 3) |
||||
|
builder (3.3.0) |
||||
|
capybara (3.40.0) |
||||
|
addressable |
||||
|
matrix |
||||
|
mini_mime (>= 0.1.3) |
||||
|
nokogiri (~> 1.11) |
||||
|
rack (>= 1.6.0) |
||||
|
rack-test (>= 0.6.3) |
||||
|
regexp_parser (>= 1.5, < 3.0) |
||||
|
xpath (~> 3.2) |
||||
|
concurrent-ruby (1.3.3) |
||||
|
crass (1.0.6) |
||||
|
date (3.3.4) |
||||
|
debug (1.9.2) |
||||
|
irb (~> 1.10) |
||||
|
reline (>= 0.3.8) |
||||
|
erubi (1.12.0) |
||||
|
execjs (2.10.0) |
||||
|
ffi (1.17.0-x86_64-linux-gnu) |
||||
|
font-awesome-rails (4.7.0.9) |
||||
|
railties (>= 3.2, < 9.0) |
||||
|
globalid (1.2.1) |
||||
|
activesupport (>= 6.1) |
||||
|
i18n (1.14.5) |
||||
|
concurrent-ruby (~> 1.0) |
||||
|
importmap-rails (2.0.1) |
||||
|
actionpack (>= 6.0.0) |
||||
|
activesupport (>= 6.0.0) |
||||
|
railties (>= 6.0.0) |
||||
|
io-console (0.7.2) |
||||
|
irb (1.13.1) |
||||
|
rdoc (>= 4.0.0) |
||||
|
reline (>= 0.4.2) |
||||
|
jbuilder (2.12.0) |
||||
|
actionview (>= 5.0.0) |
||||
|
activesupport (>= 5.0.0) |
||||
|
jquery-rails (4.6.0) |
||||
|
rails-dom-testing (>= 1, < 3) |
||||
|
railties (>= 4.2.0) |
||||
|
thor (>= 0.14, < 2.0) |
||||
|
json (2.7.2) |
||||
|
loofah (2.22.0) |
||||
|
crass (~> 1.0.2) |
||||
|
nokogiri (>= 1.12.0) |
||||
|
mail (2.8.1) |
||||
|
mini_mime (>= 0.1.1) |
||||
|
net-imap |
||||
|
net-pop |
||||
|
net-smtp |
||||
|
marcel (1.0.4) |
||||
|
matrix (0.4.2) |
||||
|
method_source (1.1.0) |
||||
|
mini_mime (1.1.5) |
||||
|
minitest (5.23.1) |
||||
|
msgpack (1.7.2) |
||||
|
mysql2 (0.5.6) |
||||
|
net-imap (0.4.12) |
||||
|
date |
||||
|
net-protocol |
||||
|
net-pop (0.1.2) |
||||
|
net-protocol |
||||
|
net-protocol (0.2.2) |
||||
|
timeout |
||||
|
net-smtp (0.5.0) |
||||
|
net-protocol |
||||
|
nio4r (2.7.3) |
||||
|
nokogiri (1.16.5-x86_64-linux) |
||||
|
racc (~> 1.4) |
||||
|
pagy (9.2.2) |
||||
|
popper_js (2.11.8) |
||||
|
psych (5.1.2) |
||||
|
stringio |
||||
|
public_suffix (5.0.5) |
||||
|
puma (6.4.2) |
||||
|
nio4r (~> 2.0) |
||||
|
racc (1.8.0) |
||||
|
rack (2.2.9) |
||||
|
rack-test (2.1.0) |
||||
|
rack (>= 1.3) |
||||
|
rails (7.0.8.4) |
||||
|
actioncable (= 7.0.8.4) |
||||
|
actionmailbox (= 7.0.8.4) |
||||
|
actionmailer (= 7.0.8.4) |
||||
|
actionpack (= 7.0.8.4) |
||||
|
actiontext (= 7.0.8.4) |
||||
|
actionview (= 7.0.8.4) |
||||
|
activejob (= 7.0.8.4) |
||||
|
activemodel (= 7.0.8.4) |
||||
|
activerecord (= 7.0.8.4) |
||||
|
activestorage (= 7.0.8.4) |
||||
|
activesupport (= 7.0.8.4) |
||||
|
bundler (>= 1.15.0) |
||||
|
railties (= 7.0.8.4) |
||||
|
rails-dom-testing (2.2.0) |
||||
|
activesupport (>= 5.0.0) |
||||
|
minitest |
||||
|
nokogiri (>= 1.6) |
||||
|
rails-html-sanitizer (1.6.0) |
||||
|
loofah (~> 2.21) |
||||
|
nokogiri (~> 1.14) |
||||
|
railties (7.0.8.4) |
||||
|
actionpack (= 7.0.8.4) |
||||
|
activesupport (= 7.0.8.4) |
||||
|
method_source |
||||
|
rake (>= 12.2) |
||||
|
thor (~> 1.0) |
||||
|
zeitwerk (~> 2.5) |
||||
|
rake (13.2.1) |
||||
|
rdoc (6.7.0) |
||||
|
psych (>= 4.0.0) |
||||
|
redis (4.8.1) |
||||
|
regexp_parser (2.9.2) |
||||
|
reline (0.5.8) |
||||
|
io-console (~> 0.5) |
||||
|
rexml (3.3.0) |
||||
|
strscan |
||||
|
rubyzip (2.3.2) |
||||
|
sass-rails (6.0.0) |
||||
|
sassc-rails (~> 2.1, >= 2.1.1) |
||||
|
sassc (2.4.0) |
||||
|
ffi (~> 1.9) |
||||
|
sassc-rails (2.1.2) |
||||
|
railties (>= 4.0.0) |
||||
|
sassc (>= 2.0) |
||||
|
sprockets (> 3.0) |
||||
|
sprockets-rails |
||||
|
tilt |
||||
|
selenium-webdriver (4.21.1) |
||||
|
base64 (~> 0.2) |
||||
|
rexml (~> 3.2, >= 3.2.5) |
||||
|
rubyzip (>= 1.2.2, < 3.0) |
||||
|
websocket (~> 1.0) |
||||
|
sprockets (4.2.1) |
||||
|
concurrent-ruby (~> 1.0) |
||||
|
rack (>= 2.2.4, < 4) |
||||
|
sprockets-rails (3.5.1) |
||||
|
actionpack (>= 6.1) |
||||
|
activesupport (>= 6.1) |
||||
|
sprockets (>= 3.0.0) |
||||
|
sqlite3 (1.7.3-x86_64-linux) |
||||
|
stimulus-rails (1.3.3) |
||||
|
railties (>= 6.0.0) |
||||
|
stringio (3.1.0) |
||||
|
strscan (3.1.0) |
||||
|
thor (1.3.1) |
||||
|
tilt (2.4.0) |
||||
|
timeout (0.4.1) |
||||
|
turbo-rails (2.0.5) |
||||
|
actionpack (>= 6.0.0) |
||||
|
activejob (>= 6.0.0) |
||||
|
railties (>= 6.0.0) |
||||
|
tzinfo (2.0.6) |
||||
|
concurrent-ruby (~> 1.0) |
||||
|
web-console (4.2.1) |
||||
|
actionview (>= 6.0.0) |
||||
|
activemodel (>= 6.0.0) |
||||
|
bindex (>= 0.4.0) |
||||
|
railties (>= 6.0.0) |
||||
|
websocket (1.2.10) |
||||
|
websocket-driver (0.7.6) |
||||
|
websocket-extensions (>= 0.1.0) |
||||
|
websocket-extensions (0.1.5) |
||||
|
xpath (3.2.0) |
||||
|
nokogiri (~> 1.8) |
||||
|
zeitwerk (2.6.15) |
||||
|
|
||||
|
PLATFORMS |
||||
|
x86_64-linux |
||||
|
|
||||
|
DEPENDENCIES |
||||
|
bootsnap |
||||
|
bootstrap (~> 5.3.3) |
||||
|
capybara |
||||
|
debug |
||||
|
font-awesome-rails |
||||
|
importmap-rails |
||||
|
jbuilder |
||||
|
jquery-rails (~> 4.6) |
||||
|
json |
||||
|
mysql2 |
||||
|
pagy (~> 9.2) |
||||
|
puma |
||||
|
rails (~> 7.0.8, >= 7.0.8.1) |
||||
|
redis (~> 4.0) |
||||
|
sass-rails (~> 6.0) |
||||
|
selenium-webdriver |
||||
|
sprockets-rails |
||||
|
sqlite3 (~> 1.4) |
||||
|
stimulus-rails |
||||
|
turbo-rails |
||||
|
tzinfo-data |
||||
|
web-console |
||||
|
|
||||
|
RUBY VERSION |
||||
|
ruby 3.1.4p223 |
||||
|
|
||||
|
BUNDLED WITH |
||||
|
2.3.26 |
||||
@ -0,0 +1,15 @@ |
|||||
|
Postal mail reports app |
||||
|
|
||||
|
|
||||
|
# Usage |
||||
|
|
||||
|
``` |
||||
|
# install dependencies |
||||
|
bundle install |
||||
|
|
||||
|
# Start server |
||||
|
rails s |
||||
|
``` |
||||
|
|
||||
|
|
||||
|
|
||||
@ -0,0 +1,6 @@ |
|||||
|
# Add your own tasks in files placed in lib/tasks ending in .rake, |
||||
|
# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. |
||||
|
|
||||
|
require_relative "config/application" |
||||
|
|
||||
|
Rails.application.load_tasks |
||||
@ -0,0 +1,4 @@ |
|||||
|
//= link_tree ../images
|
||||
|
//= link_directory ../stylesheets .css
|
||||
|
//= link_tree ../../javascript .js
|
||||
|
//= link_tree ../../../vendor/javascript .js
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
@ -0,0 +1,17 @@ |
|||||
|
/* |
||||
|
* This is a manifest file that'll be compiled into application.css, which will include all the files |
||||
|
* listed below. |
||||
|
* |
||||
|
* Any CSS (and SCSS, if configured) file within this directory, lib/assets/stylesheets, or any plugin's |
||||
|
* vendor/assets/stylesheets directory can be referenced here using a relative path. |
||||
|
* |
||||
|
* You're free to add application-wide styles to this file and they'll appear at the bottom of the |
||||
|
* compiled file so the styles you add here take precedence over styles defined in any other CSS |
||||
|
* files in this directory. Styles in this file should be added after the last require_* statement. |
||||
|
* It is generally better to create a new file per style scope. |
||||
|
* |
||||
|
*= require_tree . |
||||
|
*= require_self |
||||
|
*/ |
||||
|
|
||||
|
@import "semantic-ui"; |
||||
@ -0,0 +1,30 @@ |
|||||
|
/* |
||||
|
* This is a manifest file that'll be compiled into application.css, which will include all the files |
||||
|
* listed below. |
||||
|
* |
||||
|
* Any CSS (and SCSS, if configured) file within this directory, lib/assets/stylesheets, or any plugin's |
||||
|
* vendor/assets/stylesheets directory can be referenced here using a relative path. |
||||
|
* |
||||
|
* You're free to add application-wide styles to this file and they'll appear at the bottom of the |
||||
|
* compiled file so the styles you add here take precedence over styles defined in any other CSS |
||||
|
* files in this directory. Styles in this file should be added after the last require_* statement. |
||||
|
* It is generally better to create a new file per style scope. |
||||
|
* |
||||
|
*= require_tree . |
||||
|
*= require_self |
||||
|
*/ |
||||
|
@import "bootstrap"; |
||||
|
|
||||
|
|
||||
|
.easypush-nav { |
||||
|
background-color: #e8f1ff; |
||||
|
color: #006666; |
||||
|
} |
||||
|
|
||||
|
body { |
||||
|
color: #1a000d; |
||||
|
} |
||||
|
|
||||
|
.table-color { |
||||
|
color: #1a000d; |
||||
|
} |
||||
@ -0,0 +1 @@ |
|||||
|
|
||||
@ -0,0 +1,4 @@ |
|||||
|
module ApplicationCable |
||||
|
class Channel < ActionCable::Channel::Base |
||||
|
end |
||||
|
end |
||||
@ -0,0 +1,4 @@ |
|||||
|
module ApplicationCable |
||||
|
class Connection < ActionCable::Connection::Base |
||||
|
end |
||||
|
end |
||||
Binary file not shown.
Binary file not shown.
@ -0,0 +1,3 @@ |
|||||
|
class ApplicationController < ActionController::Base |
||||
|
include Pagy::Backend |
||||
|
end |
||||
@ -0,0 +1,70 @@ |
|||||
|
class DeliveriesController < ApplicationController |
||||
|
before_action :set_delivery, only: %i[ show edit update destroy ] |
||||
|
|
||||
|
# GET /deliveries or /deliveries.json |
||||
|
def index |
||||
|
@deliveries = Delivery.all |
||||
|
end |
||||
|
|
||||
|
# GET /deliveries/1 or /deliveries/1.json |
||||
|
def show |
||||
|
end |
||||
|
|
||||
|
# GET /deliveries/new |
||||
|
def new |
||||
|
@delivery = Delivery.new |
||||
|
end |
||||
|
|
||||
|
# GET /deliveries/1/edit |
||||
|
def edit |
||||
|
end |
||||
|
|
||||
|
# POST /deliveries or /deliveries.json |
||||
|
def create |
||||
|
@delivery = Delivery.new(delivery_params) |
||||
|
|
||||
|
respond_to do |format| |
||||
|
if @delivery.save |
||||
|
format.html { redirect_to delivery_url(@delivery), notice: "Delivery was successfully created." } |
||||
|
format.json { render :show, status: :created, location: @delivery } |
||||
|
else |
||||
|
format.html { render :new, status: :unprocessable_entity } |
||||
|
format.json { render json: @delivery.errors, status: :unprocessable_entity } |
||||
|
end |
||||
|
end |
||||
|
end |
||||
|
|
||||
|
# PATCH/PUT /deliveries/1 or /deliveries/1.json |
||||
|
def update |
||||
|
respond_to do |format| |
||||
|
if @delivery.update(delivery_params) |
||||
|
format.html { redirect_to delivery_url(@delivery), notice: "Delivery was successfully updated." } |
||||
|
format.json { render :show, status: :ok, location: @delivery } |
||||
|
else |
||||
|
format.html { render :edit, status: :unprocessable_entity } |
||||
|
format.json { render json: @delivery.errors, status: :unprocessable_entity } |
||||
|
end |
||||
|
end |
||||
|
end |
||||
|
|
||||
|
# DELETE /deliveries/1 or /deliveries/1.json |
||||
|
def destroy |
||||
|
@delivery.destroy |
||||
|
|
||||
|
respond_to do |format| |
||||
|
format.html { redirect_to deliveries_url, notice: "Delivery was successfully destroyed." } |
||||
|
format.json { head :no_content } |
||||
|
end |
||||
|
end |
||||
|
|
||||
|
private |
||||
|
# Use callbacks to share common setup or constraints between actions. |
||||
|
def set_delivery |
||||
|
@delivery = Delivery.find(params[:id]) |
||||
|
end |
||||
|
|
||||
|
# Only allow a list of trusted parameters through. |
||||
|
def delivery_params |
||||
|
params.require(:delivery).permit(:message_id, :status, :code, :output, :details, :sent_with_ssl, :log_id, :timestamp, :time) |
||||
|
end |
||||
|
end |
||||
@ -0,0 +1,4 @@ |
|||||
|
class HomeController < ApplicationController |
||||
|
def index |
||||
|
end |
||||
|
end |
||||
@ -0,0 +1,104 @@ |
|||||
|
class MessagesController < ApplicationController |
||||
|
before_action :set_message, only: %i[ show ] |
||||
|
|
||||
|
# GET /messages or /messages.json |
||||
|
def index |
||||
|
@search_term="" |
||||
|
all_mail = Message.select("messages.id,messages.message_id,messages.token,messages.mail_from,messages.rcpt_to,messages.subject,messages.timestamp,messages.last_delivery_attempt,messages.size,messages.status,deliveries.details").joins("INNER JOIN deliveries ON messages.id=deliveries.message_id") |
||||
|
from = params[:mail_from] |
||||
|
to = params[:rcpt_to] |
||||
|
if !params[:date_to].nil? |
||||
|
date_to = Time.parse(params[:date_to]).to_i.to_s if !params[:date_to].empty? |
||||
|
to_next_day = (Time.parse(params[:date_to]).to_i + 86400).to_s if !params[:date_to].empty? |
||||
|
end |
||||
|
if !params[:date_to].nil? |
||||
|
date_from = Time.parse(params[:date_from]).to_i.to_s if !params[:date_from].empty? |
||||
|
from_next_day = (Time.parse(params[:date_from]).to_i + 86400).to_s if !params[:date_from].empty? |
||||
|
end |
||||
|
status = params[:status] |
||||
|
from ||= '' |
||||
|
to ||= '' |
||||
|
|
||||
|
if !from.blank? |
||||
|
@search_term << 'messages.mail_from="'+from+'"' |
||||
|
end |
||||
|
|
||||
|
if !to.blank? |
||||
|
if !@search_term.empty? |
||||
|
@search_term << " AND " |
||||
|
end |
||||
|
@search_term << 'messages.rcpt_to="'+to+'"' |
||||
|
puts "search term is #{@search_term}" |
||||
|
end |
||||
|
|
||||
|
if !date_to.nil? |
||||
|
if !@search_term.empty? |
||||
|
@search_term << " AND " |
||||
|
end |
||||
|
if params[:date_from].nil? or params[:date_from].empty? |
||||
|
@search_term << 'messages.timestamp>'+date_to+" AND messages.timestamp<"+ to_next_day |
||||
|
else |
||||
|
@search_term << 'messages.timestamp<='+date_to |
||||
|
end |
||||
|
end |
||||
|
|
||||
|
if !date_from.nil? |
||||
|
if !@search_term.empty? |
||||
|
@search_term << " AND " |
||||
|
end |
||||
|
if params[:date_to].nil? or params[:date_to].empty? |
||||
|
@search_term << 'messages.timestamp>'+date_from+" AND messages.timestamp<"+ from_next_day |
||||
|
else |
||||
|
@search_term << 'messages.timestamp>='+date_from |
||||
|
end |
||||
|
end |
||||
|
|
||||
|
if params[:status].blank? |
||||
|
params[:status] = 'All' |
||||
|
end |
||||
|
|
||||
|
if params[:status] != "All" and @search_term.blank? |
||||
|
@search_term << 'messages.status="'+params[:status]+'"' |
||||
|
elsif status != "All" and !@search_term.blank? |
||||
|
@search_term << ' AND messages.status="'+params[:status]+'"' |
||||
|
end |
||||
|
|
||||
|
if @search_term.blank? |
||||
|
mail = all_mail |
||||
|
else |
||||
|
mail = all_mail.where("#{@search_term}") |
||||
|
end |
||||
|
@@results = mail |
||||
|
@pagy, @messages = pagy(mail.order(id: :desc)) |
||||
|
end |
||||
|
|
||||
|
# GET /messages/1 or /messages/1.json |
||||
|
def show |
||||
|
end |
||||
|
|
||||
|
def export |
||||
|
if File.file?("#{Rails.root}/mail_delivery_report.csv") |
||||
|
File.delete("#{Rails.root}/mail_delivery_report.csv") |
||||
|
end |
||||
|
|
||||
|
file = File.open("mail_delivery_report.csv", "a") |
||||
|
file.write("ID|SENDER|RECIPIENT|SUBJECT|DATE|TIME|SIZE|STATUS|DELIVERY DETAILS\n") |
||||
|
@@results.each do |mail| |
||||
|
file.write("#{mail.id}|#{mail.mail_from}|#{mail.rcpt_to}|#{mail.subject}|#{Time.at(mail.timestamp).strftime('%d-%m-%Y')}|#{Time.at(mail.timestamp).strftime('%H:%M:%S')}|#{ mail.size.to_f >= 1048576 ? "#{(mail.size.to_d/1048576).round(2)} MB" : "#{(mail.size.to_d/1024).round(2)} KB" }|#{mail.status}|#{mail.details}\n") |
||||
|
end |
||||
|
file.close |
||||
|
send_file("#{Rails.root}/mail_delivery_report.csv") |
||||
|
end |
||||
|
|
||||
|
# POST /messages or /messages.json |
||||
|
private |
||||
|
# Use callbacks to share common setup or constraints between actions. |
||||
|
def set_message |
||||
|
@message = Message.find(params[:id]) |
||||
|
end |
||||
|
|
||||
|
# Only allow a list of trusted parameters through. |
||||
|
def message_params |
||||
|
params.require(:message).permit(:token, :scope, :rcpt_to, :mail_from, :subject, :message_id, :timestamp, :route_id, :domain_id, :credential_id, :status, :held, :size, :last_delivery_attempt, :raw_table, :raw_body_id, :raw_headers_id, :inspected, :spam, :spam_score, :threat, :threat_details, :bounce, :bounce_for_id, :tag, :loaded, :clicked, :received_with_ssl, :hold_expiry, :tracked_links, :tracked_images, :parsed, :endpoint_id, :endpoint_type) |
||||
|
end |
||||
|
end |
||||
@ -0,0 +1,88 @@ |
|||||
|
class ReportsController < ApplicationController |
||||
|
attr_reader :report |
||||
|
def initialize |
||||
|
@search_term="" |
||||
|
end |
||||
|
|
||||
|
def search |
||||
|
from = params[:mail_from] |
||||
|
to = params[:rcpt_to] |
||||
|
if !params[:date_to].nil? |
||||
|
date_to = Time.parse(params[:date_to]).to_i.to_s if !params[:date_to].empty? |
||||
|
to_next_day = (Time.parse(params[:date_to]).to_i + 86400).to_s if !params[:date_to].empty? |
||||
|
end |
||||
|
if !params[:date_to].nil? |
||||
|
date_from = Time.parse(params[:date_from]).to_i.to_s if !params[:date_from].empty? |
||||
|
from_next_day = (Time.parse(params[:date_from]).to_i + 86400).to_s if !params[:date_from].empty? |
||||
|
end |
||||
|
status = params[:status] |
||||
|
from ||= '' |
||||
|
to ||= '' |
||||
|
|
||||
|
if !from.empty? |
||||
|
@search_term << 'messages.mail_from="'+from+'"' |
||||
|
end |
||||
|
|
||||
|
if !to.empty? |
||||
|
if !@search_term.empty? |
||||
|
@search_term << " AND " |
||||
|
end |
||||
|
@search_term << 'messages.rcpt_to="'+to+'"' |
||||
|
puts "search term is #{@search_term}" |
||||
|
end |
||||
|
|
||||
|
if !date_to.nil? |
||||
|
if !@search_term.empty? |
||||
|
@search_term << " AND " |
||||
|
end |
||||
|
if params[:date_from].nil? or params[:date_from].empty? |
||||
|
@search_term << 'messages.timestamp>'+date_to+" AND messages.timestamp<"+ to_next_day |
||||
|
else |
||||
|
@search_term << 'messages.timestamp<='+date_to |
||||
|
end |
||||
|
end |
||||
|
|
||||
|
if !date_from.nil? |
||||
|
if !@search_term.empty? |
||||
|
@search_term << " AND " |
||||
|
end |
||||
|
if params[:date_to].nil? or params[:date_to].empty? |
||||
|
@search_term << 'messages.timestamp>'+date_from+" AND messages.timestamp<"+ from_next_day |
||||
|
else |
||||
|
@search_term << 'messages.timestamp>='+date_from |
||||
|
end |
||||
|
end |
||||
|
|
||||
|
if status != "All" and @search_term.empty? |
||||
|
@search_term << 'messages.status="'+status+'"' |
||||
|
elsif status != "All" and !@search_term.empty? |
||||
|
@search_term << ' AND messages.status="'+status+'"' |
||||
|
end |
||||
|
puts "search term is #{@search_term}" |
||||
|
|
||||
|
@@report_search = Report.find(@search_term) |
||||
|
p @query_report |
||||
|
@query_report = Report.find(@search_term) |
||||
|
end |
||||
|
|
||||
|
def export |
||||
|
if File.file?("#{Rails.root}/mail_delivery_report.csv") |
||||
|
File.delete("#{Rails.root}/mail_delivery_report.csv") |
||||
|
end |
||||
|
|
||||
|
file = File.open("mail_delivery_report.csv", "a") |
||||
|
file.write("ID|SENDER|RECIPIENT|SUBJECT|DATE|TIME|SIZE|STATUS|DELIVERY DETAILS\n") |
||||
|
@@report_search.each(:as => :hash) do |mail| |
||||
|
file.write("#{mail['message_id']}|#{mail['mail_from']}|#{mail['rcpt_to']}|#{mail['subject']}|#{Time.at(mail['timestamp']).strftime('%d-%m-%Y')}|#{Time.at(mail['timestamp']).strftime('%H:%M:%S')}|#{ mail['size'].to_f >= 1048576 ? "#{(mail['size'].to_d/1048576).round(2)} MB" : "#{(mail['size'].to_d/1024).round(2)} KB" }|#{mail['status']}|#{mail['details']}\n") |
||||
|
end |
||||
|
file.close |
||||
|
send_file("#{Rails.root}/mail_delivery_report.csv") |
||||
|
end |
||||
|
|
||||
|
|
||||
|
def index |
||||
|
@mails = Report.all |
||||
|
# @pagy, @record = pagy(Report.all) |
||||
|
end |
||||
|
|
||||
|
end |
||||
@ -0,0 +1,3 @@ |
|||||
|
module ApplicationHelper |
||||
|
include Pagy::Frontend |
||||
|
end |
||||
@ -0,0 +1,2 @@ |
|||||
|
module DeliveriesHelper |
||||
|
end |
||||
@ -0,0 +1,2 @@ |
|||||
|
module MessagesHelper |
||||
|
end |
||||
@ -0,0 +1,2 @@ |
|||||
|
module ReportsHelper |
||||
|
end |
||||
Binary file not shown.
@ -0,0 +1,4 @@ |
|||||
|
// Configure your import map in config/importmap.rb. Read more: https://github.com/rails/importmap-rails
|
||||
|
import "@hotwired/turbo-rails" |
||||
|
import "controllers" |
||||
|
import * as bootstrap from "bootstrap" |
||||
@ -0,0 +1,9 @@ |
|||||
|
import { Application } from "@hotwired/stimulus" |
||||
|
|
||||
|
const application = Application.start() |
||||
|
|
||||
|
// Configure Stimulus development experience
|
||||
|
application.debug = false |
||||
|
window.Stimulus = application |
||||
|
|
||||
|
export { application } |
||||
@ -0,0 +1,7 @@ |
|||||
|
import { Controller } from "@hotwired/stimulus" |
||||
|
|
||||
|
export default class extends Controller { |
||||
|
connect() { |
||||
|
this.element.textContent = "Hello World!" |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,11 @@ |
|||||
|
// Import and register all your controllers from the importmap under controllers/*
|
||||
|
|
||||
|
import { application } from "controllers/application" |
||||
|
|
||||
|
// Eager load all controllers defined in the import map under controllers/**/*_controller
|
||||
|
import { eagerLoadControllersFrom } from "@hotwired/stimulus-loading" |
||||
|
eagerLoadControllersFrom("controllers", application) |
||||
|
|
||||
|
// Lazy load controllers as they appear in the DOM (remember not to preload controllers in import map!)
|
||||
|
// import { lazyLoadControllersFrom } from "@hotwired/stimulus-loading"
|
||||
|
// lazyLoadControllersFrom("controllers", application)
|
||||
@ -0,0 +1,2 @@ |
|||||
|
|
||||
|
//= require semantic-ui
|
||||
@ -0,0 +1,7 @@ |
|||||
|
class ApplicationJob < ActiveJob::Base |
||||
|
# Automatically retry jobs that encountered a deadlock |
||||
|
# retry_on ActiveRecord::Deadlocked |
||||
|
|
||||
|
# Most jobs are safe to ignore if the underlying records are no longer available |
||||
|
# discard_on ActiveJob::DeserializationError |
||||
|
end |
||||
@ -0,0 +1,4 @@ |
|||||
|
class ApplicationMailer < ActionMailer::Base |
||||
|
default from: "from@example.com" |
||||
|
layout "mailer" |
||||
|
end |
||||
Binary file not shown.
Binary file not shown.
@ -0,0 +1,3 @@ |
|||||
|
class ApplicationRecord < ActiveRecord::Base |
||||
|
primary_abstract_class |
||||
|
end |
||||
@ -0,0 +1,4 @@ |
|||||
|
class Delivery < ApplicationRecord |
||||
|
belongs_to :message |
||||
|
belongs_to :log |
||||
|
end |
||||
@ -0,0 +1,10 @@ |
|||||
|
class Message < ApplicationRecord |
||||
|
belongs_to :message |
||||
|
belongs_to :route |
||||
|
belongs_to :domain |
||||
|
belongs_to :credential |
||||
|
belongs_to :raw_body |
||||
|
belongs_to :raw_headers |
||||
|
belongs_to :bounce_for |
||||
|
belongs_to :endpoint |
||||
|
end |
||||
@ -0,0 +1,23 @@ |
|||||
|
require 'mysql2' |
||||
|
|
||||
|
class Report < ActiveRecord::Base |
||||
|
|
||||
|
@conn = Mysql2::Client.new( :host => POSTAL_CONFIG['host'], :port => POSTAL_CONFIG['port'], :username => POSTAL_CONFIG['username'], :password => POSTAL_CONFIG['password'], :database => POSTAL_CONFIG['database']) |
||||
|
#@search_query = "SELECT id,mail_from,rcpt_to,subject,timestamp,last_delivery_attempt,status FROM messages" |
||||
|
@search_query = "SELECT DISTINCT messages.id,messages.message_id,messages.token,messages.mail_from,messages.rcpt_to,messages.subject,messages.timestamp,messages.last_delivery_attempt,messages.size,messages.status,deliveries.details FROM messages INNER JOIN deliveries ON messages.id=deliveries.message_id" |
||||
|
|
||||
|
def self.find(search_term) |
||||
|
p @search_query |
||||
|
if search_term.empty? |
||||
|
reports = @conn.query(@search_query) |
||||
|
else |
||||
|
reports = @conn.query("#{@search_query} WHERE #{search_term} ORDER BY messages.id DESC") |
||||
|
end |
||||
|
return reports |
||||
|
end |
||||
|
|
||||
|
def self.all() |
||||
|
reports = @conn.query("#{@search_query}") |
||||
|
return reports |
||||
|
end |
||||
|
end |
||||
@ -0,0 +1,47 @@ |
|||||
|
<div id="<%= dom_id delivery %>"> |
||||
|
<p> |
||||
|
<strong>Message:</strong> |
||||
|
<%= delivery.message_id %> |
||||
|
</p> |
||||
|
|
||||
|
<p> |
||||
|
<strong>Status:</strong> |
||||
|
<%= delivery.status %> |
||||
|
</p> |
||||
|
|
||||
|
<p> |
||||
|
<strong>Code:</strong> |
||||
|
<%= delivery.code %> |
||||
|
</p> |
||||
|
|
||||
|
<p> |
||||
|
<strong>Output:</strong> |
||||
|
<%= delivery.output %> |
||||
|
</p> |
||||
|
|
||||
|
<p> |
||||
|
<strong>Details:</strong> |
||||
|
<%= delivery.details %> |
||||
|
</p> |
||||
|
|
||||
|
<p> |
||||
|
<strong>Sent with ssl:</strong> |
||||
|
<%= delivery.sent_with_ssl %> |
||||
|
</p> |
||||
|
|
||||
|
<p> |
||||
|
<strong>Log:</strong> |
||||
|
<%= delivery.log_id %> |
||||
|
</p> |
||||
|
|
||||
|
<p> |
||||
|
<strong>Timestamp:</strong> |
||||
|
<%= delivery.timestamp %> |
||||
|
</p> |
||||
|
|
||||
|
<p> |
||||
|
<strong>Time:</strong> |
||||
|
<%= delivery.time %> |
||||
|
</p> |
||||
|
|
||||
|
</div> |
||||
@ -0,0 +1,2 @@ |
|||||
|
json.extract! delivery, :id, :message_id, :status, :code, :output, :details, :sent_with_ssl, :log_id, :timestamp, :time, :created_at, :updated_at |
||||
|
json.url delivery_url(delivery, format: :json) |
||||
@ -0,0 +1,62 @@ |
|||||
|
<%= form_with(model: delivery) do |form| %> |
||||
|
<% if delivery.errors.any? %> |
||||
|
<div style="color: red"> |
||||
|
<h2><%= pluralize(delivery.errors.count, "error") %> prohibited this delivery from being saved:</h2> |
||||
|
|
||||
|
<ul> |
||||
|
<% delivery.errors.each do |error| %> |
||||
|
<li><%= error.full_message %></li> |
||||
|
<% end %> |
||||
|
</ul> |
||||
|
</div> |
||||
|
<% end %> |
||||
|
|
||||
|
<div> |
||||
|
<%= form.label :message_id, style: "display: block" %> |
||||
|
<%= form.text_field :message_id %> |
||||
|
</div> |
||||
|
|
||||
|
<div> |
||||
|
<%= form.label :status, style: "display: block" %> |
||||
|
<%= form.text_field :status %> |
||||
|
</div> |
||||
|
|
||||
|
<div> |
||||
|
<%= form.label :code, style: "display: block" %> |
||||
|
<%= form.number_field :code %> |
||||
|
</div> |
||||
|
|
||||
|
<div> |
||||
|
<%= form.label :output, style: "display: block" %> |
||||
|
<%= form.text_field :output %> |
||||
|
</div> |
||||
|
|
||||
|
<div> |
||||
|
<%= form.label :details, style: "display: block" %> |
||||
|
<%= form.text_field :details %> |
||||
|
</div> |
||||
|
|
||||
|
<div> |
||||
|
<%= form.label :sent_with_ssl, style: "display: block" %> |
||||
|
<%= form.check_box :sent_with_ssl %> |
||||
|
</div> |
||||
|
|
||||
|
<div> |
||||
|
<%= form.label :log_id, style: "display: block" %> |
||||
|
<%= form.text_field :log_id %> |
||||
|
</div> |
||||
|
|
||||
|
<div> |
||||
|
<%= form.label :timestamp, style: "display: block" %> |
||||
|
<%= form.text_field :timestamp %> |
||||
|
</div> |
||||
|
|
||||
|
<div> |
||||
|
<%= form.label :time, style: "display: block" %> |
||||
|
<%= form.text_field :time %> |
||||
|
</div> |
||||
|
|
||||
|
<div> |
||||
|
<%= form.submit %> |
||||
|
</div> |
||||
|
<% end %> |
||||
@ -0,0 +1,10 @@ |
|||||
|
<h1>Editing delivery</h1> |
||||
|
|
||||
|
<%= render "form", delivery: @delivery %> |
||||
|
|
||||
|
<br> |
||||
|
|
||||
|
<div> |
||||
|
<%= link_to "Show this delivery", @delivery %> | |
||||
|
<%= link_to "Back to deliveries", deliveries_path %> |
||||
|
</div> |
||||
@ -0,0 +1,14 @@ |
|||||
|
<p style="color: green"><%= notice %></p> |
||||
|
|
||||
|
<h1>Deliveries</h1> |
||||
|
|
||||
|
<div id="deliveries"> |
||||
|
<% @deliveries.each do |delivery| %> |
||||
|
<%= render delivery %> |
||||
|
<p> |
||||
|
<%= link_to "Show this delivery", delivery %> |
||||
|
</p> |
||||
|
<% end %> |
||||
|
</div> |
||||
|
|
||||
|
<%= link_to "New delivery", new_delivery_path %> |
||||
@ -0,0 +1 @@ |
|||||
|
json.array! @deliveries, partial: "deliveries/delivery", as: :delivery |
||||
@ -0,0 +1,9 @@ |
|||||
|
<h1>New delivery</h1> |
||||
|
|
||||
|
<%= render "form", delivery: @delivery %> |
||||
|
|
||||
|
<br> |
||||
|
|
||||
|
<div> |
||||
|
<%= link_to "Back to deliveries", deliveries_path %> |
||||
|
</div> |
||||
@ -0,0 +1,10 @@ |
|||||
|
<p style="color: green"><%= notice %></p> |
||||
|
|
||||
|
<%= render @delivery %> |
||||
|
|
||||
|
<div> |
||||
|
<%= link_to "Edit this delivery", edit_delivery_path(@delivery) %> | |
||||
|
<%= link_to "Back to deliveries", deliveries_path %> |
||||
|
|
||||
|
<%= button_to "Destroy this delivery", @delivery, method: :delete %> |
||||
|
</div> |
||||
@ -0,0 +1 @@ |
|||||
|
json.partial! "deliveries/delivery", delivery: @delivery |
||||
@ -0,0 +1,44 @@ |
|||||
|
<!DOCTYPE html> |
||||
|
<html> |
||||
|
<head> |
||||
|
<title>Postal Mail Reports</title> |
||||
|
<meta name="viewport" content="width=device-width,initial-scale=1"> |
||||
|
<%= csrf_meta_tags %> |
||||
|
<%= csp_meta_tag %> |
||||
|
|
||||
|
<%= stylesheet_link_tag "application" %> |
||||
|
<%= javascript_importmap_tags %> |
||||
|
</head> |
||||
|
|
||||
|
<body> |
||||
|
<nav class="navbar easypush-nav justify-content-between p-2"> |
||||
|
<a class="navbar-brand" href="/messages"> <%= image_tag "mail-report.svg", size: "38" %>Delivery Reports</a> |
||||
|
<div class="container"> |
||||
|
<%= form_with url: "/messages", class: "form-inline" , method: :get do |form| %> |
||||
|
<div class="row"> |
||||
|
<div class="input-group "> |
||||
|
<div class="input-group-prepend"> |
||||
|
<span class="input-group-text">From Date</span> |
||||
|
</div> |
||||
|
<%= form.date_field :date_from , class: "form-control me-1" %> |
||||
|
<div class="input-group-prepend"> |
||||
|
<span class="input-group-text">To Date</span> |
||||
|
</div> |
||||
|
<%= form.date_field :date_to , class: "form-control me-1 " %> |
||||
|
<%= form.email_field :mail_from, placeholder: "From Address", class: "form-control me-1 " %> |
||||
|
<%= form.email_field :rcpt_to , placeholder: "To Address", class: "form-control me-1 " %> |
||||
|
<div class="input-group-prepend"> |
||||
|
<span class="input-group-text">Status</span> |
||||
|
</div> |
||||
|
<%= form.select :status , ['All', 'Sent','SoftFail', 'HardFail','Held'], class: " form-control custom-select dropdown-menu me-1" %> |
||||
|
<%= form.submit "Search" , class: "btn btn-primary ms-1"%> |
||||
|
</div> |
||||
|
</div> |
||||
|
<% end %> |
||||
|
<%= link_to '<button type="button" class="btn btn-primary">Download Report</button>'.html_safe , :action => :export %> |
||||
|
</div> |
||||
|
</nav> |
||||
|
|
||||
|
<%= yield %> |
||||
|
</body> |
||||
|
</html> |
||||
Binary file not shown.
@ -0,0 +1,187 @@ |
|||||
|
<%= form_with(model: message) do |form| %> |
||||
|
<% if message.errors.any? %> |
||||
|
<div style="color: red"> |
||||
|
<h2><%= pluralize(message.errors.count, "error") %> prohibited this message from being saved:</h2> |
||||
|
|
||||
|
<ul> |
||||
|
<% message.errors.each do |error| %> |
||||
|
<li><%= error.full_message %></li> |
||||
|
<% end %> |
||||
|
</ul> |
||||
|
</div> |
||||
|
<% end %> |
||||
|
|
||||
|
<div> |
||||
|
<%= form.label :token, style: "display: block" %> |
||||
|
<%= form.text_field :token %> |
||||
|
</div> |
||||
|
|
||||
|
<div> |
||||
|
<%= form.label :scope, style: "display: block" %> |
||||
|
<%= form.text_field :scope %> |
||||
|
</div> |
||||
|
|
||||
|
<div> |
||||
|
<%= form.label :rcpt_to, style: "display: block" %> |
||||
|
<%= form.text_field :rcpt_to %> |
||||
|
</div> |
||||
|
|
||||
|
<div> |
||||
|
<%= form.label :mail_from, style: "display: block" %> |
||||
|
<%= form.text_field :mail_from %> |
||||
|
</div> |
||||
|
|
||||
|
<div> |
||||
|
<%= form.label :subject, style: "display: block" %> |
||||
|
<%= form.text_field :subject %> |
||||
|
</div> |
||||
|
|
||||
|
<div> |
||||
|
<%= form.label :message_id, style: "display: block" %> |
||||
|
<%= form.text_field :message_id %> |
||||
|
</div> |
||||
|
|
||||
|
<div> |
||||
|
<%= form.label :timestamp, style: "display: block" %> |
||||
|
<%= form.text_field :timestamp %> |
||||
|
</div> |
||||
|
|
||||
|
<div> |
||||
|
<%= form.label :route_id, style: "display: block" %> |
||||
|
<%= form.text_field :route_id %> |
||||
|
</div> |
||||
|
|
||||
|
<div> |
||||
|
<%= form.label :domain_id, style: "display: block" %> |
||||
|
<%= form.text_field :domain_id %> |
||||
|
</div> |
||||
|
|
||||
|
<div> |
||||
|
<%= form.label :credential_id, style: "display: block" %> |
||||
|
<%= form.text_field :credential_id %> |
||||
|
</div> |
||||
|
|
||||
|
<div> |
||||
|
<%= form.label :status, style: "display: block" %> |
||||
|
<%= form.text_field :status %> |
||||
|
</div> |
||||
|
|
||||
|
<div> |
||||
|
<%= form.label :held, style: "display: block" %> |
||||
|
<%= form.check_box :held %> |
||||
|
</div> |
||||
|
|
||||
|
<div> |
||||
|
<%= form.label :size, style: "display: block" %> |
||||
|
<%= form.text_field :size %> |
||||
|
</div> |
||||
|
|
||||
|
<div> |
||||
|
<%= form.label :last_delivery_attempt, style: "display: block" %> |
||||
|
<%= form.text_field :last_delivery_attempt %> |
||||
|
</div> |
||||
|
|
||||
|
<div> |
||||
|
<%= form.label :raw_table, style: "display: block" %> |
||||
|
<%= form.text_field :raw_table %> |
||||
|
</div> |
||||
|
|
||||
|
<div> |
||||
|
<%= form.label :raw_body_id, style: "display: block" %> |
||||
|
<%= form.text_field :raw_body_id %> |
||||
|
</div> |
||||
|
|
||||
|
<div> |
||||
|
<%= form.label :raw_headers_id, style: "display: block" %> |
||||
|
<%= form.text_field :raw_headers_id %> |
||||
|
</div> |
||||
|
|
||||
|
<div> |
||||
|
<%= form.label :inspected, style: "display: block" %> |
||||
|
<%= form.check_box :inspected %> |
||||
|
</div> |
||||
|
|
||||
|
<div> |
||||
|
<%= form.label :spam, style: "display: block" %> |
||||
|
<%= form.check_box :spam %> |
||||
|
</div> |
||||
|
|
||||
|
<div> |
||||
|
<%= form.label :spam_score, style: "display: block" %> |
||||
|
<%= form.text_field :spam_score %> |
||||
|
</div> |
||||
|
|
||||
|
<div> |
||||
|
<%= form.label :threat, style: "display: block" %> |
||||
|
<%= form.check_box :threat %> |
||||
|
</div> |
||||
|
|
||||
|
<div> |
||||
|
<%= form.label :threat_details, style: "display: block" %> |
||||
|
<%= form.text_field :threat_details %> |
||||
|
</div> |
||||
|
|
||||
|
<div> |
||||
|
<%= form.label :bounce, style: "display: block" %> |
||||
|
<%= form.check_box :bounce %> |
||||
|
</div> |
||||
|
|
||||
|
<div> |
||||
|
<%= form.label :bounce_for_id, style: "display: block" %> |
||||
|
<%= form.text_field :bounce_for_id %> |
||||
|
</div> |
||||
|
|
||||
|
<div> |
||||
|
<%= form.label :tag, style: "display: block" %> |
||||
|
<%= form.text_field :tag %> |
||||
|
</div> |
||||
|
|
||||
|
<div> |
||||
|
<%= form.label :loaded, style: "display: block" %> |
||||
|
<%= form.text_field :loaded %> |
||||
|
</div> |
||||
|
|
||||
|
<div> |
||||
|
<%= form.label :clicked, style: "display: block" %> |
||||
|
<%= form.text_field :clicked %> |
||||
|
</div> |
||||
|
|
||||
|
<div> |
||||
|
<%= form.label :received_with_ssl, style: "display: block" %> |
||||
|
<%= form.check_box :received_with_ssl %> |
||||
|
</div> |
||||
|
|
||||
|
<div> |
||||
|
<%= form.label :hold_expiry, style: "display: block" %> |
||||
|
<%= form.text_field :hold_expiry %> |
||||
|
</div> |
||||
|
|
||||
|
<div> |
||||
|
<%= form.label :tracked_links, style: "display: block" %> |
||||
|
<%= form.number_field :tracked_links %> |
||||
|
</div> |
||||
|
|
||||
|
<div> |
||||
|
<%= form.label :tracked_images, style: "display: block" %> |
||||
|
<%= form.number_field :tracked_images %> |
||||
|
</div> |
||||
|
|
||||
|
<div> |
||||
|
<%= form.label :parsed, style: "display: block" %> |
||||
|
<%= form.number_field :parsed %> |
||||
|
</div> |
||||
|
|
||||
|
<div> |
||||
|
<%= form.label :endpoint_id, style: "display: block" %> |
||||
|
<%= form.text_field :endpoint_id %> |
||||
|
</div> |
||||
|
|
||||
|
<div> |
||||
|
<%= form.label :endpoint_type, style: "display: block" %> |
||||
|
<%= form.text_field :endpoint_type %> |
||||
|
</div> |
||||
|
|
||||
|
<div> |
||||
|
<%= form.submit %> |
||||
|
</div> |
||||
|
<% end %> |
||||
@ -0,0 +1,15 @@ |
|||||
|
<div id="<%= dom_id message %>"> |
||||
|
<div class="row justify-content-center border p-2 border-dark rounded m-2 overflow-auto"> |
||||
|
<tbody> |
||||
|
<tr> |
||||
|
<td style="text-align: center;"><%= message.mail_from %></td> |
||||
|
<td style="text-align: center;"><%= message.rcpt_to %></td> |
||||
|
<td style="text-align: center;"><%= message.subject %></td> |
||||
|
<td style="text-align: center;"><%= Time.at(message.timestamp).strftime('%d-%m-%Y') %></td> |
||||
|
<td style="text-align: center;"><%= Time.at(message.timestamp).strftime('%H:%M:%S') %></td> |
||||
|
<td style="text-align: center;"><%= message.size.to_f >= 1048576 ? "#{(message.size.to_d/1048576).round(2)} MB" : "#{(message.size.to_d/1024).round(2)} KB"%></td> |
||||
|
<td style="text-align: center;"><%= message.status == "Sent"? "Delivered": message.status %></td> |
||||
|
</tr> |
||||
|
</tbody> |
||||
|
</div> |
||||
|
</div> |
||||
@ -0,0 +1,2 @@ |
|||||
|
json.extract! message, :id, :token, :scope, :rcpt_to, :mail_from, :subject, :message_id, :timestamp, :route_id, :domain_id, :credential_id, :status, :held, :size, :last_delivery_attempt, :raw_table, :raw_body_id, :raw_headers_id, :inspected, :spam, :spam_score, :threat, :threat_details, :bounce, :bounce_for_id, :tag, :loaded, :clicked, :received_with_ssl, :hold_expiry, :tracked_links, :tracked_images, :parsed, :endpoint_id, :endpoint_type, :created_at, :updated_at |
||||
|
json.url message_url(message, format: :json) |
||||
@ -0,0 +1,10 @@ |
|||||
|
<h1>Editing message</h1> |
||||
|
|
||||
|
<%= render "form", message: @message %> |
||||
|
|
||||
|
<br> |
||||
|
|
||||
|
<div> |
||||
|
<%= link_to "Show this message", @message %> | |
||||
|
<%= link_to "Back to messages", messages_path %> |
||||
|
</div> |
||||
@ -0,0 +1,35 @@ |
|||||
|
<p style="color: green"><%= notice %></p> |
||||
|
|
||||
|
<div id="messages" class="container-fluid"> |
||||
|
<div class="row justify-content-center rounded m-2 overflow-auto"> |
||||
|
<table class="table table-color"> |
||||
|
<thead class="thead-dark"> |
||||
|
<tr> |
||||
|
<th scope="col" style="text-align: center;">Sender</th> |
||||
|
<th scope="col" style="text-align: center;">Recipient</th> |
||||
|
<th scope="col" style="text-align: center;">Subject</th> |
||||
|
<th scope="col" style="text-align: center;">Date</th> |
||||
|
<th scope="col" style="text-align: center;">Time</th> |
||||
|
<th scope="col" style="text-align: center;">Size</th> |
||||
|
<th scope="col" style="text-align: center;">Status</th> |
||||
|
</tr> |
||||
|
</thead> |
||||
|
<tbody> |
||||
|
<% @messages.each do |message| %> |
||||
|
<tr> |
||||
|
<td style="text-align: center;"><%= message.mail_from %></td> |
||||
|
<td style="text-align: center;"><%= message.rcpt_to %></td> |
||||
|
<td style="text-align: center;"><%= message.subject %></td> |
||||
|
<td style="text-align: center;"><%= Time.at(message.timestamp).strftime('%d-%m-%Y') %></td> |
||||
|
<td style="text-align: center;"><%= Time.at(message.timestamp).strftime('%H:%M:%S') %></td> |
||||
|
<td style="text-align: center;"><%= message.size.to_f >= 1048576 ? "#{(message.size.to_d/1048576).round(2)} MB" : "#{(message.size.to_d/1024).round(2)} KB"%></td> |
||||
|
<td style="text-align: center;"><%= message.status == "Sent"? "Delivered": message.status %></td> |
||||
|
</tr> |
||||
|
<% end %> |
||||
|
</tbody> |
||||
|
</table> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="container d-flex justify-content-center"> |
||||
|
<%== pagy_bootstrap_nav(@pagy) if @pagy.pages > 1 %> |
||||
|
</div> |
||||
@ -0,0 +1 @@ |
|||||
|
json.array! @messages, partial: "messages/message", as: :message |
||||
@ -0,0 +1,9 @@ |
|||||
|
<h1>New message</h1> |
||||
|
|
||||
|
<%= render "form", message: @message %> |
||||
|
|
||||
|
<br> |
||||
|
|
||||
|
<div> |
||||
|
<%= link_to "Back to messages", messages_path %> |
||||
|
</div> |
||||
@ -0,0 +1,10 @@ |
|||||
|
<p style="color: green"><%= notice %></p> |
||||
|
|
||||
|
<%= render @message %> |
||||
|
|
||||
|
<div> |
||||
|
<%= link_to "Edit this message", edit_message_path(@message) %> | |
||||
|
<%= link_to "Back to messages", messages_path %> |
||||
|
|
||||
|
<%= button_to "Destroy this message", @message, method: :delete %> |
||||
|
</div> |
||||
@ -0,0 +1 @@ |
|||||
|
json.partial! "messages/message", message: @message |
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,58 @@ |
|||||
|
<style> |
||||
|
table, th, td { |
||||
|
border: 1px solid black; |
||||
|
border-collapse: collapse; |
||||
|
border-color: #96D4D4; |
||||
|
} |
||||
|
</style> |
||||
|
<div class="row justify-content-center"> |
||||
|
<h4 class="mt-4 display-4">Mail Delivery Report</h4> |
||||
|
</div> |
||||
|
<%= form_with url: "/search", method: :get do |form| %> |
||||
|
<%= form.label :date_from, "From" %> |
||||
|
<%= form.date_field :date_from %> |
||||
|
<%= form.label :date_to, "To" %> |
||||
|
<%= form.date_field :date_to %> |
||||
|
<%= form.label :rcpt_to, "To" %> |
||||
|
<%= form.email_field :rcpt_to %> |
||||
|
<%= form.label :mail_from, "From" %> |
||||
|
<%= form.email_field :mail_from %> |
||||
|
<%= form.label :status, "Status" %> |
||||
|
<%= form.select :status , ['All', 'Sent','SoftFail', 'HardFail','Held'] , selected: "Sent" %> |
||||
|
<%= form.submit "search" %> |
||||
|
<% end %> |
||||
|
<%= link_to '<button type="button">Download Report</button>'.html_safe ,:action => :export %> |
||||
|
<div class="container "> |
||||
|
<% if @mails.present? %> |
||||
|
<div class="row justify-content-center border p-2 border-dark rounded m-2 overflow-auto"> |
||||
|
<table class="table table-bordered"> |
||||
|
<thead> |
||||
|
<tr> |
||||
|
<th scope="col" style="text-align: center;">Sender</th> |
||||
|
<th scope="col" style="text-align: center;">Recipient</th> |
||||
|
<th scope="col" style="text-align: center;">Subject</th> |
||||
|
<th scope="col" style="text-align: center;">Date</th> |
||||
|
<th scope="col" style="text-align: center;">Time</th> |
||||
|
<th scope="col" style="text-align: center;">Size</th> |
||||
|
<th scope="col" style="text-align: center;">Status</th> |
||||
|
<th scope="col" style="text-align: center;">Delivery Details</th> |
||||
|
</tr> |
||||
|
</thead> |
||||
|
<tbody> |
||||
|
<% @mails.each(:as => :hash ) do |mail| %> |
||||
|
<tr> |
||||
|
<td style="text-align: center;"><%= mail['mail_from'] %></td> |
||||
|
<td style="text-align: center;"><%= mail['rcpt_to'] %></td> |
||||
|
<td style="text-align: center;"><%= mail['subject'] %></td> |
||||
|
<td style="text-align: center;"><%= Time.at(mail['timestamp']).strftime('%d-%m-%Y') %></td> |
||||
|
<td style="text-align: center;"><%= Time.at(mail['timestamp']).strftime('%H:%M:%S') %></td> |
||||
|
<td style="text-align: center;"><%= mail['size'].to_f >= 1048576 ? "#{(mail['size'].to_d/1048576).round(2)} MB" : "#{(mail['size'].to_d/1024).round(2)} KB"%></td> |
||||
|
<td style="text-align: center;"><%= mail['status'] == "Sent"? "Delivered": mail['status'] %></td> |
||||
|
<td><%= mail['details'] %></td> |
||||
|
</tr> |
||||
|
<% end %> |
||||
|
</tbody> |
||||
|
</table> |
||||
|
</div> |
||||
|
<% end %> |
||||
|
</div> |
||||
@ -0,0 +1,67 @@ |
|||||
|
<style> |
||||
|
table, th, td { |
||||
|
border: 1px solid black; |
||||
|
border-collapse: collapse; |
||||
|
border-color: #96D4D4; |
||||
|
} |
||||
|
</style> |
||||
|
<div class="row justify-content-center"> |
||||
|
<h4 class="mt-4 display-4">Mail Delivery Report</h4> |
||||
|
</div> |
||||
|
<%= form_with url: "/search", method: :get do |form| %> |
||||
|
<%= form.label :date_from, "From" %> |
||||
|
<%= form.date_field :date_from %> |
||||
|
<%= form.label :date_to, "To" %> |
||||
|
<%= form.date_field :date_to %> |
||||
|
<%= form.label :rcpt_to, "To" %> |
||||
|
<%= form.email_field :rcpt_to %> |
||||
|
<%= form.label :mail_from, "From" %> |
||||
|
<%= form.email_field :mail_from %> |
||||
|
<%= form.label :status, "Status" %> |
||||
|
<%= form.select :status , ['All', 'Sent','SoftFail', 'HardFail','Held'] %> |
||||
|
<%= form.submit "search" %> |
||||
|
<% end %> |
||||
|
<%= link_to "Download Report" ,:action => :export %> <%= "#{@query_report.count} mails" %> |
||||
|
<div class="container"> |
||||
|
<% if @query_report.present? %> |
||||
|
<div class="row justify-content-center border p-2 border-dark rounded m-2 overflow-auto "> |
||||
|
<table class="table table-bordered"> |
||||
|
<thead> |
||||
|
<tr> |
||||
|
<th scope="col" style="text-align: center;">Message ID</th> |
||||
|
<th scope="col" style="text-align: center;">Sender</th> |
||||
|
<th scope="col" style="text-align: center;">Recipient</th> |
||||
|
<th scope="col" style="text-align: center;">Subject</th> |
||||
|
<th scope="col" style="text-align: center;">Date</th> |
||||
|
<th scope="col" style="text-align: center;">Time</th> |
||||
|
<th scope="col" style="text-align: center;">Size</th> |
||||
|
<th scope="col" style="text-align: center;">Status</th> |
||||
|
<th scope="col" style="text-align: center;">Delivery Details</th> |
||||
|
</tr> |
||||
|
</thead> |
||||
|
<tbody> |
||||
|
<% @query_report.each(:as => :hash ) do |mail| %> |
||||
|
<tr> |
||||
|
<td style="text-align: center;"><%= mail['message_id'] %></td> |
||||
|
<td style="text-align: center;"><%= mail['mail_from'] %></td> |
||||
|
<td style="text-align: center;"><%= mail['rcpt_to'] %></td> |
||||
|
<td style="text-align: center;"><%= mail['subject'] %></td> |
||||
|
<td style="text-align: center;"><%= Time.at(mail['timestamp']).strftime('%d-%m-%Y') %></td> |
||||
|
<td style="text-align: center;"><%= Time.at(mail['timestamp']).strftime('%H:%M:%S') %></td> |
||||
|
<td style="text-align: center;"><%= mail['size'].to_f >= 1048576 ? "#{(mail['size'].to_d/1048576).round(2)} MB" : "#{(mail['size'].to_d/1024).round(2)} KB"%></td> |
||||
|
<td style="text-align: center;"><%= mail['status'] == "Sent"? "Delivered": mail['status'] %></td> |
||||
|
<td><%= mail['details'] %></td> |
||||
|
</tr> |
||||
|
<% end %> |
||||
|
</tbody> |
||||
|
</table> |
||||
|
</div> |
||||
|
<% else %> |
||||
|
<div class="p-3 mb-2 bg-light text-dark"> |
||||
|
<span class="text-info font-weight-bold"></span> |
||||
|
Download Report |
||||
|
</div> |
||||
|
<% end %> |
||||
|
</div> |
||||
|
|
||||
|
|
||||
@ -0,0 +1,109 @@ |
|||||
|
#!/usr/bin/env ruby |
||||
|
# frozen_string_literal: true |
||||
|
|
||||
|
# |
||||
|
# This file was generated by Bundler. |
||||
|
# |
||||
|
# The application 'bundle' is installed as part of a gem, and |
||||
|
# this file is here to facilitate running it. |
||||
|
# |
||||
|
|
||||
|
require "rubygems" |
||||
|
|
||||
|
m = Module.new do |
||||
|
module_function |
||||
|
|
||||
|
def invoked_as_script? |
||||
|
File.expand_path($0) == File.expand_path(__FILE__) |
||||
|
end |
||||
|
|
||||
|
def env_var_version |
||||
|
ENV["BUNDLER_VERSION"] |
||||
|
end |
||||
|
|
||||
|
def cli_arg_version |
||||
|
return unless invoked_as_script? # don't want to hijack other binstubs |
||||
|
return unless "update".start_with?(ARGV.first || " ") # must be running `bundle update` |
||||
|
bundler_version = nil |
||||
|
update_index = nil |
||||
|
ARGV.each_with_index do |a, i| |
||||
|
if update_index && update_index.succ == i && a.match?(Gem::Version::ANCHORED_VERSION_PATTERN) |
||||
|
bundler_version = a |
||||
|
end |
||||
|
next unless a =~ /\A--bundler(?:[= ](#{Gem::Version::VERSION_PATTERN}))?\z/ |
||||
|
bundler_version = $1 |
||||
|
update_index = i |
||||
|
end |
||||
|
bundler_version |
||||
|
end |
||||
|
|
||||
|
def gemfile |
||||
|
gemfile = ENV["BUNDLE_GEMFILE"] |
||||
|
return gemfile if gemfile && !gemfile.empty? |
||||
|
|
||||
|
File.expand_path("../Gemfile", __dir__) |
||||
|
end |
||||
|
|
||||
|
def lockfile |
||||
|
lockfile = |
||||
|
case File.basename(gemfile) |
||||
|
when "gems.rb" then gemfile.sub(/\.rb$/, ".locked") |
||||
|
else "#{gemfile}.lock" |
||||
|
end |
||||
|
File.expand_path(lockfile) |
||||
|
end |
||||
|
|
||||
|
def lockfile_version |
||||
|
return unless File.file?(lockfile) |
||||
|
lockfile_contents = File.read(lockfile) |
||||
|
return unless lockfile_contents =~ /\n\nBUNDLED WITH\n\s{2,}(#{Gem::Version::VERSION_PATTERN})\n/ |
||||
|
Regexp.last_match(1) |
||||
|
end |
||||
|
|
||||
|
def bundler_requirement |
||||
|
@bundler_requirement ||= |
||||
|
env_var_version || |
||||
|
cli_arg_version || |
||||
|
bundler_requirement_for(lockfile_version) |
||||
|
end |
||||
|
|
||||
|
def bundler_requirement_for(version) |
||||
|
return "#{Gem::Requirement.default}.a" unless version |
||||
|
|
||||
|
bundler_gem_version = Gem::Version.new(version) |
||||
|
|
||||
|
bundler_gem_version.approximate_recommendation |
||||
|
end |
||||
|
|
||||
|
def load_bundler! |
||||
|
ENV["BUNDLE_GEMFILE"] ||= gemfile |
||||
|
|
||||
|
activate_bundler |
||||
|
end |
||||
|
|
||||
|
def activate_bundler |
||||
|
gem_error = activation_error_handling do |
||||
|
gem "bundler", bundler_requirement |
||||
|
end |
||||
|
return if gem_error.nil? |
||||
|
require_error = activation_error_handling do |
||||
|
require "bundler/version" |
||||
|
end |
||||
|
return if require_error.nil? && Gem::Requirement.new(bundler_requirement).satisfied_by?(Gem::Version.new(Bundler::VERSION)) |
||||
|
warn "Activating bundler (#{bundler_requirement}) failed:\n#{gem_error.message}\n\nTo install the version of bundler this project requires, run `gem install bundler -v '#{bundler_requirement}'`" |
||||
|
exit 42 |
||||
|
end |
||||
|
|
||||
|
def activation_error_handling |
||||
|
yield |
||||
|
nil |
||||
|
rescue StandardError, LoadError => e |
||||
|
e |
||||
|
end |
||||
|
end |
||||
|
|
||||
|
m.load_bundler! |
||||
|
|
||||
|
if m.invoked_as_script? |
||||
|
load Gem.bin_path("bundler", "bundle") |
||||
|
end |
||||
@ -0,0 +1,4 @@ |
|||||
|
#!/usr/bin/env ruby |
||||
|
|
||||
|
require_relative "../config/application" |
||||
|
require "importmap/commands" |
||||
@ -0,0 +1,4 @@ |
|||||
|
#!/usr/bin/env ruby |
||||
|
APP_PATH = File.expand_path("../config/application", __dir__) |
||||
|
require_relative "../config/boot" |
||||
|
require "rails/commands" |
||||
@ -0,0 +1,4 @@ |
|||||
|
#!/usr/bin/env ruby |
||||
|
require_relative "../config/boot" |
||||
|
require "rake" |
||||
|
Rake.application.run |
||||
@ -0,0 +1,33 @@ |
|||||
|
#!/usr/bin/env ruby |
||||
|
require "fileutils" |
||||
|
|
||||
|
# path to your application root. |
||||
|
APP_ROOT = File.expand_path("..", __dir__) |
||||
|
|
||||
|
def system!(*args) |
||||
|
system(*args) || abort("\n== Command #{args} failed ==") |
||||
|
end |
||||
|
|
||||
|
FileUtils.chdir APP_ROOT do |
||||
|
# This script is a way to set up or update your development environment automatically. |
||||
|
# This script is idempotent, so that you can run it at any time and get an expectable outcome. |
||||
|
# Add necessary setup steps to this file. |
||||
|
|
||||
|
puts "== Installing dependencies ==" |
||||
|
system! "gem install bundler --conservative" |
||||
|
system("bundle check") || system!("bundle install") |
||||
|
|
||||
|
# puts "\n== Copying sample files ==" |
||||
|
# unless File.exist?("config/database.yml") |
||||
|
# FileUtils.cp "config/database.yml.sample", "config/database.yml" |
||||
|
# end |
||||
|
|
||||
|
puts "\n== Preparing database ==" |
||||
|
system! "bin/rails db:prepare" |
||||
|
|
||||
|
puts "\n== Removing old logs and tempfiles ==" |
||||
|
system! "bin/rails log:clear tmp:clear" |
||||
|
|
||||
|
puts "\n== Restarting application server ==" |
||||
|
system! "bin/rails restart" |
||||
|
end |
||||
@ -0,0 +1,6 @@ |
|||||
|
# This file is used by Rack-based servers to start the application. |
||||
|
|
||||
|
require_relative "config/environment" |
||||
|
|
||||
|
run Rails.application |
||||
|
Rails.application.load_server |
||||
@ -0,0 +1,22 @@ |
|||||
|
require_relative "boot" |
||||
|
|
||||
|
require "rails/all" |
||||
|
|
||||
|
# Require the gems listed in Gemfile, including any gems |
||||
|
# you've limited to :test, :development, or :production. |
||||
|
Bundler.require(*Rails.groups) |
||||
|
|
||||
|
module PostalReports |
||||
|
class Application < Rails::Application |
||||
|
# Initialize configuration defaults for originally generated Rails version. |
||||
|
config.load_defaults 7.0 |
||||
|
|
||||
|
# Configuration for the application, engines, and railties goes here. |
||||
|
# |
||||
|
# These settings can be overridden in specific environments using the files |
||||
|
# in config/environments, which are processed later. |
||||
|
# |
||||
|
# config.time_zone = "Central Time (US & Canada)" |
||||
|
# config.eager_load_paths << Rails.root.join("extras") |
||||
|
end |
||||
|
end |
||||
@ -0,0 +1,4 @@ |
|||||
|
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) |
||||
|
|
||||
|
require "bundler/setup" # Set up gems listed in the Gemfile. |
||||
|
require "bootsnap/setup" # Speed up boot time by caching expensive operations. |
||||
@ -0,0 +1,11 @@ |
|||||
|
development: |
||||
|
adapter: redis |
||||
|
url: redis://localhost:6379/1 |
||||
|
|
||||
|
test: |
||||
|
adapter: test |
||||
|
|
||||
|
production: |
||||
|
adapter: redis |
||||
|
url: <%= ENV.fetch("REDIS_URL") { "redis://localhost:6379/1" } %> |
||||
|
channel_prefix: postal_reports_production |
||||
@ -0,0 +1 @@ |
|||||
|
c2btjUYWsrKiX4Wk+a83yWODEus/0ejcgQEsHDNwpmaxv54yu+Nlx7IcF0Fk1ot11xKrX4TBEHj+y73IJuWqo12OFt0qAPmIv8Wssv8J/W67Ft2i12T+5unYei6Zy73t1z3QMrZI9kUNhtDovCqwN05pClYmY/YcegJreSjJXDzOHj8Zpytv61R1QWHFWcBuXaU75oXyh1Wz3nYYo3ZrT5zh4pYu54W3DIC8CbEtpzMbXQj1xWG+zjlt2muXLs45epvrxu9Z5KUasIhKQWo7RAqiA6K3kbG3+IHCJG8eKUO4KtrR8ufNdbDlwGMAfVU0iGislWofeKkaDCDHPSA8xn0G3ytgv/X02CwRMOqeXzddJa3ZLZMkDpnAB7kf4yKXLZC9LFFSTcumIPxIM2SQGo24M/b9YBZA+Pln--deArg00D7FC9BK/U--KFc/wy5PIkzMjuTSIzLQdQ== |
||||
@ -0,0 +1,29 @@ |
|||||
|
# SQLite. Versions 3.8.0 and up are supported. |
||||
|
# gem install sqlite3 |
||||
|
# |
||||
|
# Ensure the SQLite 3 gem is defined in your Gemfile |
||||
|
# gem "sqlite3" |
||||
|
# |
||||
|
default: &default |
||||
|
adapter: mysql2 |
||||
|
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> |
||||
|
timeout: 5000 |
||||
|
host: 127.0.0.1 |
||||
|
username: postal |
||||
|
password: postal |
||||
|
port: 3306 |
||||
|
|
||||
|
development: |
||||
|
<<: *default |
||||
|
database: postal1 |
||||
|
|
||||
|
# Warning: The database defined as "test" will be erased and |
||||
|
# re-generated from your development database when you run "rake". |
||||
|
# Do not set this db to the same as development or production. |
||||
|
test: |
||||
|
<<: *default |
||||
|
database: postal1 |
||||
|
|
||||
|
production: |
||||
|
<<: *default |
||||
|
database: postal1 |
||||
@ -0,0 +1,5 @@ |
|||||
|
# Load the Rails application. |
||||
|
require_relative "application" |
||||
|
|
||||
|
# Initialize the Rails application. |
||||
|
Rails.application.initialize! |
||||
@ -0,0 +1,70 @@ |
|||||
|
require "active_support/core_ext/integer/time" |
||||
|
|
||||
|
Rails.application.configure do |
||||
|
# Settings specified here will take precedence over those in config/application.rb. |
||||
|
|
||||
|
# In the development environment your application's code is reloaded any time |
||||
|
# it changes. This slows down response time but is perfect for development |
||||
|
# since you don't have to restart the web server when you make code changes. |
||||
|
config.cache_classes = false |
||||
|
|
||||
|
# Do not eager load code on boot. |
||||
|
config.eager_load = false |
||||
|
|
||||
|
# Show full error reports. |
||||
|
config.consider_all_requests_local = true |
||||
|
|
||||
|
# Enable server timing |
||||
|
config.server_timing = true |
||||
|
|
||||
|
# Enable/disable caching. By default caching is disabled. |
||||
|
# Run rails dev:cache to toggle caching. |
||||
|
if Rails.root.join("tmp/caching-dev.txt").exist? |
||||
|
config.action_controller.perform_caching = true |
||||
|
config.action_controller.enable_fragment_cache_logging = true |
||||
|
|
||||
|
config.cache_store = :memory_store |
||||
|
config.public_file_server.headers = { |
||||
|
"Cache-Control" => "public, max-age=#{2.days.to_i}" |
||||
|
} |
||||
|
else |
||||
|
config.action_controller.perform_caching = false |
||||
|
|
||||
|
config.cache_store = :null_store |
||||
|
end |
||||
|
|
||||
|
# Store uploaded files on the local file system (see config/storage.yml for options). |
||||
|
config.active_storage.service = :local |
||||
|
|
||||
|
# Don't care if the mailer can't send. |
||||
|
config.action_mailer.raise_delivery_errors = false |
||||
|
|
||||
|
config.action_mailer.perform_caching = false |
||||
|
|
||||
|
# Print deprecation notices to the Rails logger. |
||||
|
config.active_support.deprecation = :log |
||||
|
|
||||
|
# Raise exceptions for disallowed deprecations. |
||||
|
config.active_support.disallowed_deprecation = :raise |
||||
|
|
||||
|
# Tell Active Support which deprecation messages to disallow. |
||||
|
config.active_support.disallowed_deprecation_warnings = [] |
||||
|
|
||||
|
# Raise an error on page load if there are pending migrations. |
||||
|
config.active_record.migration_error = :page_load |
||||
|
|
||||
|
# Highlight code that triggered database queries in logs. |
||||
|
config.active_record.verbose_query_logs = true |
||||
|
|
||||
|
# Suppress logger output for asset requests. |
||||
|
config.assets.quiet = true |
||||
|
|
||||
|
# Raises error for missing translations. |
||||
|
# config.i18n.raise_on_missing_translations = true |
||||
|
|
||||
|
# Annotate rendered view with file names. |
||||
|
# config.action_view.annotate_rendered_view_with_filenames = true |
||||
|
|
||||
|
# Uncomment if you wish to allow Action Cable access from any origin. |
||||
|
# config.action_cable.disable_request_forgery_protection = true |
||||
|
end |
||||
@ -0,0 +1,93 @@ |
|||||
|
require "active_support/core_ext/integer/time" |
||||
|
|
||||
|
Rails.application.configure do |
||||
|
# Settings specified here will take precedence over those in config/application.rb. |
||||
|
|
||||
|
# Code is not reloaded between requests. |
||||
|
config.cache_classes = true |
||||
|
|
||||
|
# Eager load code on boot. This eager loads most of Rails and |
||||
|
# your application in memory, allowing both threaded web servers |
||||
|
# and those relying on copy on write to perform better. |
||||
|
# Rake tasks automatically ignore this option for performance. |
||||
|
config.eager_load = true |
||||
|
|
||||
|
# Full error reports are disabled and caching is turned on. |
||||
|
config.consider_all_requests_local = false |
||||
|
config.action_controller.perform_caching = true |
||||
|
|
||||
|
# Ensures that a master key has been made available in either ENV["RAILS_MASTER_KEY"] |
||||
|
# or in config/master.key. This key is used to decrypt credentials (and other encrypted files). |
||||
|
# config.require_master_key = true |
||||
|
|
||||
|
# Disable serving static files from the `/public` folder by default since |
||||
|
# Apache or NGINX already handles this. |
||||
|
config.public_file_server.enabled = ENV["RAILS_SERVE_STATIC_FILES"].present? |
||||
|
|
||||
|
# Compress CSS using a preprocessor. |
||||
|
# config.assets.css_compressor = :sass |
||||
|
|
||||
|
# Do not fallback to assets pipeline if a precompiled asset is missed. |
||||
|
config.assets.compile = false |
||||
|
|
||||
|
# Enable serving of images, stylesheets, and JavaScripts from an asset server. |
||||
|
# config.asset_host = "http://assets.example.com" |
||||
|
|
||||
|
# Specifies the header that your server uses for sending files. |
||||
|
# config.action_dispatch.x_sendfile_header = "X-Sendfile" # for Apache |
||||
|
# config.action_dispatch.x_sendfile_header = "X-Accel-Redirect" # for NGINX |
||||
|
|
||||
|
# Store uploaded files on the local file system (see config/storage.yml for options). |
||||
|
config.active_storage.service = :local |
||||
|
|
||||
|
# Mount Action Cable outside main process or domain. |
||||
|
# config.action_cable.mount_path = nil |
||||
|
# config.action_cable.url = "wss://example.com/cable" |
||||
|
# config.action_cable.allowed_request_origins = [ "http://example.com", /http:\/\/example.*/ ] |
||||
|
|
||||
|
# Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies. |
||||
|
# config.force_ssl = true |
||||
|
|
||||
|
# Include generic and useful information about system operation, but avoid logging too much |
||||
|
# information to avoid inadvertent exposure of personally identifiable information (PII). |
||||
|
config.log_level = :info |
||||
|
|
||||
|
# Prepend all log lines with the following tags. |
||||
|
config.log_tags = [ :request_id ] |
||||
|
|
||||
|
# Use a different cache store in production. |
||||
|
# config.cache_store = :mem_cache_store |
||||
|
|
||||
|
# Use a real queuing backend for Active Job (and separate queues per environment). |
||||
|
# config.active_job.queue_adapter = :resque |
||||
|
# config.active_job.queue_name_prefix = "postal_reports_production" |
||||
|
|
||||
|
config.action_mailer.perform_caching = false |
||||
|
|
||||
|
# Ignore bad email addresses and do not raise email delivery errors. |
||||
|
# Set this to true and configure the email server for immediate delivery to raise delivery errors. |
||||
|
# config.action_mailer.raise_delivery_errors = false |
||||
|
|
||||
|
# Enable locale fallbacks for I18n (makes lookups for any locale fall back to |
||||
|
# the I18n.default_locale when a translation cannot be found). |
||||
|
config.i18n.fallbacks = true |
||||
|
|
||||
|
# Don't log any deprecations. |
||||
|
config.active_support.report_deprecations = false |
||||
|
|
||||
|
# Use default logging formatter so that PID and timestamp are not suppressed. |
||||
|
config.log_formatter = ::Logger::Formatter.new |
||||
|
|
||||
|
# Use a different logger for distributed setups. |
||||
|
# require "syslog/logger" |
||||
|
# config.logger = ActiveSupport::TaggedLogging.new(Syslog::Logger.new "app-name") |
||||
|
|
||||
|
if ENV["RAILS_LOG_TO_STDOUT"].present? |
||||
|
logger = ActiveSupport::Logger.new(STDOUT) |
||||
|
logger.formatter = config.log_formatter |
||||
|
config.logger = ActiveSupport::TaggedLogging.new(logger) |
||||
|
end |
||||
|
|
||||
|
# Do not dump schema after migrations. |
||||
|
config.active_record.dump_schema_after_migration = false |
||||
|
end |
||||
@ -0,0 +1,60 @@ |
|||||
|
require "active_support/core_ext/integer/time" |
||||
|
|
||||
|
# The test environment is used exclusively to run your application's |
||||
|
# test suite. You never need to work with it otherwise. Remember that |
||||
|
# your test database is "scratch space" for the test suite and is wiped |
||||
|
# and recreated between test runs. Don't rely on the data there! |
||||
|
|
||||
|
Rails.application.configure do |
||||
|
# Settings specified here will take precedence over those in config/application.rb. |
||||
|
|
||||
|
# Turn false under Spring and add config.action_view.cache_template_loading = true. |
||||
|
config.cache_classes = true |
||||
|
|
||||
|
# Eager loading loads your whole application. When running a single test locally, |
||||
|
# this probably isn't necessary. It's a good idea to do in a continuous integration |
||||
|
# system, or in some way before deploying your code. |
||||
|
config.eager_load = ENV["CI"].present? |
||||
|
|
||||
|
# Configure public file server for tests with Cache-Control for performance. |
||||
|
config.public_file_server.enabled = true |
||||
|
config.public_file_server.headers = { |
||||
|
"Cache-Control" => "public, max-age=#{1.hour.to_i}" |
||||
|
} |
||||
|
|
||||
|
# Show full error reports and disable caching. |
||||
|
config.consider_all_requests_local = true |
||||
|
config.action_controller.perform_caching = false |
||||
|
config.cache_store = :null_store |
||||
|
|
||||
|
# Raise exceptions instead of rendering exception templates. |
||||
|
config.action_dispatch.show_exceptions = false |
||||
|
|
||||
|
# Disable request forgery protection in test environment. |
||||
|
config.action_controller.allow_forgery_protection = false |
||||
|
|
||||
|
# Store uploaded files on the local file system in a temporary directory. |
||||
|
config.active_storage.service = :test |
||||
|
|
||||
|
config.action_mailer.perform_caching = false |
||||
|
|
||||
|
# Tell Action Mailer not to deliver emails to the real world. |
||||
|
# The :test delivery method accumulates sent emails in the |
||||
|
# ActionMailer::Base.deliveries array. |
||||
|
config.action_mailer.delivery_method = :test |
||||
|
|
||||
|
# Print deprecation notices to the stderr. |
||||
|
config.active_support.deprecation = :stderr |
||||
|
|
||||
|
# Raise exceptions for disallowed deprecations. |
||||
|
config.active_support.disallowed_deprecation = :raise |
||||
|
|
||||
|
# Tell Active Support which deprecation messages to disallow. |
||||
|
config.active_support.disallowed_deprecation_warnings = [] |
||||
|
|
||||
|
# Raises error for missing translations. |
||||
|
# config.i18n.raise_on_missing_translations = true |
||||
|
|
||||
|
# Annotate rendered view with file names. |
||||
|
# config.action_view.annotate_rendered_view_with_filenames = true |
||||
|
end |
||||
@ -0,0 +1,12 @@ |
|||||
|
# Pin npm packages by running ./bin/importmap |
||||
|
|
||||
|
pin "application" |
||||
|
# pin "bootstrap", to: "bootstrap.min.js", preload: true |
||||
|
pin "@popperjs/core", to: "popper.js", preload: true |
||||
|
pin "bootstrap", to: "https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js", preload: true |
||||
|
|
||||
|
|
||||
|
pin "@hotwired/turbo-rails", to: "turbo.min.js" |
||||
|
pin "@hotwired/stimulus", to: "stimulus.min.js" |
||||
|
pin "@hotwired/stimulus-loading", to: "stimulus-loading.js" |
||||
|
pin_all_from "app/javascript/controllers", under: "controllers" |
||||
@ -0,0 +1,13 @@ |
|||||
|
# Be sure to restart your server when you modify this file. |
||||
|
|
||||
|
# Version of your assets, change this if you want to expire all your assets. |
||||
|
Rails.application.config.assets.version = "1.0" |
||||
|
|
||||
|
# Add additional assets to the asset load path. |
||||
|
# Rails.application.config.assets.paths << Emoji.images_path |
||||
|
|
||||
|
# Precompile additional assets. |
||||
|
# application.js, application.css, and all non-JS/CSS in the app/assets |
||||
|
# folder are already added. |
||||
|
# Rails.application.config.assets.precompile += %w( admin.js admin.css ) |
||||
|
Rails.application.config.assets.precompile += %w(bootstrap.min.js popper.js) |
||||
@ -0,0 +1,25 @@ |
|||||
|
# Be sure to restart your server when you modify this file. |
||||
|
|
||||
|
# Define an application-wide content security policy. |
||||
|
# See the Securing Rails Applications Guide for more information: |
||||
|
# https://guides.rubyonrails.org/security.html#content-security-policy-header |
||||
|
|
||||
|
# Rails.application.configure do |
||||
|
# config.content_security_policy do |policy| |
||||
|
# policy.default_src :self, :https |
||||
|
# policy.font_src :self, :https, :data |
||||
|
# policy.img_src :self, :https, :data |
||||
|
# policy.object_src :none |
||||
|
# policy.script_src :self, :https |
||||
|
# policy.style_src :self, :https |
||||
|
# # Specify URI for violation reports |
||||
|
# # policy.report_uri "/csp-violation-report-endpoint" |
||||
|
# end |
||||
|
# |
||||
|
# # Generate session nonces for permitted importmap and inline scripts |
||||
|
# config.content_security_policy_nonce_generator = ->(request) { request.session.id.to_s } |
||||
|
# config.content_security_policy_nonce_directives = %w(script-src) |
||||
|
# |
||||
|
# # Report violations without enforcing the policy. |
||||
|
# # config.content_security_policy_report_only = true |
||||
|
# end |
||||
@ -0,0 +1,8 @@ |
|||||
|
# Be sure to restart your server when you modify this file. |
||||
|
|
||||
|
# Configure parameters to be filtered from the log file. Use this to limit dissemination of |
||||
|
# sensitive information. See the ActiveSupport::ParameterFilter documentation for supported |
||||
|
# notations and behaviors. |
||||
|
Rails.application.config.filter_parameters += [ |
||||
|
:passw, :secret, :token, :_key, :crypt, :salt, :certificate, :otp, :ssn |
||||
|
] |
||||
@ -0,0 +1,16 @@ |
|||||
|
# Be sure to restart your server when you modify this file. |
||||
|
|
||||
|
# Add new inflection rules using the following format. Inflections |
||||
|
# are locale specific, and you may define rules for as many different |
||||
|
# locales as you wish. All of these examples are active by default: |
||||
|
# ActiveSupport::Inflector.inflections(:en) do |inflect| |
||||
|
# inflect.plural /^(ox)$/i, "\\1en" |
||||
|
# inflect.singular /^(ox)en/i, "\\1" |
||||
|
# inflect.irregular "person", "people" |
||||
|
# inflect.uncountable %w( fish sheep ) |
||||
|
# end |
||||
|
|
||||
|
# These inflection rules are supported but not enabled by default: |
||||
|
# ActiveSupport::Inflector.inflections(:en) do |inflect| |
||||
|
# inflect.acronym "RESTful" |
||||
|
# end |
||||
@ -0,0 +1,220 @@ |
|||||
|
# frozen_string_literal: true |
||||
|
|
||||
|
# Pagy initializer file (9.2.2) |
||||
|
# Customize only what you really need and notice that the core Pagy works also without any of the following lines. |
||||
|
# Should you just cherry pick part of this file, please maintain the require-order of the extras |
||||
|
|
||||
|
|
||||
|
# Pagy Variables |
||||
|
# See https://ddnexus.github.io/pagy/docs/api/pagy#variables |
||||
|
# You can set any pagy variable as a Pagy::DEFAULT. They can also be overridden per instance by just passing them to |
||||
|
# Pagy.new|Pagy::Countless.new|Pagy::Calendar::*.new or any of the #pagy* controller methods |
||||
|
# Here are the few that make more sense as DEFAULTs: |
||||
|
Pagy::DEFAULT[:limit] = 20 # default |
||||
|
Pagy::DEFAULT[:size] = 7 # default |
||||
|
Pagy::DEFAULT[:ends] = true # default |
||||
|
# Pagy::DEFAULT[:page_param] = :page # default |
||||
|
# Pagy::DEFAULT[:count_args] = [] # example for non AR ORMs |
||||
|
# Pagy::DEFAULT[:max_pages] = 3000 # example |
||||
|
|
||||
|
|
||||
|
# Extras |
||||
|
# See https://ddnexus.github.io/pagy/categories/extra |
||||
|
|
||||
|
|
||||
|
# Legacy Compatibility Extras |
||||
|
|
||||
|
# Size extra: Enable the Array type for the `:size` variable (e.g. `size: [1,4,4,1]`) |
||||
|
# See https://ddnexus.github.io/pagy/docs/extras/size |
||||
|
# require 'pagy/extras/size' # must be required before the other extras |
||||
|
|
||||
|
|
||||
|
# Backend Extras |
||||
|
|
||||
|
# Arel extra: For better performance utilizing grouped ActiveRecord collections: |
||||
|
# See: https://ddnexus.github.io/pagy/docs/extras/arel |
||||
|
# require 'pagy/extras/arel' |
||||
|
|
||||
|
# Array extra: Paginate arrays efficiently, avoiding expensive array-wrapping and without overriding |
||||
|
# See https://ddnexus.github.io/pagy/docs/extras/array |
||||
|
# require 'pagy/extras/array' |
||||
|
|
||||
|
# Calendar extra: Add pagination filtering by calendar time unit (year, quarter, month, week, day) |
||||
|
# See https://ddnexus.github.io/pagy/docs/extras/calendar |
||||
|
# require 'pagy/extras/calendar' |
||||
|
# Default for each calendar unit class in IRB: |
||||
|
# >> Pagy::Calendar::Year::DEFAULT |
||||
|
# >> Pagy::Calendar::Quarter::DEFAULT |
||||
|
# >> Pagy::Calendar::Month::DEFAULT |
||||
|
# >> Pagy::Calendar::Week::DEFAULT |
||||
|
# >> Pagy::Calendar::Day::DEFAULT |
||||
|
# |
||||
|
# Uncomment the following lines, if you need calendar localization without using the I18n extra |
||||
|
# module LocalizePagyCalendar |
||||
|
# def localize(time, opts) |
||||
|
# ::I18n.l(time, **opts) |
||||
|
# end |
||||
|
# end |
||||
|
# Pagy::Calendar.prepend LocalizePagyCalendar |
||||
|
|
||||
|
# Countless extra: Paginate without any count, saving one query per rendering |
||||
|
# See https://ddnexus.github.io/pagy/docs/extras/countless |
||||
|
# require 'pagy/extras/countless' |
||||
|
# Pagy::DEFAULT[:countless_minimal] = false # default (eager loading) |
||||
|
|
||||
|
# Elasticsearch Rails extra: Paginate `ElasticsearchRails::Results` objects |
||||
|
# See https://ddnexus.github.io/pagy/docs/extras/elasticsearch_rails |
||||
|
# Default :pagy_search method: change only if you use also |
||||
|
# the searchkick or meilisearch extra that defines the same |
||||
|
# Pagy::DEFAULT[:elasticsearch_rails_pagy_search] = :pagy_search |
||||
|
# Default original :search method called internally to do the actual search |
||||
|
# Pagy::DEFAULT[:elasticsearch_rails_search] = :search |
||||
|
# require 'pagy/extras/elasticsearch_rails' |
||||
|
|
||||
|
# Headers extra: http response headers (and other helpers) useful for API pagination |
||||
|
# See https://ddnexus.github.io/pagy/docs/extras/headers |
||||
|
# require 'pagy/extras/headers' |
||||
|
# Pagy::DEFAULT[:headers] = { page: 'Current-Page', |
||||
|
# limit: 'Page-Items', |
||||
|
# count: 'Total-Count', |
||||
|
# pages: 'Total-Pages' } # default |
||||
|
|
||||
|
# Keyset extra: Paginate with the Pagy keyset pagination technique |
||||
|
# See https://ddnexus.github.io/pagy/docs/extras/keyset |
||||
|
# require 'pagy/extras/keyset' |
||||
|
|
||||
|
# Meilisearch extra: Paginate `Meilisearch` result objects |
||||
|
# See https://ddnexus.github.io/pagy/docs/extras/meilisearch |
||||
|
# Default :pagy_search method: change only if you use also |
||||
|
# the elasticsearch_rails or searchkick extra that define the same method |
||||
|
# Pagy::DEFAULT[:meilisearch_pagy_search] = :pagy_search |
||||
|
# Default original :search method called internally to do the actual search |
||||
|
# Pagy::DEFAULT[:meilisearch_search] = :ms_search |
||||
|
# require 'pagy/extras/meilisearch' |
||||
|
|
||||
|
# Metadata extra: Provides the pagination metadata to Javascript frameworks like Vue.js, react.js, etc. |
||||
|
# See https://ddnexus.github.io/pagy/docs/extras/metadata |
||||
|
# you must require the JS Tools internal extra (BEFORE the metadata extra) ONLY if you need also the :sequels |
||||
|
# require 'pagy/extras/js_tools' |
||||
|
# require 'pagy/extras/metadata' |
||||
|
# For performance reasons, you should explicitly set ONLY the metadata you use in the frontend |
||||
|
# Pagy::DEFAULT[:metadata] = %i[scaffold_url page prev next last] # example |
||||
|
|
||||
|
# Searchkick extra: Paginate `Searchkick::Results` objects |
||||
|
# See https://ddnexus.github.io/pagy/docs/extras/searchkick |
||||
|
# Default :pagy_search method: change only if you use also |
||||
|
# the elasticsearch_rails or meilisearch extra that defines the same |
||||
|
# Pagy::DEFAULT[:searchkick_pagy_search] = :pagy_search |
||||
|
# Default original :search method called internally to do the actual search |
||||
|
# Pagy::DEFAULT[:searchkick_search] = :search |
||||
|
# require 'pagy/extras/searchkick' |
||||
|
# uncomment if you are going to use Searchkick.pagy_search |
||||
|
# Searchkick.extend Pagy::Searchkick |
||||
|
|
||||
|
|
||||
|
# Frontend Extras |
||||
|
|
||||
|
# Bootstrap extra: Add nav, nav_js and combo_nav_js helpers and templates for Bootstrap pagination |
||||
|
# See https://ddnexus.github.io/pagy/docs/extras/bootstrap |
||||
|
require 'pagy/extras/bootstrap' |
||||
|
|
||||
|
# Bulma extra: Add nav, nav_js and combo_nav_js helpers and templates for Bulma pagination |
||||
|
# See https://ddnexus.github.io/pagy/docs/extras/bulma |
||||
|
# require 'pagy/extras/bulma' |
||||
|
|
||||
|
# Pagy extra: Add the pagy styled versions of the javascript-powered navs |
||||
|
# and a few other components to the Pagy::Frontend module. |
||||
|
# See https://ddnexus.github.io/pagy/docs/extras/pagy |
||||
|
require 'pagy/extras/pagy' |
||||
|
|
||||
|
# Multi size var used by the *_nav_js helpers |
||||
|
# See https://ddnexus.github.io/pagy/docs/extras/pagy#steps |
||||
|
# Pagy::DEFAULT[:steps] = { 0 => 5, 540 => 7, 720 => 9 } # example |
||||
|
|
||||
|
|
||||
|
# Feature Extras |
||||
|
|
||||
|
# Gearbox extra: Automatically change the limit per page depending on the page number |
||||
|
# See https://ddnexus.github.io/pagy/docs/extras/gearbox |
||||
|
# require 'pagy/extras/gearbox' |
||||
|
# set to false only if you want to make :gearbox_extra an opt-in variable |
||||
|
# Pagy::DEFAULT[:gearbox_extra] = false # default true |
||||
|
# Pagy::DEFAULT[:gearbox_limit] = [15, 30, 60, 100] # default |
||||
|
|
||||
|
# Limit extra: Allow the client to request a custom limit per page with an optional selector UI |
||||
|
# See https://ddnexus.github.io/pagy/docs/extras/limit |
||||
|
# require 'pagy/extras/limit' |
||||
|
# set to false only if you want to make :limit_extra an opt-in variable |
||||
|
# Pagy::DEFAULT[:limit_extra] = false # default true |
||||
|
# Pagy::DEFAULT[:limit_param] = :limit # default |
||||
|
# Pagy::DEFAULT[:limit_max] = 100 # default |
||||
|
|
||||
|
# Overflow extra: Allow for easy handling of overflowing pages |
||||
|
# See https://ddnexus.github.io/pagy/docs/extras/overflow |
||||
|
# require 'pagy/extras/overflow' |
||||
|
# Pagy::DEFAULT[:overflow] = :empty_page # default (other options: :last_page and :exception) |
||||
|
|
||||
|
# Trim extra: Remove the page=1 param from links |
||||
|
# See https://ddnexus.github.io/pagy/docs/extras/trim |
||||
|
# require 'pagy/extras/trim' |
||||
|
# set to false only if you want to make :trim_extra an opt-in variable |
||||
|
# Pagy::DEFAULT[:trim_extra] = false # default true |
||||
|
|
||||
|
# Standalone extra: Use pagy in non Rack environment/gem |
||||
|
# See https://ddnexus.github.io/pagy/docs/extras/standalone |
||||
|
# require 'pagy/extras/standalone' |
||||
|
# Pagy::DEFAULT[:url] = 'http://www.example.com/subdir' # optional default |
||||
|
|
||||
|
# Jsonapi extra: Implements JSON:API specifications |
||||
|
# See https://ddnexus.github.io/pagy/docs/extras/jsonapi |
||||
|
# require 'pagy/extras/jsonapi' # must be required after the other extras |
||||
|
# set to false only if you want to make :jsonapi an opt-in variable |
||||
|
# Pagy::DEFAULT[:jsonapi] = false # default true |
||||
|
|
||||
|
# Rails |
||||
|
# Enable the .js file required by the helpers that use javascript |
||||
|
# (pagy*_nav_js, pagy*_combo_nav_js, and pagy_limit_selector_js) |
||||
|
# See https://ddnexus.github.io/pagy/docs/api/javascript |
||||
|
|
||||
|
# With the asset pipeline |
||||
|
# Sprockets need to look into the pagy javascripts dir, so add it to the assets paths |
||||
|
# Rails.application.config.assets.paths << Pagy.root.join('javascripts') |
||||
|
|
||||
|
# I18n |
||||
|
|
||||
|
# Pagy internal I18n: ~18x faster using ~10x less memory than the i18n gem |
||||
|
# See https://ddnexus.github.io/pagy/docs/api/i18n |
||||
|
# Notice: No need to configure anything in this section if your app uses only "en" |
||||
|
# or if you use the i18n extra below |
||||
|
# |
||||
|
# Examples: |
||||
|
# load the "de" built-in locale: |
||||
|
# Pagy::I18n.load(locale: 'de') |
||||
|
# |
||||
|
# load the "de" locale defined in the custom file at :filepath: |
||||
|
# Pagy::I18n.load(locale: 'de', filepath: 'path/to/pagy-de.yml') |
||||
|
# |
||||
|
# load the "de", "en" and "es" built-in locales: |
||||
|
# (the first passed :locale will be used also as the default_locale) |
||||
|
# Pagy::I18n.load({ locale: 'de' }, |
||||
|
# { locale: 'en' }, |
||||
|
# { locale: 'es' }) |
||||
|
# |
||||
|
# load the "en" built-in locale, a custom "es" locale, |
||||
|
# and a totally custom locale complete with a custom :pluralize proc: |
||||
|
# (the first passed :locale will be used also as the default_locale) |
||||
|
# Pagy::I18n.load({ locale: 'en' }, |
||||
|
# { locale: 'es', filepath: 'path/to/pagy-es.yml' }, |
||||
|
# { locale: 'xyz', # not built-in |
||||
|
# filepath: 'path/to/pagy-xyz.yml', |
||||
|
# pluralize: lambda{ |count| ... } ) |
||||
|
|
||||
|
|
||||
|
# I18n extra: uses the standard i18n gem which is ~18x slower using ~10x more memory |
||||
|
# than the default pagy internal i18n (see above) |
||||
|
# See https://ddnexus.github.io/pagy/docs/extras/i18n |
||||
|
# require 'pagy/extras/i18n' |
||||
|
|
||||
|
|
||||
|
# When you are done setting your own default freeze it, so it will not get changed accidentally |
||||
|
Pagy::DEFAULT.freeze |
||||
@ -0,0 +1,11 @@ |
|||||
|
# Define an application-wide HTTP permissions policy. For further |
||||
|
# information see https://developers.google.com/web/updates/2018/06/feature-policy |
||||
|
# |
||||
|
# Rails.application.config.permissions_policy do |f| |
||||
|
# f.camera :none |
||||
|
# f.gyroscope :none |
||||
|
# f.microphone :none |
||||
|
# f.usb :none |
||||
|
# f.fullscreen :self |
||||
|
# f.payment :self, "https://secure.example.com" |
||||
|
# end |
||||
@ -0,0 +1 @@ |
|||||
|
POSTAL_CONFIG = YAML.load_file("#{Rails.root.to_s}/config/postal.yml")["production"] |
||||
@ -0,0 +1,33 @@ |
|||||
|
# Files in the config/locales directory are used for internationalization |
||||
|
# and are automatically loaded by Rails. If you want to use locales other |
||||
|
# than English, add the necessary files in this directory. |
||||
|
# |
||||
|
# To use the locales, use `I18n.t`: |
||||
|
# |
||||
|
# I18n.t "hello" |
||||
|
# |
||||
|
# In views, this is aliased to just `t`: |
||||
|
# |
||||
|
# <%= t("hello") %> |
||||
|
# |
||||
|
# To use a different locale, set it with `I18n.locale`: |
||||
|
# |
||||
|
# I18n.locale = :es |
||||
|
# |
||||
|
# This would use the information in config/locales/es.yml. |
||||
|
# |
||||
|
# The following keys must be escaped otherwise they will not be retrieved by |
||||
|
# the default I18n backend: |
||||
|
# |
||||
|
# true, false, on, off, yes, no |
||||
|
# |
||||
|
# Instead, surround them with single quotes. |
||||
|
# |
||||
|
# en: |
||||
|
# "true": "foo" |
||||
|
# |
||||
|
# To learn more, please read the Rails Internationalization guide |
||||
|
# available at https://guides.rubyonrails.org/i18n.html. |
||||
|
|
||||
|
en: |
||||
|
hello: "Hello world" |
||||
@ -0,0 +1,13 @@ |
|||||
|
production: |
||||
|
host: 127.0.0.1 |
||||
|
database: postal1 |
||||
|
username: postal |
||||
|
password: postal |
||||
|
port: 3306 |
||||
|
|
||||
|
development: |
||||
|
host: 127.0.0.1 |
||||
|
database: postal1 |
||||
|
username: postal |
||||
|
password: postal |
||||
|
port: 3306 |
||||
@ -0,0 +1,43 @@ |
|||||
|
# Puma can serve each request in a thread from an internal thread pool. |
||||
|
# The `threads` method setting takes two numbers: a minimum and maximum. |
||||
|
# Any libraries that use thread pools should be configured to match |
||||
|
# the maximum value specified for Puma. Default is set to 5 threads for minimum |
||||
|
# and maximum; this matches the default thread size of Active Record. |
||||
|
# |
||||
|
max_threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 } |
||||
|
min_threads_count = ENV.fetch("RAILS_MIN_THREADS") { max_threads_count } |
||||
|
threads min_threads_count, max_threads_count |
||||
|
|
||||
|
# Specifies the `worker_timeout` threshold that Puma will use to wait before |
||||
|
# terminating a worker in development environments. |
||||
|
# |
||||
|
worker_timeout 3600 if ENV.fetch("RAILS_ENV", "development") == "development" |
||||
|
|
||||
|
# Specifies the `port` that Puma will listen on to receive requests; default is 3000. |
||||
|
# |
||||
|
port ENV.fetch("PORT") { 3000 } |
||||
|
|
||||
|
# Specifies the `environment` that Puma will run in. |
||||
|
# |
||||
|
environment ENV.fetch("RAILS_ENV") { "development" } |
||||
|
|
||||
|
# Specifies the `pidfile` that Puma will use. |
||||
|
pidfile ENV.fetch("PIDFILE") { "tmp/pids/server.pid" } |
||||
|
|
||||
|
# Specifies the number of `workers` to boot in clustered mode. |
||||
|
# Workers are forked web server processes. If using threads and workers together |
||||
|
# the concurrency of the application would be max `threads` * `workers`. |
||||
|
# Workers do not work on JRuby or Windows (both of which do not support |
||||
|
# processes). |
||||
|
# |
||||
|
# workers ENV.fetch("WEB_CONCURRENCY") { 2 } |
||||
|
|
||||
|
# Use the `preload_app!` method when specifying a `workers` number. |
||||
|
# This directive tells Puma to first boot the application and load code |
||||
|
# before forking the application. This takes advantage of Copy On Write |
||||
|
# process behavior so workers use less memory. |
||||
|
# |
||||
|
# preload_app! |
||||
|
|
||||
|
# Allow puma to be restarted by `bin/rails restart` command. |
||||
|
plugin :tmp_restart |
||||
@ -0,0 +1,9 @@ |
|||||
|
Rails.application.routes.draw do |
||||
|
resources :messages |
||||
|
resources :deliveries |
||||
|
get '/export', to: 'messages#export' |
||||
|
|
||||
|
# Defines the root path route ("/") |
||||
|
root "reports#index" |
||||
|
get '/search', to: 'reports#search' |
||||
|
end |
||||
@ -0,0 +1,34 @@ |
|||||
|
test: |
||||
|
service: Disk |
||||
|
root: <%= Rails.root.join("tmp/storage") %> |
||||
|
|
||||
|
local: |
||||
|
service: Disk |
||||
|
root: <%= Rails.root.join("storage") %> |
||||
|
|
||||
|
# Use bin/rails credentials:edit to set the AWS secrets (as aws:access_key_id|secret_access_key) |
||||
|
# amazon: |
||||
|
# service: S3 |
||||
|
# access_key_id: <%= Rails.application.credentials.dig(:aws, :access_key_id) %> |
||||
|
# secret_access_key: <%= Rails.application.credentials.dig(:aws, :secret_access_key) %> |
||||
|
# region: us-east-1 |
||||
|
# bucket: your_own_bucket-<%= Rails.env %> |
||||
|
|
||||
|
# Remember not to checkin your GCS keyfile to a repository |
||||
|
# google: |
||||
|
# service: GCS |
||||
|
# project: your_project |
||||
|
# credentials: <%= Rails.root.join("path/to/gcs.keyfile") %> |
||||
|
# bucket: your_own_bucket-<%= Rails.env %> |
||||
|
|
||||
|
# Use bin/rails credentials:edit to set the Azure Storage secret (as azure_storage:storage_access_key) |
||||
|
# microsoft: |
||||
|
# service: AzureStorage |
||||
|
# storage_account_name: your_account_name |
||||
|
# storage_access_key: <%= Rails.application.credentials.dig(:azure_storage, :storage_access_key) %> |
||||
|
# container: your_container_name-<%= Rails.env %> |
||||
|
|
||||
|
# mirror: |
||||
|
# service: Mirror |
||||
|
# primary: local |
||||
|
# mirrors: [ amazon, google, microsoft ] |
||||
@ -0,0 +1,251 @@ |
|||||
|
# This file is auto-generated from the current state of the database. Instead |
||||
|
# of editing this file, please use the migrations feature of Active Record to |
||||
|
# incrementally modify your database, and then regenerate this schema definition. |
||||
|
# |
||||
|
# This file is the source Rails uses to define your schema when running `bin/rails |
||||
|
# db:schema:load`. When creating a new database, `bin/rails db:schema:load` tends to |
||||
|
# be faster and is potentially less error prone than running all of your |
||||
|
# migrations from scratch. Old migrations may fail to apply correctly if those |
||||
|
# migrations use external dependencies or application code. |
||||
|
# |
||||
|
# It's strongly recommended that you check this file into your version control system. |
||||
|
|
||||
|
ActiveRecord::Schema[7.0].define(version: 0) do |
||||
|
create_table "clicks", id: :integer, charset: "utf8mb4", collation: "utf8mb4_unicode_ci", force: :cascade do |t| |
||||
|
t.integer "message_id" |
||||
|
t.integer "link_id" |
||||
|
t.string "ip_address" |
||||
|
t.string "country" |
||||
|
t.string "city" |
||||
|
t.string "user_agent" |
||||
|
t.decimal "timestamp", precision: 18, scale: 6 |
||||
|
t.index ["link_id"], name: "on_link_id" |
||||
|
t.index ["message_id"], name: "on_message_id" |
||||
|
end |
||||
|
|
||||
|
create_table "deliveries", id: :integer, charset: "utf8mb4", collation: "utf8mb4_unicode_ci", force: :cascade do |t| |
||||
|
t.integer "message_id" |
||||
|
t.string "status" |
||||
|
t.integer "code" |
||||
|
t.string "output", limit: 512 |
||||
|
t.string "details", limit: 512 |
||||
|
t.boolean "sent_with_ssl", default: false |
||||
|
t.string "log_id", limit: 100 |
||||
|
t.decimal "timestamp", precision: 18, scale: 6 |
||||
|
t.decimal "time", precision: 8, scale: 2 |
||||
|
t.index ["message_id"], name: "on_message_id" |
||||
|
end |
||||
|
|
||||
|
create_table "links", id: :integer, charset: "utf8mb4", collation: "utf8mb4_unicode_ci", force: :cascade do |t| |
||||
|
t.integer "message_id" |
||||
|
t.string "token" |
||||
|
t.string "hash" |
||||
|
t.text "url" |
||||
|
t.decimal "timestamp", precision: 18, scale: 6 |
||||
|
t.index ["message_id"], name: "on_message_id" |
||||
|
t.index ["token"], name: "on_token", length: 8 |
||||
|
end |
||||
|
|
||||
|
create_table "live_stats", primary_key: ["minute", "type"], charset: "utf8mb4", collation: "utf8mb4_unicode_ci", force: :cascade do |t| |
||||
|
t.string "type", limit: 20, null: false |
||||
|
t.integer "minute", null: false |
||||
|
t.integer "count" |
||||
|
t.decimal "timestamp", precision: 18, scale: 6 |
||||
|
end |
||||
|
|
||||
|
create_table "loads", id: :integer, charset: "utf8mb4", collation: "utf8mb4_unicode_ci", force: :cascade do |t| |
||||
|
t.integer "message_id" |
||||
|
t.string "ip_address" |
||||
|
t.string "country" |
||||
|
t.string "city" |
||||
|
t.string "user_agent" |
||||
|
t.decimal "timestamp", precision: 18, scale: 6 |
||||
|
t.index ["message_id"], name: "on_message_id" |
||||
|
end |
||||
|
|
||||
|
create_table "messages", id: :integer, charset: "utf8mb4", collation: "utf8mb4_unicode_ci", force: :cascade do |t| |
||||
|
t.string "token" |
||||
|
t.string "scope", limit: 10 |
||||
|
t.string "rcpt_to" |
||||
|
t.string "mail_from" |
||||
|
t.string "subject" |
||||
|
t.string "message_id" |
||||
|
t.decimal "timestamp", precision: 18, scale: 6 |
||||
|
t.integer "route_id" |
||||
|
t.integer "domain_id" |
||||
|
t.integer "credential_id" |
||||
|
t.string "status" |
||||
|
t.boolean "held", default: false |
||||
|
t.string "size" |
||||
|
t.decimal "last_delivery_attempt", precision: 18, scale: 6 |
||||
|
t.string "raw_table" |
||||
|
t.integer "raw_body_id" |
||||
|
t.integer "raw_headers_id" |
||||
|
t.boolean "inspected", default: false |
||||
|
t.boolean "spam", default: false |
||||
|
t.decimal "spam_score", precision: 8, scale: 2, default: "0.0" |
||||
|
t.boolean "threat", default: false |
||||
|
t.string "threat_details" |
||||
|
t.boolean "bounce", default: false |
||||
|
t.integer "bounce_for_id", default: 0 |
||||
|
t.string "tag" |
||||
|
t.decimal "loaded", precision: 18, scale: 6 |
||||
|
t.decimal "clicked", precision: 18, scale: 6 |
||||
|
t.boolean "received_with_ssl" |
||||
|
t.decimal "hold_expiry", precision: 18, scale: 6 |
||||
|
t.integer "tracked_links", default: 0 |
||||
|
t.integer "tracked_images", default: 0 |
||||
|
t.integer "parsed", limit: 1, default: 0 |
||||
|
t.integer "endpoint_id" |
||||
|
t.string "endpoint_type" |
||||
|
t.index ["bounce_for_id"], name: "on_bounce_for_id" |
||||
|
t.index ["held"], name: "on_held" |
||||
|
t.index ["mail_from", "timestamp"], name: "on_mail_from", length: { mail_from: 12 } |
||||
|
t.index ["message_id"], name: "on_message_id", length: 8 |
||||
|
t.index ["raw_table"], name: "on_raw_table", length: 14 |
||||
|
t.index ["rcpt_to", "timestamp"], name: "on_rcpt_to", length: { rcpt_to: 12 } |
||||
|
t.index ["scope", "spam", "status", "timestamp"], name: "on_scope_and_status", length: { scope: 1, status: 6 } |
||||
|
t.index ["scope", "spam", "tag", "timestamp"], name: "on_scope_and_tag", length: { scope: 1, tag: 8 } |
||||
|
t.index ["scope", "spam", "timestamp"], name: "on_scope_and_spam", length: { scope: 1 } |
||||
|
t.index ["scope", "threat", "status", "timestamp"], name: "on_scope_and_thr_status", length: { scope: 1, status: 6 } |
||||
|
t.index ["scope", "threat", "timestamp"], name: "on_scope_and_threat", length: { scope: 1 } |
||||
|
t.index ["status"], name: "on_status", length: 8 |
||||
|
t.index ["token"], name: "on_token", length: 6 |
||||
|
end |
||||
|
|
||||
|
create_table "migrations", primary_key: "version", id: :integer, default: nil, charset: "utf8mb4", collation: "utf8mb4_unicode_ci", force: :cascade do |t| |
||||
|
end |
||||
|
|
||||
|
create_table "raw-2024-04-01", id: :integer, charset: "utf8mb4", collation: "utf8mb4_general_ci", force: :cascade do |t| |
||||
|
t.binary "data", size: :long |
||||
|
t.integer "next" |
||||
|
end |
||||
|
|
||||
|
create_table "raw-2024-04-02", id: :integer, charset: "utf8mb4", collation: "utf8mb4_general_ci", force: :cascade do |t| |
||||
|
t.binary "data", size: :long |
||||
|
t.integer "next" |
||||
|
end |
||||
|
|
||||
|
create_table "raw-2024-04-05", id: :integer, charset: "utf8mb4", collation: "utf8mb4_general_ci", force: :cascade do |t| |
||||
|
t.binary "data", size: :long |
||||
|
t.integer "next" |
||||
|
end |
||||
|
|
||||
|
create_table "raw-2024-06-25", id: :integer, charset: "utf8mb4", collation: "utf8mb4_general_ci", force: :cascade do |t| |
||||
|
t.binary "data", size: :long |
||||
|
t.integer "next" |
||||
|
end |
||||
|
|
||||
|
create_table "raw-2024-06-26", id: :integer, charset: "utf8mb4", collation: "utf8mb4_general_ci", force: :cascade do |t| |
||||
|
t.binary "data", size: :long |
||||
|
t.integer "next" |
||||
|
end |
||||
|
|
||||
|
create_table "raw-2024-07-06", id: :integer, charset: "utf8mb4", collation: "utf8mb4_general_ci", force: :cascade do |t| |
||||
|
t.binary "data", size: :long |
||||
|
t.integer "next" |
||||
|
end |
||||
|
|
||||
|
create_table "raw-2024-07-07", id: :integer, charset: "utf8mb4", collation: "utf8mb4_general_ci", force: :cascade do |t| |
||||
|
t.binary "data", size: :long |
||||
|
t.integer "next" |
||||
|
end |
||||
|
|
||||
|
create_table "raw-2024-07-08", id: :integer, charset: "utf8mb4", collation: "utf8mb4_general_ci", force: :cascade do |t| |
||||
|
t.binary "data", size: :long |
||||
|
t.integer "next" |
||||
|
end |
||||
|
|
||||
|
create_table "raw-2024-07-09", id: :integer, charset: "utf8mb4", collation: "utf8mb4_general_ci", force: :cascade do |t| |
||||
|
t.binary "data", size: :long |
||||
|
t.integer "next" |
||||
|
end |
||||
|
|
||||
|
create_table "raw-2024-07-10", id: :integer, charset: "utf8mb4", collation: "utf8mb4_general_ci", force: :cascade do |t| |
||||
|
t.binary "data", size: :long |
||||
|
t.integer "next" |
||||
|
end |
||||
|
|
||||
|
create_table "raw_message_sizes", id: :integer, charset: "utf8mb4", collation: "utf8mb4_unicode_ci", force: :cascade do |t| |
||||
|
t.string "table_name" |
||||
|
t.bigint "size" |
||||
|
t.index ["table_name"], name: "on_table_name", length: 14 |
||||
|
end |
||||
|
|
||||
|
create_table "spam_checks", id: :integer, charset: "utf8mb4", collation: "utf8mb4_unicode_ci", force: :cascade do |t| |
||||
|
t.integer "message_id" |
||||
|
t.decimal "score", precision: 8, scale: 2 |
||||
|
t.string "code" |
||||
|
t.string "description" |
||||
|
t.index ["code"], name: "on_code", length: 8 |
||||
|
t.index ["message_id"], name: "on_message_id" |
||||
|
end |
||||
|
|
||||
|
create_table "stats_daily", id: :integer, charset: "utf8mb4", collation: "utf8mb4_unicode_ci", force: :cascade do |t| |
||||
|
t.integer "time" |
||||
|
t.bigint "incoming" |
||||
|
t.bigint "outgoing" |
||||
|
t.bigint "spam" |
||||
|
t.bigint "bounces" |
||||
|
t.bigint "held" |
||||
|
t.index ["time"], name: "on_time", unique: true |
||||
|
end |
||||
|
|
||||
|
create_table "stats_hourly", id: :integer, charset: "utf8mb4", collation: "utf8mb4_unicode_ci", force: :cascade do |t| |
||||
|
t.integer "time" |
||||
|
t.bigint "incoming" |
||||
|
t.bigint "outgoing" |
||||
|
t.bigint "spam" |
||||
|
t.bigint "bounces" |
||||
|
t.bigint "held" |
||||
|
t.index ["time"], name: "on_time", unique: true |
||||
|
end |
||||
|
|
||||
|
create_table "stats_monthly", id: :integer, charset: "utf8mb4", collation: "utf8mb4_unicode_ci", force: :cascade do |t| |
||||
|
t.integer "time" |
||||
|
t.bigint "incoming" |
||||
|
t.bigint "outgoing" |
||||
|
t.bigint "spam" |
||||
|
t.bigint "bounces" |
||||
|
t.bigint "held" |
||||
|
t.index ["time"], name: "on_time", unique: true |
||||
|
end |
||||
|
|
||||
|
create_table "stats_yearly", id: :integer, charset: "utf8mb4", collation: "utf8mb4_unicode_ci", force: :cascade do |t| |
||||
|
t.integer "time" |
||||
|
t.bigint "incoming" |
||||
|
t.bigint "outgoing" |
||||
|
t.bigint "spam" |
||||
|
t.bigint "bounces" |
||||
|
t.bigint "held" |
||||
|
t.index ["time"], name: "on_time", unique: true |
||||
|
end |
||||
|
|
||||
|
create_table "suppressions", id: :integer, charset: "utf8mb4", collation: "utf8mb4_unicode_ci", force: :cascade do |t| |
||||
|
t.string "type" |
||||
|
t.string "address" |
||||
|
t.string "reason" |
||||
|
t.decimal "timestamp", precision: 18, scale: 6 |
||||
|
t.decimal "keep_until", precision: 18, scale: 6 |
||||
|
t.index ["address"], name: "on_address", length: 6 |
||||
|
t.index ["keep_until"], name: "on_keep_until" |
||||
|
end |
||||
|
|
||||
|
create_table "webhook_requests", id: :integer, charset: "utf8mb4", collation: "utf8mb4_unicode_ci", force: :cascade do |t| |
||||
|
t.string "uuid" |
||||
|
t.string "event" |
||||
|
t.integer "attempt" |
||||
|
t.decimal "timestamp", precision: 18, scale: 6 |
||||
|
t.integer "status_code" |
||||
|
t.text "body" |
||||
|
t.text "payload" |
||||
|
t.integer "will_retry", limit: 1 |
||||
|
t.string "url" |
||||
|
t.integer "webhook_id" |
||||
|
t.index ["event"], name: "on_event", length: 8 |
||||
|
t.index ["timestamp"], name: "on_timestamp" |
||||
|
t.index ["uuid"], name: "on_uuid", length: 8 |
||||
|
t.index ["webhook_id"], name: "on_webhook_id" |
||||
|
end |
||||
|
|
||||
|
end |
||||
@ -0,0 +1,7 @@ |
|||||
|
# This file should contain all the record creation needed to seed the database with its default values. |
||||
|
# The data can then be loaded with the bin/rails db:seed command (or created alongside the database with db:setup). |
||||
|
# |
||||
|
# Examples: |
||||
|
# |
||||
|
# movies = Movie.create([{ name: "Star Wars" }, { name: "Lord of the Rings" }]) |
||||
|
# Character.create(name: "Luke", movie: movies.first) |
||||
@ -0,0 +1,61 @@ |
|||||
|
<style> |
||||
|
table, th, td { |
||||
|
border: 1px solid black; |
||||
|
border-collapse: collapse; |
||||
|
border-color: #96D4D4; |
||||
|
} |
||||
|
</style> |
||||
|
<div class="row justify-content-center"> |
||||
|
<h4 class="mt-4 display-4">Mail Delivery Report</h4> |
||||
|
</div> |
||||
|
<%= form_with url: "/search", method: :get do |form| %> |
||||
|
<%= form.label :date_from, "From" %> |
||||
|
<%= form.date_field :date_from %> |
||||
|
<%= form.label :date_to, "To" %> |
||||
|
<%= form.date_field :date_to %> |
||||
|
<%= form.label :rcpt_to, "To" %> |
||||
|
<%= form.email_field :rcpt_to %> |
||||
|
<%= form.label :mail_from, "From" %> |
||||
|
<%= form.email_field :mail_from %> |
||||
|
<%= form.label :status, "Status" %> |
||||
|
<%= form.select :status , ['All', 'Sent','SoftFail', 'HardFail','Held'] %> |
||||
|
<%= form.submit "search" %> |
||||
|
<% end %> |
||||
|
<%= link_to "Download Report" ,:action => :export %> |
||||
|
|
||||
|
<div class="container "> |
||||
|
<% if @mails.present? %> |
||||
|
<div class="row justify-content-center border p-2 border-dark rounded m-2 overflow-auto"> |
||||
|
<table class="table table-bordered"> |
||||
|
<thead> |
||||
|
<tr> |
||||
|
<th scope="col" style="text-align: center;">Message ID</th> |
||||
|
<th scope="col" style="text-align: center;">Sender</th> |
||||
|
<th scope="col" style="text-align: center;">Recipient</th> |
||||
|
<th scope="col" style="text-align: center;">Subject</th> |
||||
|
<th scope="col" style="text-align: center;">Date</th> |
||||
|
<th scope="col" style="text-align: center;">Time</th> |
||||
|
<th scope="col" style="text-align: center;">Size</th> |
||||
|
<th scope="col" style="text-align: center;">Status</th> |
||||
|
<th scope="col" style="text-align: center;">Delivery Details</th> |
||||
|
</tr> |
||||
|
</thead> |
||||
|
<tbody> |
||||
|
<% @mails.each(:as => :hash ) do |mail| %> |
||||
|
<tr> |
||||
|
<td style="text-align: center;"><%= mail['message_id'] %></td> |
||||
|
<td style="text-align: center;"><%= mail['mail_from'] %></td> |
||||
|
<td style="text-align: center;"><%= mail['rcpt_to'] %></td> |
||||
|
<td style="text-align: center;"><%= mail['subject'] %></td> |
||||
|
<td style="text-align: center;"><%= Time.at(mail['timestamp']).strftime('%d-%m-%Y') %></td> |
||||
|
<td style="text-align: center;"><%= Time.at(mail['timestamp']).strftime('%H:%M:%S') %></td> |
||||
|
<td style="text-align: center;"><%= mail['size'].to_f >= 1048576 ? "#{(mail['size'].to_d/1048576).round(2)} MB" : "#{(mail['size'].to_d/1024).round(2)} KB"%></td> |
||||
|
<td style="text-align: center;"><%= mail['status'] == "Sent"? "Delivered": mail['status'] %></td> |
||||
|
<td><%= mail['details'] %></td> |
||||
|
</tr> |
||||
|
<% end %> |
||||
|
</tbody> |
||||
|
</table> |
||||
|
</div> |
||||
|
<% end %> |
||||
|
</div> |
||||
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue