Initial Commit
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
Markus Pesch 2021-08-31 18:47:34 +02:00
commit 4a4d350e20
Signed by: volker.raschek
GPG Key ID: 852BCC170D81A982
12 changed files with 624 additions and 0 deletions

5
.dev_env Normal file
View File

@ -0,0 +1,5 @@
DATABASE_TYPE=Pg
DATABASE_HOST=localhost
DATABASE_NAME=postgres
DATABASE_USER=fetchmail
DATABASE_PASSWORD=MySecretPassword

164
.drone.yml Normal file
View File

@ -0,0 +1,164 @@
---
kind: pipeline
type: kubernetes
name: linter
platform:
os: linux
arch: amd64
steps:
- name: markdown lint
commands:
- markdownlint *.md
image: docker.io/tmknom/markdownlint:0.23.1
resources:
limits:
cpu: 50
memory: 50M
- name: email-notification
environment:
PLUGIN_HOST:
from_secret: smtp_host
PLUGIN_USERNAME:
from_secret: smtp_username
PLUGIN_PASSWORD:
from_secret: smtp_password
PLUGIN_FROM:
from_secret: smtp_mail_address
image: docker.io/drillster/drone-email:latest
resources:
limits:
cpu: 50
memory: 25M
when:
status:
- changed
- failure
trigger:
event:
exclude:
- tag
---
kind: pipeline
type: docker
name: build
platform:
os: linux
arch: amd64
steps:
- name: build
image: docker.io/volkerraschek/build-image:latest
commands:
- make container-image/build
volumes:
- name: docker_socket
path: /var/run/docker.sock
when:
branch:
- master
- name: push
image: docker.io/volkerraschek/build-image:latest
commands:
- make container-image/push
environment:
FETCHMAIL_IMAGE_REGISTRY_PASSWORD:
from_secret: container_image_registry_password
volumes:
- name: docker_socket
path: /var/run/docker.sock
when:
branch:
- master
repo:
- volker.raschek/fetchmail-docker
- name: delete
image: docker.io/volkerraschek/build-image:latest
commands:
- make container-image/delete
volumes:
- name: docker_socket
path: /var/run/docker.sock
when:
branch:
- master
- name: notify
image: drillster/drone-email
environment:
PLUGIN_HOST:
from_secret: smtp_host
PLUGIN_USERNAME:
from_secret: smtp_username
PLUGIN_PASSWORD:
from_secret: smtp_password
PLUGIN_FROM:
from_secret: smtp_mail_address
when:
status:
- changed
- failure
volumes:
- name: docker_socket
host:
path: /var/run/docker.sock
trigger:
event:
exclude:
- tag
---
kind: pipeline
type: kubernetes
name: sync
platform:
os: linux
arch: amd64
steps:
- name: github
image: docker.io/appleboy/drone-git-push:latest
resources:
limits:
cpu: 50
memory: 25M
settings:
branch: master
remote: ssh://git@github.com/volker-raschek/fetchmail-docker.git
force: true
ssh_key:
from_secret: ssh_key
- name: email-notification
environment:
PLUGIN_HOST:
from_secret: smtp_host
PLUGIN_USERNAME:
from_secret: smtp_username
PLUGIN_PASSWORD:
from_secret: smtp_password
PLUGIN_FROM:
from_secret: smtp_mail_address
image: docker.io/drillster/drone-email:latest
resources:
limits:
cpu: 50
memory: 25M
when:
status:
- changed
- failure
trigger:
event:
- push
repo:
- volker.raschek/fetchmail-docker

12
.editorconfig Normal file
View File

