123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380 |
- ;;; GNU Guix --- Functional package management for GNU
- ;;; Copyright © 2019 Christopher Baines <mail@cbaines.net>
- ;;;
- ;;; This file is part of GNU Guix.
- ;;;
- ;;; GNU Guix is free software; you can redistribute it and/or modify it
- ;;; under the terms of the GNU General Public License as published by
- ;;; the Free Software Foundation; either version 3 of the License, or (at
- ;;; your option) any later version.
- ;;;
- ;;; GNU Guix is distributed in the hope that it will be useful, but
- ;;; WITHOUT ANY WARRANTY; without even the implied warranty of
- ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- ;;; GNU General Public License for more details.
- ;;;
- ;;; You should have received a copy of the GNU General Public License
- ;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
- (define-module (gnu services getmail)
- #:use-module (gnu services)
- #:use-module (gnu services base)
- #:use-module (gnu services configuration)
- #:use-module (gnu services shepherd)
- #:use-module (gnu system pam)
- #:use-module (gnu system shadow)
- #:use-module (gnu packages mail)
- #:use-module (gnu packages admin)
- #:use-module (gnu packages tls)
- #:use-module (guix records)
- #:use-module (guix store)
- #:use-module (guix packages)
- #:use-module (guix gexp)
- #:use-module (ice-9 match)
- #:use-module (ice-9 format)
- #:use-module (srfi srfi-1)
- #:export (getmail-retriever-configuration
- getmail-retriever-configuration-extra-parameters
- getmail-destination-configuration
- getmail-options-configuration
- getmail-configuration-file
- getmail-configuration
- getmail-service-type))
- ;;; Commentary:
- ;;;
- ;;; Service for the getmail mail retriever.
- ;;;
- ;;; Code:
- (define (uglify-field-name field-name)
- (let ((str (symbol->string field-name)))
- (string-join (string-split (if (string-suffix? "?" str)
- (substring str 0 (1- (string-length str)))
- str)
- #\-)
- "_")))
- (define (serialize-field field-name val)
- #~(let ((val '#$val))
- (format #f "~a = ~a\n"
- #$(uglify-field-name field-name)
- (cond
- ((list? val)
- (string-append
- "("
- (string-concatenate
- (map (lambda (list-val)
- (format #f "\"~a\", " list-val))
- val))
- ")"))
- (else
- val)))))
- (define (serialize-string field-name val)
- (if (string=? val "")
- ""
- (serialize-field field-name val)))
- (define (string-or-filelike? val)
- (or (string? val)
- (file-like? val)))
- (define (serialize-string-or-filelike field-name val)
- (if (equal? val "")
- ""
- (serialize-field field-name val)))
- (define (serialize-boolean field-name val)
- (serialize-field field-name (if val "true" "false")))
- (define (non-negative-integer? val)
- (and (exact-integer? val) (not (negative? val))))
- (define (serialize-non-negative-integer field-name val)
- (serialize-field field-name val))
- (define serialize-list serialize-field)
- (define parameter-alist? list?)
- (define (serialize-parameter-alist field-name val)
- #~(string-append
- #$@(map (match-lambda
- ((key . value)
- (serialize-field key value)))
- val)))
- (define (serialize-getmail-retriever-configuration field-name val)
- (serialize-configuration val getmail-retriever-configuration-fields))
- (define-configuration getmail-retriever-configuration
- (type
- (string "SimpleIMAPSSLRetriever")
- "The type of mail retriever to use. Valid values include
- @samp{passwd} and @samp{static}.")
- (server
- string
- "Name or IP address of the server to retrieve mail from.")
- (username
- string
- "Username to login to the mail server with.")
- (port
- (non-negative-integer #f)
- "Port number to connect to.")
- (password
- (string "")
- "Override fields from passwd.")
- (password-command
- (list '())
- "Override fields from passwd.")
- (keyfile
- (string "")
- "PEM-formatted key file to use for the TLS negotiation.")
- (certfile
- (string "")
- "PEM-formatted certificate file to use for the TLS negotiation.")
- (ca-certs
- (string "")
- "CA certificates to use.")
- (extra-parameters
- (parameter-alist '())
- "Extra retriever parameters."))
- (define (serialize-getmail-destination-configuration field-name val)
- (serialize-configuration val getmail-destination-configuration-fields))
- (define-configuration getmail-destination-configuration
- (type
- string
- "The type of mail destination. Valid values include @samp{Maildir},
- @samp{Mboxrd} and @samp{MDA_external}.")
- (path
- (string-or-filelike "")
- "The path option for the mail destination. The behaviour depends on the
- chosen type.")
- (extra-parameters
- (parameter-alist '())
- "Extra destination parameters"))
- (define (serialize-getmail-options-configuration field-name val)
- (serialize-configuration val getmail-options-configuration-fields))
- (define-configuration getmail-options-configuration
- (verbose
- (non-negative-integer 1)
- "If set to @samp{0}, getmail will only print warnings and errors. A value
- of @samp{1} means that messages will be printed about retrieving and deleting
- messages. If set to @samp{2}, getmail will print messages about each of it's
- actions.")
- (read-all
- (boolean #t)
- "If true, getmail will retrieve all available messages. Otherwise it will
- only retrieve messages it hasn't seen previously.")
- (delete
- (boolean #f)
- "If set to true, messages will be deleted from the server after retrieving
- and successfully delivering them. Otherwise, messages will be left on the
- server.")
- (delete-after
- (non-negative-integer 0)
- "Getmail will delete messages this number of days after seeing them, if
- they have been delivered. This means messages will be left on the server this
- number of days after delivering them. A value of @samp{0} disabled this
- feature.")
- (delete-bigger-than
- (non-negative-integer 0)
- "Delete messages larger than this of bytes after retrieving them, even if
- the delete and delete-after options are disabled. A value of @samp{0}
- disables this feature.")
- (max-bytes-per-session
- (non-negative-integer 0)
- "Retrieve messages totalling up to this number of bytes before closing the
- session with the server. A value of @samp{0} disables this feature.")
- (max-message-size
- (non-negative-integer 0)
- "Don't retrieve messages larger than this number of bytes. A value of
- @samp{0} disables this feature.")
- (delivered-to
- (boolean #t)
- "If true, getmail will add a Delivered-To header to messages.")
- (received
- (boolean #t)
- "If set, getmail adds a Received header to the messages.")
- (message-log
- (string "")
- "Getmail will record a log of its actions to the named file. A value of
- @samp{\"\"} disables this feature.")
- (message-log-syslog
- (boolean #f)
- "If true, getmail will record a log of its actions using the system
- logger.")
- (message-log-verbose
- (boolean #f)
- "If true, getmail will log information about messages not retrieved and the
- reason for not retrieving them, as well as starting and ending information
- lines.")
- (extra-parameters
- (parameter-alist '())
- "Extra options to include."))
- (define-configuration getmail-configuration-file
- (retriever
- (getmail-retriever-configuration (getmail-retriever-configuration))
- "What mail account to retrieve mail from, and how to access that account.")
- (destination
- (getmail-destination-configuration (getmail-destination-configuration))
- "What to do with retrieved messages.")
- (options
- (getmail-options-configuration (getmail-options-configuration))
- "Configure getmail."))
- (define (serialize-getmail-configuration-file field-name val)
- (match-record val <getmail-configuration-file>
- (retriever destination options)
- #~(string-append
- "[retriever]\n"
- #$(serialize-getmail-retriever-configuration #f retriever)
- "\n[destination]\n"
- #$(serialize-getmail-destination-configuration #f destination)
- "\n[options]\n"
- #$(serialize-getmail-options-configuration #f options))))
- (define (serialize-symbol field-name val) "")
- (define (serialize-getmail-configuration field-name val) "")
- (define-configuration getmail-configuration
- (name
- (symbol "unset")
- "A symbol to identify the getmail service.")
- (package
- (file-like getmail)
- "The getmail package to use.")
- (user
- (string "getmail")
- "The user to run getmail as.")
- (group
- (string "getmail")
- "The group to run getmail as.")
- (directory
- (string "/var/lib/getmail/default")
- "The getmail directory to use.")
- (rcfile
- (getmail-configuration-file (getmail-configuration-file))
- "The getmail configuration file to use.")
- (idle
- (list '())
- "A list of mailboxes that getmail should wait on the server for new mail
- notifications. This depends on the server supporting the IDLE extension.")
- (environment-variables
- (list '())
- "Environment variables to set for getmail."))
- (define (generate-getmail-documentation)
- (generate-documentation
- `((getmail-configuration
- ,getmail-configuration-fields
- (rcfile getmail-configuration-file))
- (getmail-configuration-file
- ,getmail-configuration-file-fields
- (retriever getmail-retriever-configuration)
- (destination getmail-destination-configuration)
- (options getmail-options-configuration))
- (getmail-retriever-configuration ,getmail-retriever-configuration-fields)
- (getmail-destination-configuration ,getmail-destination-configuration-fields)
- (getmail-options-configuration ,getmail-options-configuration-fields))
- 'getmail-configuration))
- (define-gexp-compiler (getmail-configuration-file-compiler
- (rcfile <getmail-configuration-file>) system target)
- (gexp->derivation
- "getmailrc"
- #~(call-with-output-file #$output
- (lambda (port)
- (display #$(serialize-getmail-configuration-file #f rcfile)
- port)))
- #:system system
- #:target target))
- (define (getmail-accounts configs)
- (let ((users (delete-duplicates
- (map getmail-configuration-user
- configs)))
- (groups (delete-duplicates
- (map getmail-configuration-group
- configs))))
- (append
- (map (lambda (group)
- (user-group
- (name group)
- (system? #t)))
- groups)
- (map (lambda (user)
- (user-account
- (name user)
- (group (getmail-configuration-group
- (find (lambda (config)
- (and
- (string=? user (getmail-configuration-user config))
- (getmail-configuration-group config)))
- configs)))
- (system? #t)
- (comment "Getmail user")
- (home-directory "/var/empty")
- (shell (file-append shadow "/sbin/nologin"))))
- users))))
- (define (getmail-activation configs)
- "Return the activation GEXP for CONFIGS."
- (with-imported-modules '((guix build utils))
- #~(begin
- (use-modules (guix build utils))
- #$@(map
- (lambda (config)
- #~(let* ((pw (getpw #$(getmail-configuration-user config)))
- (uid (passwd:uid pw))
- (gid (passwd:gid pw))
- (getmaildir #$(getmail-configuration-directory config)))
- (mkdir-p getmaildir)
- (chown getmaildir uid gid)))
- configs))))
- (define (getmail-shepherd-services configs)
- "Return a list of <shepherd-service> for CONFIGS."
- (map (lambda (config)
- (match-record config <getmail-configuration>
- (name package user group directory rcfile idle environment-variables)
- (shepherd-service
- (documentation "Run getmail.")
- (provision (list (symbol-append 'getmail- name)))
- (requirement '(networking))
- (start #~(make-forkexec-constructor
- `(#$(file-append package "/bin/getmail")
- ,(string-append "--getmaildir=" #$directory)
- #$@(map (lambda (idle)
- (string-append "--idle=" idle))
- idle)
- ,(string-append "--rcfile=" #$rcfile))
- #:user #$user
- #:group #$group
- #:environment-variables
- (list #$@environment-variables)
- #:log-file
- #$(string-append "/var/log/getmail-"
- (symbol->string name))))
- (stop #~(make-kill-destructor)))))
- configs))
- (define getmail-service-type
- (service-type
- (name 'getmail)
- (extensions
- (list (service-extension shepherd-root-service-type
- getmail-shepherd-services)
- (service-extension activation-service-type
- getmail-activation)
- (service-extension account-service-type
- getmail-accounts)))
- (description
- "Run @command{getmail}, a mail retriever program.")
- (default-value '())
- (compose concatenate)
- (extend append)))
|