@ -0,0 +1,12 @@
root = true
[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = false
[Makefile]
indent_style = tab

1
.gitattributes vendored Normal file
View File

@ -0,0 +1 @@
Makefile eol=lf

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
.env

144
.markdownlint.yaml Normal file
View File

@ -0,0 +1,144 @@
# markdownlint YAML configuration
# https://github.com/DavidAnson/markdownlint/blob/main/schema/.markdownlint.yaml
# Default state for all rules
default: true
# Path to configuration file to extend
extends: null
# MD003/heading-style/header-style - Heading style
MD003:
# Heading style
style: "atx"
# MD004/ul-style - Unordered list style
MD004:
style: "dash"
# MD007/ul-indent - Unordered list indentation
MD007:
# Spaces for indent
indent: 2
# Whether to indent the first level of the list
start_indented: false
# MD009/no-trailing-spaces - Trailing spaces
MD009:
# Spaces for line break
br_spaces: 2
# Allow spaces for empty lines in list items
list_item_empty_lines: false
# Include unnecessary breaks
strict: false
# MD010/no-hard-tabs - Hard tabs
MD010:
# Include code blocks
code_blocks: true
# MD012/no-multiple-blanks - Multiple consecutive blank lines
MD012:
# Consecutive blank lines
maximum: 1
# MD013/line-length - Line length
MD013:
# Number of characters
line_length: 80
# Number of characters for headings
heading_line_length: 80
# Number of characters for code blocks
code_block_line_length: 80
# Include code blocks
code_blocks: false
# Include tables
tables: false
# Include headings
headings: true
# Include headings
headers: true
# Strict length checking
strict: false
# Stern length checking
stern: false
# MD022/blanks-around-headings/blanks-around-headers - Headings should be surrounded by blank lines
MD022:
# Blank lines above heading
lines_above: 1
# Blank lines below heading
lines_below: 1
# MD024/no-duplicate-heading/no-duplicate-header - Multiple headings with the same content
MD024:
# Only check sibling headings
allow_different_nesting: true
# MD025/single-title/single-h1 - Multiple top-level headings in the same document
MD025:
# Heading level
level: 1
# RegExp for matching title in front matter
front_matter_title: "^\\s*title\\s*[:=]"
# MD026/no-trailing-punctuation - Trailing punctuation in heading
MD026:
# Punctuation characters
punctuation: ".,;:!。,;:!"
# MD029/ol-prefix - Ordered list item prefix
MD029:
# List style
style: "one_or_ordered"
# MD030/list-marker-space - Spaces after list markers
MD030:
# Spaces for single-line unordered list items
ul_single: 1
# Spaces for single-line ordered list items
ol_single: 1
# Spaces for multi-line unordered list items
ul_multi: 1
# Spaces for multi-line ordered list items
ol_multi: 1
# MD033/no-inline-html - Inline HTML
MD033:
# Allowed elements
allowed_elements: []
# MD035/hr-style - Horizontal rule style
MD035:
# Horizontal rule style
style: "---"
# MD036/no-emphasis-as-heading/no-emphasis-as-header - Emphasis used instead of a heading
MD036:
# Punctuation characters
punctuation: ".,;:!?。,;:!?"
# MD041/first-line-heading/first-line-h1 - First line in a file should be a top-level heading
MD041:
# Heading level
level: 1
# RegExp for matching title in front matter
front_matter_title: "^\\s*title\\s*[:=]"
# MD044/proper-names - Proper names should have the correct capitalization
MD044:
# List of proper names
names: []
# - some-thing
# Include code blocks
code_blocks: false
# MD046/code-block-style - Code block style
MD046:
# Block style
style: "fenced"
# MD048/code-fence-style - Code fence style
MD048:
# Code fence syle
style: "backtick"

12
Dockerfile Normal file
View File

@ -0,0 +1,12 @@
FROM docker.io/library/alpine:3.11.2
RUN echo "http://dl-3.alpinelinux.org/alpine/edge/testing/" >> /etc/apk/repositories
RUN apk add --update perl perl-lockfile-simple perl-dbi perl-dbd-pg perl-dbd-mysql fetchmail
RUN mkdir --parents /run/fetchmail
COPY --chown=fetchmail:fetchmail fetchmail.pl /usr/local/bin/fetchmail.pl
USER fetchmail
ENTRYPOINT [ "/usr/bin/perl" ]
CMD [ "/usr/local/bin/fetchmail.pl" ]

13
LICENSE Normal file
View File

@ -0,0 +1,13 @@
Copyright 2019 Markus Pesch
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

47
Makefile Normal file
View File

@ -0,0 +1,47 @@
# CONTAINER_RUNTIME
# The CONTAINER_RUNTIME variable will be used to specified the path to a
# container runtime. This is needed to start and run a container image.
CONTAINER_RUNTIME?=$(shell which docker)
# FETCHMAIL_IMAGE_REGISTRY_NAME
# Defines the name of the new container to be built using several variables.
FETCHMAIL_IMAGE_REGISTRY_NAME:=docker.io
FETCHMAIL_IMAGE_REGISTRY_USER:=volkerraschek
FETCHMAIL_IMAGE_NAMESPACE?=${FETCHMAIL_IMAGE_REGISTRY_USER}
FETCHMAIL_IMAGE_NAME:=fetchmail
FETCHMAIL_IMAGE_VERSION?=latest
FETCHMAIL_IMAGE_FULLY_QUALIFIED=${FETCHMAIL_IMAGE_REGISTRY_NAME}/${FETCHMAIL_IMAGE_NAMESPACE}/${FETCHMAIL_IMAGE_NAME}:${FETCHMAIL_IMAGE_VERSION}
FETCHMAIL_IMAGE_UNQUALIFIED=${FETCHMAIL_IMAGE_NAMESPACE}/${FETCHMAIL_IMAGE_NAME}:${FETCHMAIL_IMAGE_VERSION}
# BUILD CONTAINER IMAGE
# ==============================================================================
PHONY:=container-image/build
container-image/build:
${CONTAINER_RUNTIME} build \
--file Dockerfile \
--no-cache \
--pull \
--tag ${FETCHMAIL_IMAGE_FULLY_QUALIFIED} \
--tag ${FETCHMAIL_IMAGE_UNQUALIFIED} \
.
# DELETE CONTAINER IMAGE
# ==============================================================================
PHONY:=container-image/delete
container-image/delete:
- ${CONTAINER_RUNTIME} image rm ${FETCHMAIL_IMAGE_FULLY_QUALIFIED} ${FETCHMAIL_IMAGE_UNQUALIFIED}
- ${CONTAINER_RUNTIME} image rm ${BASE_IMAGE_FULL}
# PUSH CONTAINER IMAGE
# ==============================================================================
PHONY+=container-image/push
container-image/push:
echo ${FETCHMAIL_IMAGE_REGISTRY_PASSWORD} | ${CONTAINER_RUNTIME} login ${FETCHMAIL_IMAGE_REGISTRY_NAME} --username ${FETCHMAIL_IMAGE_REGISTRY_USER} --password-stdin
${CONTAINER_RUNTIME} push ${FETCHMAIL_IMAGE_FULLY_QUALIFIED}
# PHONY
# ==============================================================================
# Declare the contents of the PHONY variable as phony. We keep that information
# in a variable so we can use it in if_changed.
.PHONY: ${PHONY}

79
README.md Normal file
View File

@ -0,0 +1,79 @@
# fetchmail-docker
[![Build Status](https://drone.cryptic.systems/api/badges/volker.raschek/fetchmail-docker/status.svg)](https://drone.cryptic.systems/volker.raschek/fetchmail-docker)
[![Docker Pulls](https://img.shields.io/docker/pulls/volkerraschek/fetchmail)](https://hub.docker.com/r/volkerraschek/fetchmail)
This project contains all sources to build the container image
`docker.io/volkerraschek/fetchmail`. The primary goal of the image is to fetch
mails from external servers and forward them to on local running mail server.
The configuration file will be automatically generated based on information from
a database. As table the fetchmail table from the schema of
[postfixadmin](https://github.com/postfixadmin/postfixadmin) is expected.
## Usage
Possible database types are `my` for MySQL and `Pg` for postgres. Make sure that
the database and the SMTP server are accessible. Otherwise, adjust the enclosed
docker-compose or docker command accordingly. Alternatively you can use
docker-compose in addition to the docker commands.
### PostgreSQL
```bash
$ docker run \
--rm \
--env DATABASE_TYPE: Pg \
--env DATABASE_HOST: postgres \
--env DATABASE_NAME: postgres \
--env DATABASE_USER: fetchmail \
--env DATABASE_PASSWORD: MySecretPassword \
--network host \
volkerraschek/fetchmail:latest
```
### MySQL
```bash
$ docker run \
--rm \
--env DATABASE_TYPE: my \
--env DATABASE_HOST: root \
--env DATABASE_NAME: mysql \
--env DATABASE_USER: fetchmail \
--env DATABASE_PASSWORD: MySecretPassword \
--network host \
volkerraschek/fetchmail:latest
```
### docker-compose
The repository contains a default `docker-compose.yml` file, which can be used
to start the container. To set the environment variables you need a `.env` file.
The `.dev_env` from this repository can be used for this. This must be located
exclusively in the same directory as the `docker-compose.yml` file and must be
renamed as `.env`.
```yml
version: "3"
services:
fetchmail:
image: volkerraschek/fetchmail:latest
environment:
- DATABASE_TYPE=${DATABASE_TYPE}
- DATABASE_HOST=${DATABASE_HOST}
- DATABASE_NAME=${DATABASE_NAME}
- DATABASE_USER=${DATABASE_USER}
- DATABASE_PASSWORD=${DATABASE_PASSWORD}
network_mode: host
```
## Build container image manually
To build the images manually check out the repository on
[github](https://github.com/volker-raschek/fetchmail-docker) with git and use
the make command to build the container image.
```bash
make container-image/build
```

12
docker-compose.yml Normal file
View File

@ -0,0 +1,12 @@
version: "3"
services:
fetchmail:
container_name: fetchmail
image: volkerraschek/fetchmail-docker:latest
environment:
- DATABASE_TYPE=${DATABASE_TYPE}
- DATABASE_HOST=${DATABASE_HOST}
- DATABASE_NAME=${DATABASE_NAME}
- DATABASE_USER=${DATABASE_USER}
- DATABASE_PASSWORD=${DATABASE_PASSWORD}
network_mode: host

134
fetchmail.pl Executable file
View File

@ -0,0 +1,134 @@
#!/usr/bin/perl
use DBI;
use MIME::Base64;
# use Data::Dumper;
use File::Temp qw/ mkstemp /;
use Sys::Syslog;
# require liblockfile-simple-perl
use LockFile::Simple qw(lock trylock unlock);
######################################################################
########## Change the following variables to fit your needs ##########
# database settings
# database backend - uncomment one of these
our $db_type=$ENV{'DATABASE_TYPE'};
our $db_host=$ENV{'DATABASE_HOST'};
our $db_name=$ENV{'DATABASE_NAME'};
our $db_username=$ENV{'DATABASE_USER'};
our $db_password=$ENV{'DATABASE_PASSWORD'};
# instead of changing this script, you can put your settings to /etc/mail/postfixadmin/fetchmail.conf
# just use perl syntax there to fill the variables listed above (without the "our" keyword). Example:
# $db_username = 'mail';
if (-f "/etc/mail/postfixadmin/fetchmail.conf") {
require "/etc/mail/postfixadmin/fetchmail.conf";
}
#################### Don't change anything below! ####################
######################################################################
openlog("fetchmail-all", "pid", "mail");
sub log_and_die {
my($message) = @_;
syslog("err", $message);
die $message;
}
# read options and arguments
$configfile = "/etc/fetchmail-all/config";
@ARGS1 = @ARGV;
while ($_ = shift @ARGS1) {
if (/^-/) {
if (/^--config$/) {
$configfile = shift @ARGS1
}
}
}
$run_dir="/run/fetchmail";
# use specified config file
if (-e $configfile) {
do $configfile;
}
if($db_type eq "Pg" || $db_type eq "mysql") {
$dsn = "DBI:$db_type:database=$db_name;host=$db_host";
} else {
log_and_die "unsupported db_type $db_type";
}
$lock_file=$run_dir . "/fetchmail-all.lock";
$lockmgr = LockFile::Simple->make(-autoclean => 1, -max => 1);
$lockmgr->lock($lock_file) || log_and_die "can't lock ${lock_file}";
# database connect
$dbh = DBI->connect($dsn, $db_username, $db_password) || log_and_die "cannot connect the database";
if($db_type eq "Pg") {
$sql_cond = "active = 't' AND date_part('epoch',now())-date_part('epoch',date)";
} elsif($db_type eq "mysql") {
$sql_cond = "active = 1 AND unix_timestamp(now())-unix_timestamp(date)";
}
$sql = "
SELECT id,mailbox,src_server,src_auth,src_user,src_password,src_folder,fetchall,keep,protocol,mda,extra_options,usessl, sslcertck, sslcertpath, sslfingerprint
FROM fetchmail
WHERE $sql_cond > poll_time*60
";
my (%config);
map{
my ($id,$mailbox,$src_server,$src_auth,$src_user,$src_password,$src_folder,$fetchall,$keep,$protocol,$mda,$extra_options,$usessl,$sslcertck,$sslcertpath,$sslfingerprint)=@$_;
syslog("info","fetch ${src_user}@${src_server} for ${mailbox}");
$cmd="user '${src_user}' there with password '".decode_base64($src_password)."'";
$cmd.=" folder '${src_folder}'" if ($src_folder);
$cmd.=" mda ".$mda if ($mda);
# $cmd.=" mda \"/usr/local/libexec/dovecot/deliver -m ${mailbox}\"";
$cmd.=" is '${mailbox}' here";
$cmd.=" keep" if ($keep);
$cmd.=" fetchall" if ($fetchall);
$cmd.=" ssl" if ($usessl);
$cmd.=" sslcertck" if($sslcertck);
$cmd.=" sslcertpath $sslcertpath" if ($sslcertck && $sslcertpath);
$cmd.=" sslfingerprint \"$sslfingerprint\"" if ($sslfingerprint);
$cmd.=" ".$extra_options if ($extra_options);
$text=<<TXT;
set postmaster "postmaster"
set nobouncemail
set no spambounce
set properties ""
set syslog
poll ${src_server} with proto ${protocol}
$cmd
TXT
($file_handler, $filename) = mkstemp( "/tmp/fetchmail-all-XXXXX" ) or log_and_die "cannot open/create fetchmail temp file";
print $file_handler $text;
close $file_handler;
$ret=`/usr/bin/fetchmail -f $filename -i $run_dir/fetchmail.pid`;
unlink $filename;
$sql="UPDATE fetchmail SET returned_text=".$dbh->quote($ret).", date=now() WHERE id=".$id;
$dbh->do($sql);
}@{$dbh->selectall_arrayref($sql)};
$lockmgr->unlock($lock_file);
closelog();