[PATCH] services: mail: add opensmtpd records to enhance opensmtpd-configuration.

  • Open
  • quality assurance status badge
Details
4 participants
  • Joshua Branson
  • Joshua Branson
  • Liliana Marie Prikler
  • Vivien Kraus
Owner
unassigned
Submitted by
Joshua Branson
Severity
normal
J
J
Joshua Branson wrote on 17 Jun 2022 23:46
(address . guix-patches@gnu.org)(name . Joshua Branson)(address . jbranso@dismail.de)
20220617214618.12377-1-jbranso@dismail.de
Openmstpd-configuration may only be configured by a config-file. This
patch, enables one to configure opensmtpd by using some guile record
types (defined via define-record-type*).

This patch is mostly complete, but I could use some guidance on what
else needs to be done for it to be accepted in to guix properly.
I do have some documentation written for the opensmtpd-service,
but it is probably not complete and is currently written in the
org-mode format.

* gnu/services/mail.scm (opensmtpd-table-configuration): New record.
* gnu/services/mail.scm (opensmtpd-ca-configuration): New record.
* gnu/services/mail.scm (opensmtpd-pki-configuration): New record.
* gnu/services/mail.scm (opensmtpd-action-local-delivery-configuration): New record.
* gnu/services/mail.scm (opensmtpd-maildir-configuration): New record.
* gnu/services/mail.scm (opensmtpd-mda-configuration): New record.
* gnu/services/mail.scm (opensmtpd-action-relay-configuration): New record.
* gnu/services/mail.scm (opensmtpd-option-configuration): New record.
* gnu/services/mail.scm (opensmtpd-filter-phase-configuration): New record.
* gnu/services/mail.scm (opensmtpd-filter-configuration): New record.
* gnu/services/mail.scm (opensmtpd-listen-on-configuration): New record.
* gnu/services/mail.scm (opensmtpd-listen-on-socket-configuration): New record.
* gnu/services/mail.scm (opensmtpd-match-configuration): New record.
* gnu/services/mail.scm (opensmtpd-smtp-configuration): New record.
* gnu/services/mail.scm (opensmtpd-srs-configuration): New record.
* gnu/services/mail.scm (opensmtpd-queue-configuration): New record.
* gnu/services/mail.scm (opensmtpd-configuration): New record.
---
gnu/services/mail.scm | 2016 ++++++++++++++++++++++++++++++++++++++++-
1 file changed, 2013 insertions(+), 3 deletions(-)

Toggle diff (369 lines)
diff --git a/gnu/services/mail.scm b/gnu/services/mail.scm
index d99743ac31..bdc0ee3bf7 100644
--- a/gnu/services/mail.scm
+++ b/gnu/services/mail.scm
@@ -57,8 +57,143 @@ (define-module (gnu services mail)
mailbox-configuration
namespace-configuration
+ opensmtpd-table-configuration
+ opensmtpd-table-configuration?
+ opensmtpd-table-configuration-name
+ opensmtpd-table-configuration-file-db
+ opensmtpd-table-configuration-data
+
+ opensmtpd-ca-configuration
+ opensmtpd-ca-configuration?
+ opensmtpd-ca-configuration-name
+ opensmtpd-ca-configuration-file
+
+ opensmtpd-pki-configuration
+ opensmtpd-pki-configuration?
+ opensmtpd-pki-configuration-domain
+ opensmtpd-pki-configuration-cert
+ opensmtpd-pki-configuration-key
+ opensmtpd-pki-configuration-dhe
+
+ opensmtpd-action-local-delivery-configuration
+ opensmtpd-action-local-delivery-configuration?
+ opensmtpd-action-local-delivery-configuration-method
+ opensmtpd-action-local-delivery-configuration-alias
+ opensmtpd-action-local-delivery-configuration-ttl
+ opensmtpd-action-local-delivery-configuration-user
+ opensmtpd-action-local-delivery-configuration-userbase
+ opensmtpd-action-local-delivery-configuration-virtual
+ opensmtpd-action-local-delivery-configuration-wrapper
+
+ opensmtpd-maildir-configuration
+ opensmtpd-maildir-configuration?
+ opensmtpd-maildir-configuration-pathname
+ opensmtpd-maildir-configuration-junk
+
+ opensmtpd-mda-configuration
+ opensmtpd-mda-configuration-name
+ opensmtpd-mda-configuration-command
+
+ opensmtpd-action-relay-configuration
+ opensmtpd-action-relay-configuration?
+ opensmtpd-action-relay-configuration-backup
+ opensmtpd-action-relay-configuration-backup-mx
+ opensmtpd-action-relay-configuration-helo
+ opensmtpd-action-relay-configuration-domain
+ opensmtpd-action-relay-configuration-host
+ opensmtpd-action-relay-configuration-pki
+ opensmtpd-action-relay-configuration-srs
+ opensmtpd-action-relay-configuration-tls
+ opensmtpd-action-relay-configuration-auth
+ opensmtpd-action-relay-configuration-mail-from
+ opensmtpd-action-relay-configuration-src
+
+ opensmtpd-option-configuration
+ opensmtpd-option-configuration?
+ opensmtpd-option-configuration-option
+ opensmtpd-option-configuration-not
+ opensmtpd-option-configuration-regex
+ opensmtpd-option-configuration-data
+
+ opensmtpd-filter-phase-configuration
+ opensmtpd-filter-phase-configuration?
+ opensmtpd-filter-phase-configuration-name
+ opensmtpd-filter-phase-configuration-phase-name
+ opensmtpd-filter-phase-configuration-options
+ opensmtpd-filter-phase-configuration-decision
+ opensmtpd-filter-phase-configuration-message
+ opensmtpd-filter-phase-configuration-value
+
+ opensmtpd-filter-configuration
+ opensmtpd-filter-configuration?
+ opensmtpd-filter-configuration-name
+ opensmtpd-filter-configuration-proc
+
+ opensmtpd-listen-on-configuration
+ opensmtpd-listen-on-configuration?
+ opensmtpd-listen-on-configuration-interface
+ opensmtpd-listen-on-configuration-family
+ opensmtpd-listen-on-configuration-auth
+ opensmtpd-listen-on-configuration-auth-optional
+ opensmtpd-listen-on-configuration-filters
+ opensmtpd-listen-on-configuration-hostname
+ opensmtpd-listen-on-configuration-hostnames
+ opensmtpd-listen-on-configuration-mask-src
+ opensmtpd-listen-on-configuration-disable-dsn
+ opensmtpd-listen-on-configuration-pki
+ opensmtpd-listen-on-configuration-port
+ opensmtpd-listen-on-configuration-proxy-v2
+ opensmtpd-listen-on-configuration-received-auth
+ opensmtpd-listen-on-configuration-senders
+ opensmtpd-listen-on-configuration-secure-connection
+ opensmtpd-listen-on-configuration-tag
+
+ opensmtpd-listen-on-socket-configuration
+ opensmtpd-listen-on-socket-configuration?
+ opensmtpd-listen-on-socket-configuration-filters
+ opensmtpd-listen-on-socket-configuration-mask-src
+ opensmtpd-listen-on-socket-configuration-tag
+
+ opensmtpd-match-configuration
+ opensmtpd-match-configuration?
+ opensmtpd-match-configuration-action
+ opensmtpd-match-configuration-options
+
+ opensmtpd-smtp-configuration
+ opensmtpd-smtp-configuration?
+ opensmtpd-smtp-configuration-ciphers
+ opensmtpd-smtp-configuration-limit-max-mails
+ opensmtpd-smtp-configuration-limit-max-rcpt
+ opensmtpd-smtp-configuration-max-message-size
+ opensmtpd-smtp-configuration-sub-addr-delim character
+
+ opensmtpd-srs-configuration
+ opensmtpd-srs-configuration?
+ opensmtpd-srs-configuration-key
+ opensmtpd-srs-configuration-backup-key
+ opensmtpd-srs-configuration-ttl-delay
+
+ opensmtpd-queue-configuration
+ opensmtpd-queue-configuration?
+ opensmtpd-queue-configuration-compression
+ opensmtpd-queue-configuration-encryption
+ opensmtpd-queue-configuration-ttl-delay
+
opensmtpd-configuration
opensmtpd-configuration?
+ opensmtpd-package
+ opensmtpd-config-file
+ opensmtpd-configuration-bounce
+ opensmtpd-configuration-listen-ons
+ opensmtpd-configuration-listen-on-socket
+ opensmtpd-configuration-includes
+ opensmtpd-configuration-matches
+ opensmtpd-configuration-mda-wrappers
+ opensmtpd-configuration-mta-max-deferred
+ opensmtpd-configuration-srs
+ opensmtpd-configuration-smtp
+ opensmtpd-configuration-queue
+
opensmtpd-service-type
%default-opensmtpd-config-file
@@ -1651,13 +1786,1888 @@ (define (generate-dovecot-documentation)
;;; OpenSMTPD.
;;;
+;; some fieldnames have a default value of #f, which is ok. They cannot have a value of #t.
+;; for example opensmtpd-table-configuration-data can be #f, BUT NOT true.
+;; my/sanitize procedure tests values to see if they are of the right kind.
+;; procedure false? is needed to allow fields like 'values' to be blank, (empty), or #f BUT also
+;; have a value like a list of strings.
+(define (false? var)
+ (eq? #f var))
+
+;; this procedure takes in a var and a list of procedures. It loops through list of procedures passing in var to each.
+;; if one procedure returns #t, the function returns true. Otherwise #f.
+;; TODO for fun rewrite this using map
+;; If I rewrote it in map, then it may help with sanitizing.
+;; eg: I could then potentially easily sanitize vars with lambda procedures.
+(define (is-value-right-type? var list-of-procedures record fieldname)
+ (if (null? list-of-procedures)
+ #f
+ (cond [(procedure? (car list-of-procedures))
+ (if ((car list-of-procedures) var)
+ #t
+ (is-value-right-type? var (cdr list-of-procedures) record fieldname))]
+ [(and (sanitize-configuration? (car list-of-procedures))
+ (sanitize-configuration-error-if-proc-fails (car list-of-procedures))
+ (if ((sanitize-configuration-proc (car list-of-procedures)) var)
+ #t
+ (begin
+ (apply string-append
+ (sanitize-configuration-error-message (car list-of-procedures)))
+ (throw 'bad! var))))]
+ [else (if ((sanitize-configuration-proc (car list-of-procedures)) var)
+ #t
+ (is-value-right-type? var (cdr list-of-procedures) record fieldname))])))
+
+;; converts strings like this:
+;; "apple, ham, cherry" -> "apple, ham, or cherry"
+;; "pineapple" -> "pinneapple".
+;; "cheese, grapefruit, or jam" -> "cheese, grapefruit, or jam"
+(define (add-comma-or string)
+ (define last-comma-location (string-rindex string #\,))
+ (if last-comma-location
+ (if (string-contains string ", or" last-comma-location)
+ string
+ (string-replace string ", or" last-comma-location
+ (+ 1 last-comma-location)))
+ string))
+
+;; I could test for read-ability of a file, but then I would have to
+;; test the program as root everytime instead of as a normal user...
+(define (file-exists? file)
+(if (string? file)
+ (access? file F_OK)
+ #f))
+
+(define (list-of-procedures->string procedures)
+ (define string
+ (let loop ([procedures procedures])
+ (if (null? procedures)
+ ""
+ (begin
+ (string-append
+ (cond [(eq? false? (car procedures))
+ "#f , "]
+ [(eq? boolean? (car procedures))
+ "boolean, "]
+ [(eq? string? (car procedures))
+ "string, "]
+ [(eq? integer? (car procedures))
+ "integer, "]
+ [(eq? list-of-strings? (car procedures))
+ "list of strings, "]
+ [(eq? assoc-list? (car procedures))
+ "an association list, "]
+ [(eq? opensmtpd-pki-configuration? (car procedures))
+ "an <opensmtpd-pki-configuration> record, "]
+ [(eq? opensmtpd-table-configuration? (car procedures))
+ "an <opensmtpd-table-configuration> record, "]
+ [(eq? list-of-unique-opensmtpd-match-configuration? (car procedures))
+ "a list of unique <opensmtpd-match-configuration> records, "]
+ [(eq? table-whose-data-are-assoc-list? (car procedures))
+ (string-append
+ "an <opensmtpd-table-configuration> record whose fieldname 'values' are an assoc-list \n"
+ "(eg: (opensmtpd-table-configuration (name \"table\") (data '(\"joshua\" . \"$encrypted$password\")))), ")]
+ [(eq? file-exists? (car procedures))
+ "file, "]
+ [else "has an incorrect value, "])
+ (loop (cdr procedures)))))))
+ (add-comma-or (string-append (string-drop-right string 2) ".\n")))
+
+;; TODO can I M-x raise-sexp (string=? string var) in this procedure? and get rid of checking
+;; if the var is a string? The previous string-in-list? had that check.
+;; (string-in-list? '("hello" 5 "cat")) currently works. If I M-x raise-sexp (string=? string var)
+;; then it will no longer work.
+(define (string-in-list? string list)
+ (primitive-eval (cons 'or (map (lambda (var) (and (string? var) (string=? string var))) list))))
+
+(define (my/sanitize var record fieldname list-of-procedures)
+ (if (is-value-right-type? var list-of-procedures record fieldname)
+ var
+ (begin
+ (display (string-append "<" record "> fieldname: '" fieldname "' is of type "
+ (list-of-procedures->string list-of-procedures) "\n"))
+ (throw 'bad! var))))
+
+;; Some example opensmtpd-table-configurations:
+;;
+;; (opensmtpd-table-configuration (name "root accounts") (data '(("joshua" . "root@dismail.de") ("joshua" . "postmaster@dismail.de"))))
+;; (opensmtpd-table-configuration (name "root accounts") (data (list "mysite.me" "your-site.com")))
+;; TODO should <opensmtpd-table-configuration> support have a fieldname 'file'?
+;; Or should I change name to name-or-file ?
+(define-record-type* <opensmtpd-table-configuration>
+ opensmtpd-table-configuration make-opensmtpd-table-configuration
+ opensmtpd-table-configuration?
+ this-record
+ (name opensmtpd-table-configuration-name ;; string
+ (default #f)
+ (sanitize (lambda (var)
+ (my/sanitize var "opensmtpd-table-configuration" "name" (list string?)))))
+ (file-db opensmtpd-table-configuration-file-db
+ (default #f)
+ (sanitize (lambda (var)
+ (my/sanitize var "opensmtpd-table-configuration" "file-db"
+ (list boolean?)))))
+ ;; FIXME support an aliasing table as described here:
+ ;; https://man.openbsd.org/table.5
+ ;; One may have to use the record file for this. I don't think tables support a table like this:
+ ;; table "name" { joshua = joshua@gnucode.me,joshua@gnu-hurd.com,joshua@propernaming.org, root = root@gnucode.me }
+ ;; If values is an absolute filename, then it will use said filename to house the table info.
+ ;; filename must be an absolute filename.
+ (data opensmtpd-table-configuration-data
+ (default #f)
+ (sanitize (lambda (var)
+ (my/sanitize var "opensmtpd-table-configuration" "values"
+ (list file-exists? list-of-strings? assoc-list?)))))
+ ;; is a list of values or key values
+ ;; eg: (list "mysite.me" "your-site.com")
+ ;; eg: (list ("joshua" . "joshua@gnu.org") ("james" . "james@gnu.org"))
+ ;; I am currently making these values be as assocation list of strings only.
+ ;; FIXME should I allow a var like this?
+ ;; (list (cons "gnucode.me" 234.949.392.23))
+ ;; can be of type: (quote list-of-strings) or (quote assoc-list)
+ ;; (opensmtpd-table-configuration-type record) returns the values' type. The user SHOULD NEVER set the type.
+ ;; TODO jpoiret: on irc reccomends that I just use an outside function to determine fieldname 'values', type.
+ ;; it would be "simpler" and possibly easier for the next person working on this code to understand what is happening.
+ (type opensmtpd-table-configuration-type
+ (default #f)
+ (thunked)
+ (sanitize (lambda (var)
+ (cond [(opensmtpd-table-configuration-data this-record)
+ (if (list-of-strings? (opensmtpd-table-configuration-data this-record))
+ (quote list-of-strings)
+ (quote assoc-list))]
+ [(file-exists? (opensmtpd-table-configuration-data this-record))
+ (if (opensmtpd-table-configuration-file-db this-record)
+ (quote db)
+ (quote file))]
+ [else
+ (display "opensmtpd-table-configuration-type is broke\n")
+ (throw 'bad! var)])))))
+
+(define-record-type* <opensmtpd-ca-configuration>
+ opensmtpd-ca-configuration make-opensmtpd-ca-configuration
+ opensmtpd-ca-configuration?
+ (name opensmtpd-ca-configuration-name
+ (default #f)
+ (sanitize (lambda (var)
+ (my/sanitize var "opensmtpd-ca-configuration" "name" (list string?)))))
+ (file opensmtpd-ca-configuration-file
+ (default #f)
+ (sanitize (lambda (var)
+ (my/sanitize var "opensmtpd-ca-configuration" "file" (list file-exists?))))))
+
+(define-record-type* <opensmtpd-pki-configuration>
+ opensmtpd-pki-configuration make-opensmtpd-pki-configuration
+ opensmtpd-pki-configuration?
+ (domain opensmtpd-pki-configuration-domain
+ (default #f)
+ (sanitize (lambda (var)
+ (my/sanitize var "opensmtpd-pki-configuration" "domain" (list string?)))))
+ ;; TODO/FIXME this should probably be a list of files. The opensmtpd documentation says
+ ;; that you could have a list of files:
+ ;;
+ ;; pki pkiname cert certfile
+ ;; Associate certificate file certfile with host pkiname, and use that file to prove
+ ;; the identity of the mail server to clients. pkiname is the server's name, de?
+ ;; rived from the default hostname or set using either
+ ;; /gnu/store/2d13sdz76ldq8zgwv4wif0zx7hkr3mh2-opensmtpd-6.8.0p2/etc/mailname or us?
+ ;; ing the hostname directive. If a fallback certificate or SNI is wanted, the ‘*’
+ ;; wildcard may be used as pkiname.
+
+ ;; A certificate chain may be created by appending one or many certificates, includ?
+ ;; ing a Certificate Authority certificate, to certfile. The creation of certifi?
+ ;; cates is documented in starttls(8).
+ (cert opensmtpd-pki-configuration-cert
+ (default #f)
+ (sanitize (lambda (var)
+ (my/sanitize var "opensmtpd-pki-configuration" "cert" (list file-exists?)))))
+ (key opensmtpd-pki-configuration-key
+ (default #f)
+ (sanitize (lambda (var)
+ (my/sanitize var "opensmtpd-pki-configuration" "key" (list file-exists?)))))
+ ; todo sanitize this. valid parameters are "none", "legacy", or "auto".
+ (dhe opensmtpd-pki-configuration-dhe
+ (default #f)
+ (sanitize (lambda (var)
+ (my/sanitize var "opensmtpd-dhe" "dhe" (list false? string?))))))
+
+(define-record-type* <opensmtpd-lmtp-configuration>
+ opensmtpd-lmtp-configuration make-opensmtpd-lmtp-configuration
+ opensmtpd-lmtp-configuration?
+ (destination opensmtpd-lmtp-configuration-destination
+ (default #f)
+ (sanitize (lambda (var)
+ (my/sanitize var "opensmtpd-lmtp-configuration" "destination"
+ (list string?)))))
+ (rcpt-to opensmtpd-lmtp-configuration-rcpt-to
+ (default #f)
+ (sanitize (lambda (var)
+ (my/sanitize var "opensmtpd-lmt
This message was truncated. Download the full message here.
J
J
Joshua Branson wrote on 17 Jun 2022 23:54
[PATCH] gnu: services: opensmtpd-records-task-list.org: Some notes about how I thought about building this service. And some additional task lists, as well as the WIP documentation.
(address . 56046@debbugs.gnu.org)(name . Joshua Branson)(address . jbranso@dismail.de)
20220617215407.21290-1-jbranso@dismail.de
---
gnu/services/opensmtpd-records-task-list.org | 5122 ++++++++++++++++++
1 file changed, 5122 insertions(+)
create mode 100644 gnu/services/opensmtpd-records-task-list.org

Toggle diff (484 lines)
diff --git a/gnu/services/opensmtpd-records-task-list.org b/gnu/services/opensmtpd-records-task-list.org
new file mode 100644
index 0000000000..c138aab8fe
--- /dev/null
+++ b/gnu/services/opensmtpd-records-task-list.org
@@ -0,0 +1,5122 @@
+#+title: Opensmtpd Records Task List
+#+AUTHOR: Joshua Branson
+
+
+(service (@ (gnu services mail) opensmtpd-service-type)
+ ((@ (gnu services mail) opensmtpd-configuration)
+ (config-file …)))
+
+* tasks
+** PROJ I have decent data structures. now let's get some good code. [0/6]
+*** why are good data structures important?
+**** nckx's advice: use a simple 1-1 mapping
+"...as I think Guix services ought to faithfully wrap the native
+syntax whenever possible (implement alternative simple APIs on top of
+that — fine)."
+
+-nckx from irc on #guix
+
+**** To follow nckx's advice, one might create the =<opensmtpd-service>= like this:
+#+BEGIN_SRC scheme
+ (service opensmtpd-service
+ (opensmtpd-configuration
+ (includes ...)
+ (tables ...)
+ (pkis ...)
+ (filters ...)
+ (listen-on ...)
+ (actions ...)
+ (matches ...)))
+#+END_SRC
+
+Defining the service this way, makes it VERY easy from a development point of
+view. But it makes it possible for users to create simple mistakes when
+defining the service.
+
+For example, it is possible to define an nginx service that will successfully
+reconfigure the system. BUT after reboot nginx refuses to start. Why? Who knows.
+Guix won't tell you. Neither will the Shepherd. To fix this, the user has to go
+digging into the nginx logs, and he might not know where to find those. If
+possible, when the user specificies a =<opensmtpd-configuration>= that has
+obvious errors, then the guix services should make reconfigure fail and print a
+helpful error message.
+
+**** BUT it would be better if the service uses better datastructures.
+
+I should follow nckx's advice, and Linus' advice: good programmers use good
+datastructures. If you have good datastructures, then your code will almost
+write itself.
+
+It might make the service a little harder to develop, but end-users will find
+the service easier to use. This would eliminate common errors like misspellings
+and give appropriate error messages. Practically it would ensure each
+=<opensmtpd-match-configuration>= has a corresponding =<opensmtpd-action>=,
+creating a table name and then misspelling the table name later, and defining
+a table but never using it, etc.
+
+**** Example configuration
+
+#+BEGIN_SRC scheme
+(service opensmtpd-service-type
+ (let ([interface "lo"]
+ [creds-table (opensmtpd-table-configuration
+ (name "creds")
+ (data
+ (list
+ (cons "joshua"
+ "$6$Ec4m8FgKjT2F/03Y$k66ABdse9TzCX6qaALB3WBL9GC1rmAWJmaoSjFMpbhzat7DOpFqpnOwpbZ34wwsQYIK8RQlqwM1I/v6vsRq86."))))]
+ [receive-action (opensmtpd-action-local-delivery-configuration
+ (name "receive")
+ (method (opensmtpd-maildir-configuration
+ (pathname "/home/%{rcpt.user}/Maildir")
+ (junk #t)))
+ (virtual (opensmtpd-table-configuration
+ (name "virtual")
+ (data (list "josh" "jbranso@dismail.de")))))]
+ [filter-dkimsign (opensmtpd-filter-configuration
+ (name "dkimsign")
+ (exec #t)
+ (proc (string-append "/path/to/dkimsign -d gnucode.me -s 2021-09-22 -c relaxed/relaxed -k "
+ "/path/to/dkimsign-key user nobody group nobody")))]
+ [smtp.gnucode.me (opensmtpd-pki-configuration
+ (domain "smtp.gnucode.me")
+ (cert "opensmtpd.scm")
+ (key "opensmtpd.scm"))])
+ (opensmtpd-configuration
+ (mta-max-deferred 50)
+ (queue
+ (opensmtpd-queue-configuration
+ (compression #t)))
+ (smtp
+ (opensmtpd-smtp-configuration
+ (max-message-size "10M")))
+ (srs
+ (opensmtpd-srs-configuration
+ (ttl-delay "5d")))
+ (listen-ons
+ (list
+ (opensmtpd-listen-on-configuration
+ (interface interface)
+ (port 25)
+ (secure-connection "tls")
+ (filters (list (opensmtpd-filter-phase-configuration
+ (name "noFRDNS")
+ (phase "commit")
+ (options (list (opensmtpd-option-configuration
+ (option "fcrdns")
+ (not #t))))
+ (decision "disconnect")
+ (message "433 No FCRDNS"))))
+ (pki smtp.gnucode.me))
+ ;; this lets local users logged into the system via ssh send email
+ (opensmtpd-listen-on-configuration
+ (interface interface)
+ (port 465)
+ (secure-connection "smtps")
+ (pki smtp.gnucode.me)
+ (auth creds-table)
+ (filters (list filter-dkimsign)))
+ (opensmtpd-listen-on-configuration
+ (interface interface)
+ (port 587)
+ (secure-connection "tls-require")
+ (pki smtp.gnucode.me)
+ (auth creds-table)
+ (filters (list filter-dkimsign)))))
+ (matches (list
+ (opensmtpd-match-configuration
+ (action (opensmtpd-action-relay-configuration
+ (name "relay")))
+ (options (list (opensmtpd-option-configuration
+ (option "for any"))
+ (opensmtpd-option-configuration
+ (option "from any"))
+ (opensmtpd-option-configuration
+ (option "auth")))))
+ (opensmtpd-match-configuration
+ (action receive-action)
+ (options (list (opensmtpd-option-configuration
+ (option "from any"))
+ (opensmtpd-option-configuration
+ (option "for domain")
+ (data (opensmtpd-table-configuration
+ (name "domain-table")
+ (data (list "gnucode.me" "gnu-hurd.com"))))))))
+ (opensmtpd-match-configuration
+ (action receive-action)
+ (options (list (opensmtpd-option-configuration
+ (option "for local"))))))))))
+#+END_SRC
+
+:OldConfigurationSyntax:
+#+BEGIN_SRC scheme
+ (service opensmtpd-service-type
+ (opensmtpd-configuration
+ (pkis (list
+ (opensmtpd-pki-configuration
+ ...)))
+ (tables (list
+ (opensmtpd-table-configuration
+ ...)
+ (opensmtpd-table-configuration
+ ...)))
+ (listen-ons
+ (list
+ (opensmtpd-listen-on-configuration
+ ...)
+ (opensmtpd-listen-on-configuration
+ ...)))
+ (actions
+ (list
+ (opensmtpd-action
+ ...)
+ (opensmtpd-action
+ ...)))
+ (matches (list
+ (opensmtpd-match-configuration
+ ...)
+ (opensmtpd-match-configuration
+ ...)))
+ (filter-chains
+ (list
+ (opensmtpd-filter-chain
+ (name "dropDumbEmails")
+ (filter-names (list "nofcrdnsDisconnect"
+ "nordnsDisconnect")))))
+ (filter-phases
+ (list (opensmtpd-filter-phase-configuration
+ ...)
+ (opensmtpd-filter-phase-configuration
+ ...)))))
+#+END_SRC
+
+Here you have to define the =pki=s twice! You define it once in the =pkis=
+section, and then you reference it later. This could potentially cause a
+mispelling error. That would be silly to debug as an end-user.
+
+:END:
+
+*** PROJ tweek the code for =<opensmtpd-filter-configuration>= & =<opensmtpd-filter-phase-configuration>= records [4/7]
+**** Why I chose the current datastructures of =<opensmtpd-filter-configuration>= & =<opensmtpd-filter-phase-configuration>=
+
+According to the man page I have a four kinds of filters:
+
+#+BEGIN_EXAMPLE
+1. filter chain-name chain {filter-name [, ...]}
+ Register a chain of filters chain-name, consisting of the filters listed from filter-name.
+ Filters part of a filter chain are executed in order of declaration for each phase that
+ they are registered for. A filter chain may be used in place of a filter for any direc?
+ tive but filter chains themselves.
+2. filter filter-name phase phase-name match conditions decision
+ Register a filter filter-name. A decision about what to do with the mail is taken at
+ phase phase-name when matching conditions. Phases, matching conditions, and decisions are
+ described in MAIL FILTERING, below.
+3. filter filter-name proc proc-name
+ Register "proc" filter filter-name backed by the proc-name process.
+4. filter filter-name proc-exec command
+ Register and execute "proc" filter filter-name from command. If command starts with a
+ slash it is executed with an absolute path, else it will be run from
+ “/gnu/store/2d13sdz76ldq8zgwv4wif0zx7hkr3mh2-opensmtpd-6.8.0p2/libexec/opensmtpd”.
+#+END_EXAMPLE
+
+=chain-name= could be easily represented as a list of filters. in the
+opensmtpd-configuration-filter fieldname:
+
+#+BEGIN_SRC scheme
+(opensmtpd-configuration
+ (listen-on
+ (filter
+ (list (opensmtpd-filter-configuration)
+ (opensmtpd-filter-configuration)
+ (opensmtpd-filter-configuration)))))
+#+END_SRC
+
+For example, this is probably easier
+
+#+BEGIN_SRC scheme
+ (opensmtpd-configuration
+ (actions (list
+ (opensmtpd-action
+ (name "relay")
+ (method (opensmtpd-relay-configuration
+ (domain (opensmtpd-table-configuration
+ ;;(name "domains") ;; with some smart coding, the name would NOT be needed.
+ (data (list
+ "gnucode.me"
+ "gnu-hurd.com"))))))))))
+#+END_SRC
+
+than the alternative:
+
+#+BEGIN_SRC scheme
+ (opensmtpd-configuration
+ (tables (list
+ (opensmtpd-table-configuration
+ (name "domains")
+ (data (list
+ "gnucode.me"
+ "gnu-hurd.com")))))
+ (actions (list
+ (opensmtpd-action
+ (name "relay")
+ (method (opensmtpd-relay-configuration
+ (domain "domains")))))))
+#+END_SRC
+
+**** some example code for each of the 3 types of filters
+
+1. filter phase
+#+BEGIN_SRC scheme
+(opensmtpd-filter-phase-configuration
+ (name "phase")
+ (phase "connect")
+ (options
+ (list
+ (opensmtpd-option-configuration
+ (option "src")
+ (not #t)
+ (regex #t)
+ (table (opensmtpd-table-configuration (name "src-option-table")
+ (data (list "cat" "hot")))))))
+ (decision "reject")
+ (message "We do not want spam here!"))
+#+END_SRC
+
+#+RESULTS:
+
+2. filter proc
+this is a filter-proc
+#+BEGIN_SRC scheme
+(opensmtpd-filter
+ (name "proc")
+ (proc "dkimsign"))
+#+END_SRC
+
+3. filter proc-exec
+#+BEGIN_SRC scheme
+(opensmtpd-filter
+ (name "proc")
+ (exec #t)
+ (proc "dkimsign"))
+#+END_SRC
+
+***** Why am I doing the data structure like the above?
+
+filter-proc and proc-exec as defined in man smtpd.conf can both use the same
+<opensmtpd-filter-configuration> record. That works just fine.
+
+But filter-phase is a different beast. I do NOT want someone to accidentally
+define something like the following which is BAD data:
+
+#+BEGIN_SRC scheme
+(opensmtpd-filter
+ (name "proc")
+ (exec #t)
+ (proc "dkimsign"))
+
+#+END_SRC
+**** NO Is it advantageous/desireable to merge =<opensmtpd-filter-configuration>= & <opensmtpd-filter-phase-configuration>
+
+When a user creates a filter, he is either going to create a
+=<opensmtpd-filter-configuration>~ or an ~<opensmtpd-filter-phase>= NOT both. If
+we define separate records, then it is impossible for a user to accidentally
+define a filter record using fieldnames from both filter types. eg:
+
+#+BEGIN_SRC scheme
+(opensmtpd-filter-configuration
+ (name "filter")
+ (exec #t)
+ (proc "dkimsign")
+ (phase "connect")) ;; this phase should NOT be there. this is a <opensmtpd-filter-configuration>
+#+END_SRC
+
+If =<opensmtpd-filter-configuration>= & =<opensmtpd-filter-phase-configuration>= are separte then the above
+would correctly result in an error message for free.
+**** TODO make <opensmtpd-filter-configuration> fieldname 'proc' accept a list of strings and/or a <gexp>s
+
+Suppose you want to do dkimsigning in smtpd.conf. Here is how you might
+register the official opensmtpd dkimsign filter:
+
+#+BEGIN_EXAMPLE
+filter "dkimsign" proc-exec "filter-dkimsign -d <domain> -s <selector> \
+ -k /gnu/store/2d13sdz76ldq8zgwv4wif0zx7hkr3mh2-opensmtpd-6.8.0p2/etc/dkim/private.key" user _dkimsign group _dkimsign
+#+END_EXAMPLE
+
+For example my hacky code to do dkimsigning looks like:
+
+#+BEGIN_SRC scheme
+filter \"dkimsign\" \
+ proc-exec \"" path-to-filter-dkimsign " -d gnucode.me -s 2021-09-22 -c relaxed/relaxed -k " etc-dkimsign-key-file
+ " \" \
+ user nobody group nogroup
+
+#+END_SRC
+
+Here is some example code of how we could create an
+=<opensmtpd-filter-configuration>= that registers a dkimsign filter. The code
+below probably will NOT work.
+
+#+BEGIN_SRC scheme
+(let ((etc-dkimsign-key-file "filename.key")
+ (path-to-dkimsign-key "/etc/opensmtpd/")))
+(opensmtpd-filter-configuration
+ (name "dkimsign")
+ (proc (list
+ (file-append opensmtpd-filter-dkimsign "/libexec/opensmtpd/filter-dkimsign")
+ " -d gnucode.me -s 2021-09-22 -c relaxed/relaxed -k "
+ ~#(let ([UID-nobody (passwd:uid (getpw "nobody"))]
+ [GID-root (group:gid (getgr "root"))]
+ [GID-nogroup (group:gid (getgr "nogroup"))])
+ ;; #o550 user root can read/open the directory
+ ;; and the group "root" can read/open the directory.
+ ;; change these two lines to (mkdir-p) ?
+ (unless (file-exists? "/etc/opensmtpd")
+ (mkdir "/etc/opensmtpd" #o550))
+
+ ;; root can read/write/execute on directory dkimsign
+ ;; group "root" can read and execute
+ (unless (file-exists? "/etc/opensmtpd/dkimsign")
+ (mkdir "/etc/opensmtpd/dkimsign" #o750))
+
+ (copy-file path-to-dkimsign-key etc-dkimsign-key-file)
+ ;; make the etc-dkimsign-key-file to owned by nobody and group nogroup.
+ (chown "/etc/opensmtpd" UID-nobody GID-root)
+ (chown "/etc/opensmtpd/dkimsign" UID-nobody GID-root)
+ (chown etc-dkimsign-key-file UID-nobody GID-nogroup)
+ "/etc/opensmtpd/dkimsign/2021-09-22-rsa1024-gnucode.me.key")
+ "user nobody group nogroup"))
+ (exec #))
+#+END_SRC
+
+Here is the full for how I currently run opensmtpd:
+
+#+BEGIN_SRC sh :dir ~/prog/gnu/guix/guix-config/linode-guix-system-configuration/ :results raw
+cat opensmtpd.scm
+#+END_SRC
+
+#+RESULTS:
+#+BEGIN_SRC scheme
+(define-module (opensmtpd)
+ #:use-module (guix gexp)
+ #:use-module (guix records)
+ #:use-module (gnu packages mail) ;;for finding location of filter-dkimsign
+ #:export (
+ %smtpd.conf
+ ))
+
+
+;; to create credentials for now, I need to do the following:
+;; find /gnu/store -name '*encrypt*' | grep opensmtpd
+;; /gnu/store/blah/opensmtpd/encrypt
+(define creds
+ (plain-file "creds"
+ ;; this is my joshua's password for server. This can be found on dobby's /home/joshua/.authinfo/
+ "joshua $6$Ec4m8FgKjT2F/03Y$k66ABdse9TzCX6qaALB3WBL9GC1rmAWJmaoSjFMpbhzat7DOpFqpnOwpbZ34wwsQYIK8RQlqwM1I/v6vsRq86."))
+
+(define vdoms
+ (plain-file
+ "vdoms"
+ "gnucode.me
+gnu-hurd.com"))
+
+(define vusers
+ (plain-file
+ "vusers"
+ "joshua@gnucode.me joshua
+jbranso@gnucode.me joshua
+postmaster@gnucode.me joshua"))
+
+(define path-to-filter-dkimsign
+ (file-append opensmtpd-filter-dkimsign "/libexec/opensmtpd/filter-dkimsign"))
+
+(define path-to-dkimsign-key (string-append (getcwd) "/email-dkim-ssh-keys/2021-09-22-rsa1024-gnucode.me.key"))
+(define etc-dkimsign-key-file "/etc/opensmtpd/dkimsign/2021-09-22-rsa1024-gnucode.me.key")
+
+;; FIXME: This should become a derivation. Currently it just runs when I evaluate
+;; %smtpd.conf. For example it should look like this?
+;; (define build-exp
+;; #~(begin
+;; (mkdir #$output)
+;; (chdir #$output)
+;; (symlink (string-append #$coreutils "/bin/ls")
+;; "list-files")))
+
+;; I will need to extend the opensmtpd service, to create a directory
+;; in etc. This line needs to be added to etc-service.
+;; (service-extension etc-service-type opensmtpd-etc-service)
+;; I'll then need to create a opensmtpd-etc-service procedure. ganeti has
+;; a good example.
+
+;; It should also use the /etc service, which is a service for creating
+;; directories and files in /etc ?
+(define (create-etc-dkimsign-key-file)
+ #~(let ([UID-nobody (passwd:uid (getpw "nobody"))]
+ [GID-root (group:gid (getgr "root"))]
+ [GID-nogroup (group:gid (getgr "nogroup"))])
+ ;; #o550 user root can read/open the directory
+ ;; and the group "root" can read/open the directory.
+ ;; change these two lines to (mkdir-p) ?
+ (unless (file-exists? "/etc/opensmtpd")
+ (mkdir "/etc/opensmtpd" #o550))
+
+ ;; root can read/write/execute on directory dkimsign
+ ;; group "root" can read and execute
+ (unless (file-exists? "/etc/opensmtpd/dkimsign")
+ (mkdir "/etc/opensmtpd/dkimsign" #o750))
+
+ (copy-file path-to-dkimsign-key etc-dkimsign-key-file)
+ ;; ;; ;; make the etc-dkimsign-key-file to owned by nobody and group nogroup.
+ (chown "/etc/opensmtpd" UID-nobody GID-root)
+ (chown "/etc/opensmtpd/dkimsign" UID-nobody GID-root)
+ (chown etc-dkimsign-key-file UID-nobody GID-nogroup)
+ etc-dkimsign-key-file))
+
+(define %smtpd.conf
+ (mixed-text-file "smtpd.conf"
+ "
+# This is the smtpd server system-wide configuration file.
+# See smtpd.conf(5) for more inform
This message was truncated. Download the full message here.
J
J
Joshua Branson wrote on 4 Jul 2022 23:17
[PATCH] services: mail: add opensmtpd records to enhance opensmtpd-configuration. Version 2
(address . 56046@debbugs.gnu.org)(name . Joshua Branson)(address . jbranso@dismail.de)
20220704211759.8314-1-jbranso@dismail.de
Openmstpd-configuration may only be configured by a config-file. This
patch, enables one to configure opensmtpd by using some guile record
types (defined via define-record-type*).

* gnu/services/mail.scm: New records (opensmtpd-table-configuration),
(opensmtpd-ca-configuration),
(opensmtpd-pki-configuration),
(opensmtpd-action-local-delivery-configuration),
(opensmtpd-maildir-configuration),
(opensmtpd-mda-configuration),
(opensmtpd-action-relay-configuration),
(opensmtpd-option-configuration),
(opensmtpd-filter-phase-configuration),
(opensmtpd-filter-configuration),
(opensmtpd-listen-on-configuration),
(opensmtpd-listen-on-socket-configuration),
(opensmtpd-match-configuration),
(opensmtpd-smtp-configuration),
(opensmtpd-srs-configuration),
(opensmtpd-queue-configuration), and
(opensmtpd-configuration).

New procedures: false?, is-value-right-type, add-comma-or-string,
file-exists?, list-of-procedures->string, string-in-list?, my-sanitize,
opensmtpd-filter-chain?, throw-error-duplicate-option,
sanitize-list-of-options-for-match-configuration, sanitize-filters,
list-has-duplicates-or-non-filters?,
filter-phase-has-message-and-value?,
filter-phase-decision-lacks-proper-message?,
filter-phase-lacks-proper-value?,
filter-phase-has-incorrect-junk-or-bypass?,
filter-phase-junks-after-commit?,
list-of-unique-filter-or-filter-phase?, throw-error,
contains-duplicate?, list-of-type?, list-of-strings?,
list-of-unique-opensmtpd-option-configuration?,
list-of-opensmtpd-ca-configuration?,
list-of-opensmtpd-pki-configuration?,
list-of-opensmtpd-listen-on-configuration?,
list-of-unique-opensmtpd-match-configuration?, list-of-strings->string,
assoc-list? assoc-list, variable->string,
table-whose-data-are-assoc-list?,
table-whose-data-are-a-list-of-strings?, assoc-list->string,
opensmtpd-table-configuration->string,
opensmtpd-listen-on-configuration->string,
opensmtpd-listen-on-socket-configuration->string,
opensmtpd-action-relay-configuration->string,
opensmtpd-lmtp-configuration->string,
opensmtpd-mda-configuration->string,
opensmtpd-maildir-configuration->string,
opensmtpd-action-local-delivery-configuration->string,
opensmtpd-action->string, opensmtpd-option-configuration->string,
opensmtpd-match-configuration->string,
opensmtpd-ca-configuration->string, opensmtpd-pki-configuration->string,
generate-filter-chain-name, opensmtpd-filter-chain->string,
opensmtpd-filter-phase-configuration->string, opensmtpd-filters->string,
opensmtpd-configuration-listen->string,
opensmtpd-configuration-srs->string,
opensmtpd-smtp-configuration->string,
opensmtpd-configuration-queue->string, get-opensmtpd-actions,
get-opensmtpd-pki-configurations, get-opensmtpd-filters, flatten,
get-opensmtpd-tables, opensmtpd-configuration-fieldname->string,
list-of-records->string, opensmtpd-configuration->mixed-text-file.

* doc/guix.texi added documentation for the new records for opensmtpd.
---
doc/guix.texi | 1051 ++++++++++++++++++++-
gnu/services/mail.scm | 2016 ++++++++++++++++++++++++++++++++++++++++-
2 files changed, 3056 insertions(+), 11 deletions(-)

Toggle diff (484 lines)
diff --git a/doc/guix.texi b/doc/guix.texi
index eda0956260..e8564240d1 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -24849,14 +24849,59 @@ could instantiate a dovecot service like this:
@subsubheading OpenSMTPD Service
@deffn {Scheme Variable} opensmtpd-service-type
-This is the type of the @uref{https://www.opensmtpd.org, OpenSMTPD}
-service, whose value should be an @code{opensmtpd-configuration} object
-as in this example:
-
-@lisp
-(service opensmtpd-service-type
- (opensmtpd-configuration
- (config-file (local-file "./my-smtpd.conf"))))
+OpenSMTPD is an easy-to-use mail transfer agent (MTA). Its configuration file is
+throughly documented in @code{man 5 smtpd.conf}. OpenSMTPD @strong{listens} for incoming
+mail and @strong{matches} the mail to @strong{actions}. The following records represent those
+stages:
+
+@multitable {aaaaaaaaa} {aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}
+@item @strong{listens}
+@tab @code{<opensmtpd-listen-on-configuration}
+@item
+@tab @code{<opensmtpd-listen-on-socket-configuration>}
+@item
+@tab
+@item @strong{matches}
+@tab @code{<opensmtpd-match-configuration>}
+@item
+@tab
+@item @strong{actions}
+@tab @code{<opensmtpd-action-local-delivery-configuration>}
+@item
+@tab @code{<opensmtpd-action-relay-configuration>}
+@end multitable
+
+Additionally, each @code{<opensmtpd-listen-on-configuration>} and
+@code{<opensmtpd-listen-on-socket-configuration>} may use a list of
+@code{<opensmtpd-filter-configuration>}, and/or
+@code{<opensmtpd-filter-phase-configuration>} records to filter email/spam. Also
+numerous records' fieldnames use @code{<opensmtpd-table-configuration>} to hold lists
+or key value pairs of data.
+
+A simple example configuration is below:
+
+@lisp
+(let ((smtp.gnu.org (opensmtpd-pki-configuration
+ (domain "smtp.gnu.org")
+ (cert "file.cert")
+ (key "file.key"))))
+ (service opensmtpd-service-type
+ (opensmtpd-configuration
+ (listen-ons (list
+ (opensmtpd-listen-on-configuration
+ (pki smtp.gnu.org))
+ (opensmtpd-listen-on-configuration
+ (pki smtp.gnu.org)
+ (secure-connection "smtps"))))
+ (matches (list
+ (opensmtpd-match-configuration
+ (action
+ (opensmtpd-action-local-delivery-configuration
+ (name "local-delivery"))))
+ (opensmtpd-match-configuration
+ (action
+ (opensmtpd-action-relay-configuration
+ (name "relay")))))))))
@end lisp
@end deffn
@@ -24873,9 +24918,999 @@ it listens on the loopback network interface, and allows for mail from
users and daemons on the local machine, as well as permitting email to
remote servers. Run @command{man smtpd.conf} for more information.
+@item @code{bounce} (default: @code{(list "4h")})
+
+@code{bounce} is a list of strings, which send warning messages to the envelope
+sender when temporary delivery failures cause a message to remain in the
+queue for longer than string delay. Each string delay parameter consists
+of a string beginning with a positive decimal integer and a unit 's', 'm', 'h',
+or 'd'. At most four delay parameters can be specified.
+
+@item @code{listen-ons} (default: @code{(list (opensmtpd-listen-on-configuration))})
+
+@code{listen-ons} is a list of @code{<opensmtpd-listen-on-configuration>} records.
+This list details what interfaces and ports OpenSMTPD listens on as well as
+other information.
+
+@item @code{listen-on-socket} (default: @code{(opensmtpd-listen-on-socket-configuration-configuration)})
+
+Listens for incoming connections on the Unix domain socket.
+
+@item @code{includes} (default: @code{#f})
+
+@code{includes} is a list of string filenames. Each filename's contents is
+additional configuration that is inserted into the top of the configuration
+file.
+
+@item @code{matches} default:
+
+@lisp
+ (list (opensmtpd-match-configuration
+ (action (opensmtpd-action-local-delivery-configuration
+ (name "local")
+ (method "mbox")))
+ (for (opensmtpd-option-configuration
+ (option "for local"))))
+ (opensmtpd-match-configuration
+ (action (opensmtpd-action-relay-configuration
+ (name "outbound")))
+ (from (opensmtpd-option-configuration
+ (option "from local")))
+ (for (opensmtpd-option-configuration
+ (option "for any")))))
+@end lisp
+
+@code{matches} is a list of @code{<opensmtpd-match-configuration>} records, which
+matches incoming mail and sends it to a correspending action. The match
+records are evaluated sequentially, with the first match winning. If an
+incoming mail does not match any match records, then it is rejected.
+@c put this backin? @end itemize
+
+@c put this back in? @itemize
+@item @code{mta-max-deferred} (default: @code{100})
+
+When delivery to a given host is suspended due to temporary failures, cache
+at most number envelopes for that host such that they can be delivered as
+soon as another delivery succeeds to that host. The default is 100.
+
+@item @code{queue} (default: @code{#f})
+
+@code{queue} expects an @code{<opensmtpd-queue-configuration>} record. With it, one may
+compress and encrypt queue-ed emails as well as set the default expiration
+time for temporarily undeliverable messages.
+
+@item @code{smtp} (default: @code{#f})
+
+@code{smtp} expects an @code{<opensmtpd-smtp-configuration>} record, which lets one
+specifiy how large email may be along with other settings.
+
+@item @code{srs} (default: @code{#f})
+
+@code{srs} expects an @code{<opensmtpd-srs-configuration>} record, which lets one set
+up SRS, the Sender Rewritting Scheme.
@end table
@end deftp
+@itemize
+@item
+Data Type: opensmtpd-listen-on-configuration
+
+Data type representing the configuration of an
+@code{<opensmtpd-listen-on-configuration>}. Listen on the fieldname @code{interface} for
+incoming connections, using the same syntax as for ifconfig(8). The interface
+parameter may also be an string interface group, an string IP address, or a
+string domain name. Listening can optionally be restricted to a specific
+address fieldname @code{family}, which can be either ``inet4'' or ``inet6''.
+
+@itemize
+@item @code{interface} (default: ``lo'')
+
+The string interface to listen for incoming connections. These interface can
+usually be found by the command @code{ip link}.
+
+@item @code{family} (default: @code{#f})
+
+The string IP family to use. Valid strings are ``inet4'' or ``inet6''.
+
+@item @code{auth} (default: @code{#f})
+
+Support SMTPAUTH: clients may only start SMTP transactions after successful
+authentication. If @code{auth} is @code{#t}, then users are authenticated against
+their own normal login credentials. Alternatively @code{auth} may be an
+@code{<opensmtpd-table-configuration>} whose users are authenticated against
+their passwords.
+
+@item @code{auth-optional} (default: @code{#f})
+
+Support SMTPAUTH optionally: clients need not authenticate, but may do so.
+This allows the @code{<opensmtpd-listen-on-configuration>} to both accept
+incoming mail from untrusted senders and permit outgoing mail from
+authenticated users (using @code{<opensmtpd-match-configuration>} fieldname
+@code{auth}). It can be used in situations where it is not possible to listen on
+a separate port (usually the submission port, 587) for users to
+authenticate.
+
+@item @code{filters} (default: @code{#f})
+
+A list of one or many @code{<opensmtpd-filter-configuration>} or
+@code{<opensmtpd-filter-phase-configuration>} records. The filters are applied
+sequentially. These records listen and filter on connections handled by this
+listener.
+
+@item @code{hostname} (default: @code{#f})
+
+Use string ``hostname'' in the greeting banner instead of the default server
+name.
+
+@item @code{hostnames} (default: @code{#f})
+
+Override the server name for specific addresses. Use a
+@code{<opensmtpd-table-configuration>} containing a mapping of string IP
+addresses to hostnames. If the address on which the connection arrives
+appears in the mapping, the associated hostname is used.
+
+@item @code{mask-src} (default: @code{#f})
+
+If @code{#t}, then omit the from part when prepending “Received” headers.
+
+@item @code{disable-dsn} (default: @code{#f})
+
+When @code{#t}, then disable the DSN (Delivery Status Notification) extension.
+
+@item @code{pki} (default: @code{#f})
+
+For secure connections, use an @code{<opensmtpd-pki-configuration>}
+to prove a mail server's identity.
+
+@item @code{port} (default: @code{#f})
+
+Listen on the integer port instead of the default port of 25.
+
+@item @code{proxy-v2} (default: @code{#f})
+
+If @code{#t}, then support the PROXYv2 protocol, rewriting appropriately source
+address received from proxy.
+
+@item @code{received-auth} (default: @code{#f})
+
+If @code{#t}, then in “Received” headers, report whether the session was
+authenticated and by which local user.
+
+@item @code{senders} (default: @code{#f})
+
+Look up the authenticated user in the supplied
+@code{<opensmtpd-table-configuration>} to find the email addresses that user is
+allowed to submit mail as.
+
+@item @code{secure-connection} (default: @code{#f})
+
+This is a string of one of these options:
+
+@multitable {aaaaaaaaaaaaaaaaaaaa} {aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}
+@item ``smtps''
+@tab Support SMTPS, by default on port 465.
+@item ``tls''
+@tab Support STARTTLS, by default on port 25.
+@item ``tls-require-verify''
+@tab Like tls, but force clients to establish
+@item
+@tab a secure connection before being allowed to
+@item
+@tab start an SMTP transaction. With the verify
+@item
+@tab option, clients must also provide a valid
+@item
+@tab certificate to establish an SMTP session.
+@end multitable
+
+@item @code{tag} (default: @code{#f})
+
+Clients connecting to the listener are tagged with the given string tag.
+@end itemize
+
+@item Data Type: opensmtpd-listen-on-socket-configuration
+
+Data type representing the configuration of an
+@code{<opensmtpd-listen-on-socket-configuration>}. Listen for incoming SMTP
+connections on the Unix domain socket @samp{/var/run/smtpd.sock}. This is done by
+default, even if the directive is absent.
+
+@itemize
+@item @code{filters} (default: @code{#f})
+
+A list of one or many @code{<opensmtpd-filter-configuration>} or
+@code{<opensmtpd-filter-phase-configuration>} records. These filter incoming
+connections handled by this listener.
+
+@item @code{mask-src} (default: @code{#f})
+
+If @code{#t}, then omit the from part when prepending “Received” headers.
+
+@item @code{tag} (default: @code{#f})
+
+Clients connecting to the listener are tagged with the given string tag.
+@end itemize
+
+@item Data Type: opensmtpd-match-configuration
+
+This data type represents the configuration of an
+@code{<opensmtpd-match-configuration>} record.
+
+If at least one mail envelope matches the options of one match record, receive
+the incoming message, put a copy into each matching envelope, and atomically
+save the envelopes to the mail spool for later processing by the respective
+@code{<opensmtpd-action-configuration>} found in fieldname @code{action}.
+
+@itemize
+@item @code{action} (default: @code{#f})
+
+If mail matches this match configuration, then do this action. Valid values
+include @code{<opensmtpd-action-local-delivery-configuration>} or
+@code{<opensmtpd-action-relay-configuration>}.
+
+@item @code{options} (default: @code{#f}) @code{<opensmtpd-option-configuration>}
+The fieldname 'option' is a list of unique
+@code{<opensmtpd-option-configuration>} records.
+
+Each @code{<opensmtpd-option-configuration>} record's fieldname 'option' has some
+mutually exclusive options: there can be only one ``for'' and only one ``from'' option.
+
+@multitable {aaaaaaaaaaaaaaaaaaaaaaaaa} {aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}
+@headitem for
+@tab from
+@item only use one of the following:
+@tab only use one of the following:
+@item ``for any''
+@tab ``from any''
+@item ``for local''
+@tab ``from auth''
+@item ``for domain''
+@tab ``from local''
+@item ``for rcpt-to''
+@tab ``from mail-from''
+@item
+@tab ``from socket''
+@item
+@tab ``from src''
+@end multitable
+
+The following matching options are supported and can all be negated (via not
+#t). The options that support a table (anything surrounded with '<' and '>'
+eg: <table>), also support specifying regex via (regex #t).
+
+@itemize
+@item @samp{for any}
+
+Specify that session may address any destination.
+
+@item @samp{for local}
+
+Specify that session may address any local domain. This is the default,
+and may be omitted.
+
+@item @samp{for domain _domain_ | <domain>}
+
+Specify that session may address the string or list table domain.
+
+@item @samp{for rcpt-to _recipient_ | <recipient>}
+
+Specify that session may address the string or list table recipient.
+
+@item @samp{from any}
+
+Specify that session may originate from any source.
+
+@item @samp{from auth}
+
+Specify that session may originate from any authenticated user, no matter
+the source IP address.
+
+@item @samp{from auth _user_ | <user>}
+
+Specify that session may originate from authenticated user or user list
+user, no matter the source IP address.
+
+@item @samp{from local}
+
+Specify that session may only originate from a local IP address, or from
+the local enqueuer. This is the default, and may be omitted.
+
+@item @samp{from mail-from _sender_ | <sender>}
+
+Specify that session may originate from sender or table sender, no
+matter the source IP address.
+
+@item @samp{from rdns}
+
+Specify that session may only originate from an IP address that resolves
+to a reverse DNS@.
+
+@item @samp{from rdns _hostname_ | <hostname>}
+
+Specify that session may only originate from an IP address that resolves
+to a reverse DNS matching string or list string hostname.
+
+@item @samp{from socket}
+
+Specify that session may only originate from the local enqueuer.
+
+@item @samp{from src _address_ | <address>}
+
+Specify that session may only originate from string or list table address
+which can be a specific address or a subnet expressed in CIDR-notation.
+
+@item @samp{auth}
+
+Matches transactions which have been authenticated.
+
+@item @samp{auth _username_ | <username>}
+
+Matches transactions which have been authenticated for user or user list
+username.
+
+@item @samp{helo _helo-name_ | <helo-name>}
+
+Specify that session's HELO / EHLO should match the string or list table
+helo-name.
+
+@item @samp{mail-from _sender_ | <sender>}
+
+Specify that transactions's MAIL FROM should match the string or list
+table sender.
+
+@item @samp{rcpt-to _recipient_ | <recipient>}
+
+Specify that transaction's RCPT TO should match the string or list table
+recipient.
+
+@item @samp{tag tag}
+Matches transactions tagged with the given tag.
+
+@item @samp{tls}
+Specify that transaction should take place in a TLS channel.
+@end itemize
+
+Here is a simple example:
+@lisp
+ (opensmtpd-option-configuration
+ (not #t)
+ (regex #f)
+ (option "for domain")
+ (data (opensmtpd-table-configuration
+ (name "domain-table")
+ (data (list "gnu.org" "dismail.de")))))
+@end lisp
+
+The mail must NOT come from the domains @samp{gnu.org} or @samp{dismail.de}.
+
+@item Data Type: opensmtpd-option-configuration
+@end itemize
+
+@item Data Type: opensmtpd-action-local-delivery-configuration
+
+This data type represents the configuration of an
+@code{<opensmtpd-action-local-delivery-configuration>} record.
+
+@itemize
+@item
+@code{name} (default: @code{#f})
+
+@code{name} is the string name of the relay action.
+
+@item @code{method} (default: @code{"mbox"})
+
+The email delivery option. Valid options are:
+
+@itemize
+@item @code{"mbox"}
+
+Deliver the message to the user's mbox with mail.local(8).
+
+@item @code{"expand-only"}
+
+Only accept the message if a delivery method was specified in an aliases
+or .forward file.
+
+@item @code{"forward-only"}
+
+Only accept the message if the recipient results in a remote address after
+the processing of aliases or forward file.
+
+@item @code{<opensmtpd-lmtp-configuration>}
+
+Deliver the message to an LMTP server at
+@code{<opensmtpd-lmtp-configuration>}'s fieldname @code{destination}. The location
+may be expressed as string host:port or as a UNIX socket. Optionally,
+@code{<opensmtpd-lmtp-configuration>}'s fieldname @code{rcpt-to} might be specified
+to use the recipient email address (after expansion) instead of the local
+user in the LMTP session as RCPT TO@.
+
+@item @cod
This message was truncated. Download the full message here.
J
J
jbranso wrote on 5 Jul 2022 23:36
Re: [PATCH] services: mail: add opensmtpd records to enhance opensmtpd-configuration
(address . 56046@debbugs.gnu.org)
1bace22a7dbd8668b9a774b0f975fa53@dismail.de
Here is a video link that may help the first reviewer:

https://video.hardlimit.com/w/ixE7Tc1pCqpP3BgriRbYA5(https://video.hardlimit.com/w/ixE7Tc1pCqpP3BgriRbYA5)
The video walks you through how to play with an example configuration in emacs-geiser.

Thanks,

Joshua
Attachment: file
L
L
Liliana Marie Prikler wrote on 6 Jul 2022 06:27
Re: [PATCH] services: mail: add opensmtpd records to enhance opensmtpd-configuration. Version 2
756a905107d7783bab238091d668fddbc1e712ab.camel@gmail.com
Am Montag, dem 04.07.2022 um 17:17 -0400 schrieb Joshua Branson:
Toggle quote (23 lines)
> Openmstpd-configuration may only be configured by a config-file. 
> This
> patch, enables one to configure opensmtpd by using some guile record
> types (defined via define-record-type*).
>
> * gnu/services/mail.scm:  New records (opensmtpd-table-
> configuration),
> (opensmtpd-ca-configuration),
> (opensmtpd-pki-configuration),
> (opensmtpd-action-local-delivery-configuration),
> (opensmtpd-maildir-configuration),
> (opensmtpd-mda-configuration),
> (opensmtpd-action-relay-configuration),
> (opensmtpd-option-configuration),
> (opensmtpd-filter-phase-configuration),
> (opensmtpd-filter-configuration),
> (opensmtpd-listen-on-configuration),
> (opensmtpd-listen-on-socket-configuration),
> (opensmtpd-match-configuration),
> (opensmtpd-smtp-configuration),
> (opensmtpd-srs-configuration),
> (opensmtpd-queue-configuration), and
> (opensmtpd-configuration).
Not a ChangeLog.
Toggle quote (44 lines)
> New procedures: false?, is-value-right-type, add-comma-or-string,
> file-exists?, list-of-procedures->string, string-in-list?, my-
> sanitize,
> opensmtpd-filter-chain?, throw-error-duplicate-option,
> sanitize-list-of-options-for-match-configuration, sanitize-filters,
> list-has-duplicates-or-non-filters?,
> filter-phase-has-message-and-value?,
> filter-phase-decision-lacks-proper-message?,
> filter-phase-lacks-proper-value?,
> filter-phase-has-incorrect-junk-or-bypass?,
> filter-phase-junks-after-commit?,
> list-of-unique-filter-or-filter-phase?, throw-error,
> contains-duplicate?, list-of-type?, list-of-strings?,
> list-of-unique-opensmtpd-option-configuration?,
> list-of-opensmtpd-ca-configuration?,
> list-of-opensmtpd-pki-configuration?,
> list-of-opensmtpd-listen-on-configuration?,
> list-of-unique-opensmtpd-match-configuration?, list-of-strings-
> >string,
> assoc-list? assoc-list, variable->string,
> table-whose-data-are-assoc-list?,
> table-whose-data-are-a-list-of-strings?, assoc-list->string,
> opensmtpd-table-configuration->string,
> opensmtpd-listen-on-configuration->string,
> opensmtpd-listen-on-socket-configuration->string,
> opensmtpd-action-relay-configuration->string,
> opensmtpd-lmtp-configuration->string,
> opensmtpd-mda-configuration->string,
> opensmtpd-maildir-configuration->string,
> opensmtpd-action-local-delivery-configuration->string,
> opensmtpd-action->string, opensmtpd-option-configuration->string,
> opensmtpd-match-configuration->string,
> opensmtpd-ca-configuration->string, opensmtpd-pki-configuration-
> >string,
> generate-filter-chain-name, opensmtpd-filter-chain->string,
> opensmtpd-filter-phase-configuration->string, opensmtpd-filters-
> >string,
> opensmtpd-configuration-listen->string,
> opensmtpd-configuration-srs->string,
> opensmtpd-smtp-configuration->string,
> opensmtpd-configuration-queue->string, get-opensmtpd-actions,
> get-opensmtpd-pki-configurations, get-opensmtpd-filters, flatten,
> get-opensmtpd-tables, opensmtpd-configuration-fieldname->string,
> list-of-records->string, opensmtpd-configuration->mixed-text-file.
Neither is this.
Toggle quote (2 lines)
> * doc/guix.texi added documentation for the new records for
> opensmtpd.
Or this.
Toggle quote (34 lines)
> ---
>  doc/guix.texi         | 1051 ++++++++++++++++++++-
>  gnu/services/mail.scm | 2016
> ++++++++++++++++++++++++++++++++++++++++-
>  2 files changed, 3056 insertions(+), 11 deletions(-)
>
> diff --git a/doc/guix.texi b/doc/guix.texi
> index eda0956260..e8564240d1 100644
> --- a/doc/guix.texi
> +++ b/doc/guix.texi
> @@ -24849,14 +24849,59 @@ could instantiate a dovecot service like
> this:
>  @subsubheading OpenSMTPD Service
>  
>  @deffn {Scheme Variable} opensmtpd-service-type
> -This is the type of the @uref{https://www.opensmtpd.org, OpenSMTPD}
> -service, whose value should be an @code{opensmtpd-configuration}
> object
> -as in this example:
> -
> -@lisp
> -(service opensmtpd-service-type
> -         (opensmtpd-configuration
> -           (config-file (local-file "./my-smtpd.conf"))))
> +OpenSMTPD is an easy-to-use mail transfer agent (MTA). Its
> configuration file is
> +throughly documented in @code{man 5 smtpd.conf}. OpenSMTPD
> @strong{listens} for incoming
> +mail and @strong{matches} the mail to @strong{actions}. The
> following records represent those
> +stages:
> +
> +@multitable {aaaaaaaaa}
> {aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}
I suggest using fractions here.
Toggle quote (5 lines)
> [...]
> +This is a string of one of these options:
> +
> +@multitable {aaaaaaaaaaaaaaaaaaaa}
> {aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}
Same here. Btw. I did not actually check all the doc in between, so I
might be missing something.
Toggle quote (2 lines)
> +@multitable {aaaaaaaaaaaaaaaaaaaaaaaaa}
> {aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}
Likewise.
Toggle quote (2 lines)
> +@multitable {aaaaaaaaaa}
> {aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}
You get the drill.

Toggle quote (164 lines)
> [more doc with strange multitables]
> diff --git a/gnu/services/mail.scm b/gnu/services/mail.scm
> index d99743ac31..2a344e303e 100644
> --- a/gnu/services/mail.scm
> +++ b/gnu/services/mail.scm
> @@ -57,8 +57,143 @@ (define-module (gnu services mail)
>              mailbox-configuration
>              namespace-configuration
>  
> +            opensmtpd-table-configuration
> +            opensmtpd-table-configuration?
> +            opensmtpd-table-configuration-name
> +            opensmtpd-table-configuration-file-db
> +            opensmtpd-table-configuration-data
> +
> +            opensmtpd-ca-configuration
> +            opensmtpd-ca-configuration?
> +            opensmtpd-ca-configuration-name
> +            opensmtpd-ca-configuration-file
> +
> +            opensmtpd-pki-configuration
> +            opensmtpd-pki-configuration?
> +            opensmtpd-pki-configuration-domain
> +            opensmtpd-pki-configuration-cert
> +            opensmtpd-pki-configuration-key
> +            opensmtpd-pki-configuration-dhe
> +
> +            opensmtpd-action-local-delivery-configuration
> +            opensmtpd-action-local-delivery-configuration?
> +            opensmtpd-action-local-delivery-configuration-method
> +            opensmtpd-action-local-delivery-configuration-alias
> +            opensmtpd-action-local-delivery-configuration-ttl
> +            opensmtpd-action-local-delivery-configuration-user
> +            opensmtpd-action-local-delivery-configuration-userbase
> +            opensmtpd-action-local-delivery-configuration-virtual
> +            opensmtpd-action-local-delivery-configuration-wrapper
> +
> +            opensmtpd-maildir-configuration
> +            opensmtpd-maildir-configuration?
> +            opensmtpd-maildir-configuration-pathname
> +            opensmtpd-maildir-configuration-junk
> +
> +            opensmtpd-mda-configuration
> +            opensmtpd-mda-configuration-name
> +            opensmtpd-mda-configuration-command
> +
> +            opensmtpd-action-relay-configuration
> +            opensmtpd-action-relay-configuration?
> +            opensmtpd-action-relay-configuration-backup
> +            opensmtpd-action-relay-configuration-backup-mx
> +            opensmtpd-action-relay-configuration-helo
> +            opensmtpd-action-relay-configuration-domain
> +            opensmtpd-action-relay-configuration-host
> +            opensmtpd-action-relay-configuration-pki
> +            opensmtpd-action-relay-configuration-srs
> +            opensmtpd-action-relay-configuration-tls
> +            opensmtpd-action-relay-configuration-auth
> +            opensmtpd-action-relay-configuration-mail-from
> +            opensmtpd-action-relay-configuration-src
> +
> +            opensmtpd-option-configuration
> +            opensmtpd-option-configuration?
> +            opensmtpd-option-configuration-option
> +            opensmtpd-option-configuration-not
> +            opensmtpd-option-configuration-regex
> +            opensmtpd-option-configuration-data
> +
> +            opensmtpd-filter-phase-configuration
> +            opensmtpd-filter-phase-configuration?
> +            opensmtpd-filter-phase-configuration-name
> +            opensmtpd-filter-phase-configuration-phase-name
> +            opensmtpd-filter-phase-configuration-options
> +            opensmtpd-filter-phase-configuration-decision
> +            opensmtpd-filter-phase-configuration-message
> +            opensmtpd-filter-phase-configuration-value
> +
> +            opensmtpd-filter-configuration
> +            opensmtpd-filter-configuration?
> +            opensmtpd-filter-configuration-name
> +            opensmtpd-filter-configuration-proc
> +
> +            opensmtpd-listen-on-configuration
> +            opensmtpd-listen-on-configuration?
> +            opensmtpd-listen-on-configuration-interface
> +            opensmtpd-listen-on-configuration-family
> +            opensmtpd-listen-on-configuration-auth
> +            opensmtpd-listen-on-configuration-auth-optional
> +            opensmtpd-listen-on-configuration-filters
> +            opensmtpd-listen-on-configuration-hostname
> +            opensmtpd-listen-on-configuration-hostnames
> +            opensmtpd-listen-on-configuration-mask-src
> +            opensmtpd-listen-on-configuration-disable-dsn
> +            opensmtpd-listen-on-configuration-pki
> +            opensmtpd-listen-on-configuration-port
> +            opensmtpd-listen-on-configuration-proxy-v2
> +            opensmtpd-listen-on-configuration-received-auth
> +            opensmtpd-listen-on-configuration-senders
> +            opensmtpd-listen-on-configuration-secure-connection
> +            opensmtpd-listen-on-configuration-tag
> +
> +            opensmtpd-listen-on-socket-configuration
> +            opensmtpd-listen-on-socket-configuration?
> +            opensmtpd-listen-on-socket-configuration-filters
> +            opensmtpd-listen-on-socket-configuration-mask-src
> +            opensmtpd-listen-on-socket-configuration-tag
> +
> +            opensmtpd-match-configuration
> +            opensmtpd-match-configuration?
> +            opensmtpd-match-configuration-action
> +            opensmtpd-match-configuration-options
> +
> +            opensmtpd-smtp-configuration
> +            opensmtpd-smtp-configuration?
> +            opensmtpd-smtp-configuration-ciphers
> +            opensmtpd-smtp-configuration-limit-max-mails
> +            opensmtpd-smtp-configuration-limit-max-rcpt
> +            opensmtpd-smtp-configuration-max-message-size
> +            opensmtpd-smtp-configuration-sub-addr-delim character
> +
> +            opensmtpd-srs-configuration
> +            opensmtpd-srs-configuration?
> +            opensmtpd-srs-configuration-key
> +            opensmtpd-srs-configuration-backup-key
> +            opensmtpd-srs-configuration-ttl-delay
> +
> +            opensmtpd-queue-configuration
> +            opensmtpd-queue-configuration?
> +            opensmtpd-queue-configuration-compression
> +            opensmtpd-queue-configuration-encryption
> +            opensmtpd-queue-configuration-ttl-delay
> +
>              opensmtpd-configuration
>              opensmtpd-configuration?
> +            opensmtpd-package
> +            opensmtpd-config-file
> +            opensmtpd-configuration-bounce
> +            opensmtpd-configuration-listen-ons
> +            opensmtpd-configuration-listen-on-socket
> +            opensmtpd-configuration-includes
> +            opensmtpd-configuration-matches
> +            opensmtpd-configuration-mda-wrappers
> +            opensmtpd-configuration-mta-max-deferred
> +            opensmtpd-configuration-srs
> +            opensmtpd-configuration-smtp
> +            opensmtpd-configuration-queue
> +
>              opensmtpd-service-type
>              %default-opensmtpd-config-file
>  
> @@ -1651,13 +1786,1888 @@ (define (generate-dovecot-documentation)
>  ;;; OpenSMTPD.
>  ;;;
>  
> +;; some fieldnames have a default value of #f, which is ok.  They
> cannot have a value of #t.
> +;; for example opensmtpd-table-configuration-data can be #f, BUT NOT
> true.
> +;; my/sanitize procedure tests values to see if they are of the
> right kind.
> +;; procedure false? is needed to allow fields like 'values' to be
> blank, (empty), or #f BUT also
> +;; have a value like a list of strings.
> +(define (false? var)
> +  (eq? #f var))
I'm pretty sure it'd be fine to use not in lieu of false?, even at the
risk of matching nil.

Toggle quote (34 lines)
> +;; this procedure takes in a var and a list of procedures.  It loops
> through list of procedures passing in var to each.
> +;; if one procedure returns #t, the function returns true. 
> Otherwise #f.
> +;; TODO for fun rewrite this using map
> +;; If I rewrote it in map, then it may help with sanitizing.
> +;; eg: I could then potentially easily sanitize vars with lambda
> procedures.
> +(define (is-value-right-type? var list-of-procedures record
> fieldname)
> +  (if (null? list-of-procedures)
> +        #f
> +        (cond [(procedure? (car list-of-procedures))
> +               (if ((car list-of-procedures) var)
> +                   #t
> +                   (is-value-right-type? var (cdr list-of-
> procedures) record fieldname))]
> +              [(and (sanitize-configuration? (car list-of-
> procedures))
> +                    (sanitize-configuration-error-if-proc-fails (car
> list-of-procedures))
> +                    (if ((sanitize-configuration-proc (car list-of-
> procedures)) var)
> +                        #t
> +                        (begin
> +                          (apply string-append
> +                                 (sanitize-configuration-error-
> message (car list-of-procedures)))
> +                          (throw 'bad! var))))]
> +              [else (if ((sanitize-configuration-proc (car list-of-
> procedures)) var)
> +                        #t
> +                        (is-value-right-type? var (cdr list-of-
> procedures) record fieldname))])))
Don't we have field sanitizers already that make this obsolete?

Toggle quote (19 lines)
> +;; converts strings like this:
> +;; "apple, ham, cherry" -> "apple, ham, or cherry"
> +;; "pineapple" -> "pinneapple".
> +;; "cheese, grapefruit, or jam" -> "cheese, grapefruit, or jam"
> +(define (add-comma-or string)
> +  (define last-comma-location (string-rindex string #\,))
> +  (if last-comma-location
> +      (if (string-contains string ", or" last-comma-location)
> +          string
> +          (string-replace string ", or" last-comma-location
> +                          (+ 1 last-comma-location)))
> +      string))
> +
> +;; I could test for read-ability of a file, but then I would have to
> +;; test the program as root everytime instead of as a normal user...
> +(define (file-exists? file)
> +(if (string? file)
> +    (access? file F_OK)
> +    #f))
Is this not part of the Guile standard library?

Toggle quote (41 lines)
> +(define (list-of-procedures->string procedures)
> +  (define string
> +    (let loop ([procedures procedures])
> +      (if (null? procedures)
> +          ""
> +          (begin
> +            (string-append
> +             (cond [(eq? false? (car procedures))
> +                    "#f , "]
> +                   [(eq? boolean? (car procedures))
> +                    "boolean, "]
> +                   [(eq? string? (car procedures))
> +                    "string, "]
> +                   [(eq? integer? (car procedures))
> +                    "integer, "]
> +                   [(eq? list-of-strings? (car procedures))
> +                    "list of strings, "]
> +                   [(eq? assoc-list? (car procedures))
> +                    "an association list, "]
> +                   [(eq? opensmtpd-pki-configuration? (car
> procedures))
> +                    "an <opensmtpd-pki-configuration> record, "]
> +                   [(eq? opensmtpd-table-configuration? (car
> procedures))
> +                    "an <opensmtpd-table-configuration> record, "]
> +                   [(eq? list-of-unique-opensmtpd-match-
> configuration? (car procedures))
> +                    "a list of unique <opensmtpd-match-
> configuration> records, "]
> +                   [(eq? table-whose-data-are-assoc-list? (car
> procedures))
> +                    (string-append
> +                    "an <opensmtpd-table-configuration> record whose
> fieldname 'values' are an assoc-list \n"
> +                    "(eg: (opensmtpd-table-configuration (name
> \"table\") (data '(\"joshua\" . \"$encrypted$password\")))), ")]
> +                   [(eq? file-exists? (car procedures))
> +                    "file, "]
> +                   [else "has an incorrect value, "])
> +             (loop (cdr procedures)))))))
> +  (add-comma-or (string-append (string-drop-right string 2) ".\n")))
Using a table, map and string-join might be wiser. If this is the only
place add-comma-or is used, you can replace it by 
(string-append
(string-join (butlast strings) ",")
", or " (last strings))
where you only need to define butlast.

Toggle quote (10 lines)
> +;; TODO can I M-x raise-sexp (string=? string var) in this
> procedure? and get rid of checking
> +;; if the var is a string?  The previous string-in-list? had that
> check.
> +;; (string-in-list? '("hello" 5 "cat")) currently works.  If I M-x
> raise-sexp (string=? string var)
> +;; then it will no longer work.
> +(define (string-in-list? string list)
> +  (primitive-eval (cons 'or (map (lambda (var) (and (string? var)
> (string=? string var))) list))))
Ever heard of member?

Toggle quote (61 lines)
> +(define (my/sanitize var record fieldname list-of-procedures)
> +  (if (is-value-right-type? var list-of-procedures record fieldname)
> +      var
> +      (begin
> +        (display (string-append "<" record "> fieldname: '"
> fieldname "' is of type "
> +                                (list-of-procedures->string list-of-
> procedures) "\n"))
> +        (throw 'bad! var))))
> +
> +;; Some example opensmtpd-table-configurations:
> +;;
> +;;  (opensmtpd-table-configuration (name "root accounts") (data
> '(("joshua" . "root@dismail.de") ("joshua" .
> "postmaster@dismail.de"))))
> +;;  (opensmtpd-table-configuration (name "root accounts") (data
> (list "mysite.me" "your-site.com")))
> +;;  TODO should <opensmtpd-table-configuration> support have a
> fieldname 'file'?
> +;;  Or should I change name to name-or-file ?
> +(define-record-type* <opensmtpd-table-configuration>
> +  opensmtpd-table-configuration make-opensmtpd-table-configuration
> +  opensmtpd-table-configuration?
> +  this-record
> +  (name opensmtpd-table-configuration-name ;; string
> +        (default #f)
> +        (sanitize (lambda (var)
> +                    (my/sanitize var "opensmtpd-table-configuration"
> "name" (list string?)))))
> +  (file-db opensmtpd-table-configuration-file-db
> +           (default #f)
> +           (sanitize (lambda (var)
> +                       (my/sanitize var "opensmtpd-table-
> configuration" "file-db"
> +                                    (list boolean?)))))
> +  ;; FIXME support an aliasing table as described here:
> +  ;; https://man.openbsd.org/table.5
> +  ;; One may have to use the record file for this.  I don't think
> tables support a table like this:
> +  ;; table "name" { joshua =
> joshua@gnucode.me,joshua@gnu-hurd.com,joshua@propernaming.org, root =
> root@gnucode.me }
> +  ;; If values is an absolute filename, then it will use said
> filename to house the table info.
> +  ;; filename must be an absolute filename.
> +  (data opensmtpd-table-configuration-data
> +          (default #f)
> +          (sanitize (lambda (var)
> +                      (my/sanitize var "opensmtpd-table-
> configuration" "values"
> +                                   (list file-exists? list-of-
> strings? assoc-list?)))))
> +  ;; is a list of values or key values
> +  ;; eg: (list "mysite.me" "your-site.com")
> +  ;; eg: (list ("joshua" . "joshua@gnu.org") ("james" .
> "james@gnu.org"))
> +  ;; I am currently making these values be as assocation list of
> strings only.
> +  ;; FIXME should I allow a var like this?
> +  ;; (list (cons "gnucode.me" 234.949.392.23))
> +  ;; can be of type: (quote list-of-strings) or (
This message was truncated. Download the full message here.
J
J
jbranso wrote on 6 Jul 2022 23:51
6a272ff438ca4e2efc8e196c9160f857@dismail.de
July 6, 2022 12:27 AM, "Liliana Marie Prikler" <liliana.prikler@gmail.com> wrote:

Toggle quote (28 lines)
> Am Montag, dem 04.07.2022 um 17:17 -0400 schrieb Joshua Branson:
>
>> Openmstpd-configuration may only be configured by a config-file.
>> This
>> patch, enables one to configure opensmtpd by using some guile record
>> types (defined via define-record-type*).
>>
>> * gnu/services/mail.scm: New records (opensmtpd-table-
>> configuration),
>> (opensmtpd-ca-configuration),
>> (opensmtpd-pki-configuration),
>> (opensmtpd-action-local-delivery-configuration),
>> (opensmtpd-maildir-configuration),
>> (opensmtpd-mda-configuration),
>> (opensmtpd-action-relay-configuration),
>> (opensmtpd-option-configuration),
>> (opensmtpd-filter-phase-configuration),
>> (opensmtpd-filter-configuration),
>> (opensmtpd-listen-on-configuration),
>> (opensmtpd-listen-on-socket-configuration),
>> (opensmtpd-match-configuration),
>> (opensmtpd-smtp-configuration),
>> (opensmtpd-srs-configuration),
>> (opensmtpd-queue-configuration), and
>> (opensmtpd-configuration).
>
> Not a ChangeLog.

I'll actually go and learn how to do that thanks.

Toggle quote (89 lines)
>
>> New procedures: false?, is-value-right-type, add-comma-or-string,
>> file-exists?, list-of-procedures->string, string-in-list?, my-
>> sanitize,
>> opensmtpd-filter-chain?, throw-error-duplicate-option,
>> sanitize-list-of-options-for-match-configuration, sanitize-filters,
>> list-has-duplicates-or-non-filters?,
>> filter-phase-has-message-and-value?,
>> filter-phase-decision-lacks-proper-message?,
>> filter-phase-lacks-proper-value?,
>> filter-phase-has-incorrect-junk-or-bypass?,
>> filter-phase-junks-after-commit?,
>> list-of-unique-filter-or-filter-phase?, throw-error,
>> contains-duplicate?, list-of-type?, list-of-strings?,
>> list-of-unique-opensmtpd-option-configuration?,
>> list-of-opensmtpd-ca-configuration?,
>> list-of-opensmtpd-pki-configuration?,
>> list-of-opensmtpd-listen-on-configuration?,
>> list-of-unique-opensmtpd-match-configuration?, list-of-strings-
>> string,
>> assoc-list? assoc-list, variable->string,
>> table-whose-data-are-assoc-list?,
>> table-whose-data-are-a-list-of-strings?, assoc-list->string,
>> opensmtpd-table-configuration->string,
>> opensmtpd-listen-on-configuration->string,
>> opensmtpd-listen-on-socket-configuration->string,
>> opensmtpd-action-relay-configuration->string,
>> opensmtpd-lmtp-configuration->string,
>> opensmtpd-mda-configuration->string,
>> opensmtpd-maildir-configuration->string,
>> opensmtpd-action-local-delivery-configuration->string,
>> opensmtpd-action->string, opensmtpd-option-configuration->string,
>> opensmtpd-match-configuration->string,
>> opensmtpd-ca-configuration->string, opensmtpd-pki-configuration-
>> string,
>> generate-filter-chain-name, opensmtpd-filter-chain->string,
>> opensmtpd-filter-phase-configuration->string, opensmtpd-filters-
>> string,
>> opensmtpd-configuration-listen->string,
>> opensmtpd-configuration-srs->string,
>> opensmtpd-smtp-configuration->string,
>> opensmtpd-configuration-queue->string, get-opensmtpd-actions,
>> get-opensmtpd-pki-configurations, get-opensmtpd-filters, flatten,
>> get-opensmtpd-tables, opensmtpd-configuration-fieldname->string,
>> list-of-records->string, opensmtpd-configuration->mixed-text-file.
>
> Neither is this.
>> * doc/guix.texi added documentation for the new records for
>> opensmtpd.
>
> Or this.
>
>> ---
>> doc/guix.texi | 1051 ++++++++++++++++++++-
>> gnu/services/mail.scm | 2016
>> ++++++++++++++++++++++++++++++++++++++++-
>> 2 files changed, 3056 insertions(+), 11 deletions(-)
>>
>> diff --git a/doc/guix.texi b/doc/guix.texi
>> index eda0956260..e8564240d1 100644
>> --- a/doc/guix.texi
>> +++ b/doc/guix.texi
>> @@ -24849,14 +24849,59 @@ could instantiate a dovecot service like
>> this:
>> @subsubheading OpenSMTPD Service
>>
>> @deffn {Scheme Variable} opensmtpd-service-type
>> -This is the type of the @uref{https://www.opensmtpd.org, OpenSMTPD}
>> -service, whose value should be an @code{opensmtpd-configuration}
>> object
>> -as in this example:
>> -
>> -@lisp
>> -(service opensmtpd-service-type
>> - (opensmtpd-configuration
>> - (config-file (local-file "./my-smtpd.conf"))))
>> +OpenSMTPD is an easy-to-use mail transfer agent (MTA). Its
>> configuration file is
>> +throughly documented in @code{man 5 smtpd.conf}. OpenSMTPD
>> @strong{listens} for incoming
>> +mail and @strong{matches} the mail to @strong{actions}. The
>> following records represent those
>> +stages:
>> +
>> +@multitable {aaaaaaaaa}
>> {aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}
>
> I suggest using fractions here.

I'll take a look at the texinfo fractions bit. This was all generated
from an org-mode document.

Toggle quote (186 lines)
>
>> [...]
>> +This is a string of one of these options:
>> +
>> +@multitable {aaaaaaaaaaaaaaaaaaaa}
>> {aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}
>
> Same here. Btw. I did not actually check all the doc in between, so I
> might be missing something.
>> +@multitable {aaaaaaaaaaaaaaaaaaaaaaaaa}
>> {aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}
>
> Likewise.
>> +@multitable {aaaaaaaaaa}
>> {aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}
>
> You get the drill.
>
>> [more doc with strange multitables]
>> diff --git a/gnu/services/mail.scm b/gnu/services/mail.scm
>> index d99743ac31..2a344e303e 100644
>> --- a/gnu/services/mail.scm
>> +++ b/gnu/services/mail.scm
>> @@ -57,8 +57,143 @@ (define-module (gnu services mail)
>> mailbox-configuration
>> namespace-configuration
>>
>> + opensmtpd-table-configuration
>> + opensmtpd-table-configuration?
>> + opensmtpd-table-configuration-name
>> + opensmtpd-table-configuration-file-db
>> + opensmtpd-table-configuration-data
>> +
>> + opensmtpd-ca-configuration
>> + opensmtpd-ca-configuration?
>> + opensmtpd-ca-configuration-name
>> + opensmtpd-ca-configuration-file
>> +
>> + opensmtpd-pki-configuration
>> + opensmtpd-pki-configuration?
>> + opensmtpd-pki-configuration-domain
>> + opensmtpd-pki-configuration-cert
>> + opensmtpd-pki-configuration-key
>> + opensmtpd-pki-configuration-dhe
>> +
>> + opensmtpd-action-local-delivery-configuration
>> + opensmtpd-action-local-delivery-configuration?
>> + opensmtpd-action-local-delivery-configuration-method
>> + opensmtpd-action-local-delivery-configuration-alias
>> + opensmtpd-action-local-delivery-configuration-ttl
>> + opensmtpd-action-local-delivery-configuration-user
>> + opensmtpd-action-local-delivery-configuration-userbase
>> + opensmtpd-action-local-delivery-configuration-virtual
>> + opensmtpd-action-local-delivery-configuration-wrapper
>> +
>> + opensmtpd-maildir-configuration
>> + opensmtpd-maildir-configuration?
>> + opensmtpd-maildir-configuration-pathname
>> + opensmtpd-maildir-configuration-junk
>> +
>> + opensmtpd-mda-configuration
>> + opensmtpd-mda-configuration-name
>> + opensmtpd-mda-configuration-command
>> +
>> + opensmtpd-action-relay-configuration
>> + opensmtpd-action-relay-configuration?
>> + opensmtpd-action-relay-configuration-backup
>> + opensmtpd-action-relay-configuration-backup-mx
>> + opensmtpd-action-relay-configuration-helo
>> + opensmtpd-action-relay-configuration-domain
>> + opensmtpd-action-relay-configuration-host
>> + opensmtpd-action-relay-configuration-pki
>> + opensmtpd-action-relay-configuration-srs
>> + opensmtpd-action-relay-configuration-tls
>> + opensmtpd-action-relay-configuration-auth
>> + opensmtpd-action-relay-configuration-mail-from
>> + opensmtpd-action-relay-configuration-src
>> +
>> + opensmtpd-option-configuration
>> + opensmtpd-option-configuration?
>> + opensmtpd-option-configuration-option
>> + opensmtpd-option-configuration-not
>> + opensmtpd-option-configuration-regex
>> + opensmtpd-option-configuration-data
>> +
>> + opensmtpd-filter-phase-configuration
>> + opensmtpd-filter-phase-configuration?
>> + opensmtpd-filter-phase-configuration-name
>> + opensmtpd-filter-phase-configuration-phase-name
>> + opensmtpd-filter-phase-configuration-options
>> + opensmtpd-filter-phase-configuration-decision
>> + opensmtpd-filter-phase-configuration-message
>> + opensmtpd-filter-phase-configuration-value
>> +
>> + opensmtpd-filter-configuration
>> + opensmtpd-filter-configuration?
>> + opensmtpd-filter-configuration-name
>> + opensmtpd-filter-configuration-proc
>> +
>> + opensmtpd-listen-on-configuration
>> + opensmtpd-listen-on-configuration?
>> + opensmtpd-listen-on-configuration-interface
>> + opensmtpd-listen-on-configuration-family
>> + opensmtpd-listen-on-configuration-auth
>> + opensmtpd-listen-on-configuration-auth-optional
>> + opensmtpd-listen-on-configuration-filters
>> + opensmtpd-listen-on-configuration-hostname
>> + opensmtpd-listen-on-configuration-hostnames
>> + opensmtpd-listen-on-configuration-mask-src
>> + opensmtpd-listen-on-configuration-disable-dsn
>> + opensmtpd-listen-on-configuration-pki
>> + opensmtpd-listen-on-configuration-port
>> + opensmtpd-listen-on-configuration-proxy-v2
>> + opensmtpd-listen-on-configuration-received-auth
>> + opensmtpd-listen-on-configuration-senders
>> + opensmtpd-listen-on-configuration-secure-connection
>> + opensmtpd-listen-on-configuration-tag
>> +
>> + opensmtpd-listen-on-socket-configuration
>> + opensmtpd-listen-on-socket-configuration?
>> + opensmtpd-listen-on-socket-configuration-filters
>> + opensmtpd-listen-on-socket-configuration-mask-src
>> + opensmtpd-listen-on-socket-configuration-tag
>> +
>> + opensmtpd-match-configuration
>> + opensmtpd-match-configuration?
>> + opensmtpd-match-configuration-action
>> + opensmtpd-match-configuration-options
>> +
>> + opensmtpd-smtp-configuration
>> + opensmtpd-smtp-configuration?
>> + opensmtpd-smtp-configuration-ciphers
>> + opensmtpd-smtp-configuration-limit-max-mails
>> + opensmtpd-smtp-configuration-limit-max-rcpt
>> + opensmtpd-smtp-configuration-max-message-size
>> + opensmtpd-smtp-configuration-sub-addr-delim character
>> +
>> + opensmtpd-srs-configuration
>> + opensmtpd-srs-configuration?
>> + opensmtpd-srs-configuration-key
>> + opensmtpd-srs-configuration-backup-key
>> + opensmtpd-srs-configuration-ttl-delay
>> +
>> + opensmtpd-queue-configuration
>> + opensmtpd-queue-configuration?
>> + opensmtpd-queue-configuration-compression
>> + opensmtpd-queue-configuration-encryption
>> + opensmtpd-queue-configuration-ttl-delay
>> +
>> opensmtpd-configuration
>> opensmtpd-configuration?
>> + opensmtpd-package
>> + opensmtpd-config-file
>> + opensmtpd-configuration-bounce
>> + opensmtpd-configuration-listen-ons
>> + opensmtpd-configuration-listen-on-socket
>> + opensmtpd-configuration-includes
>> + opensmtpd-configuration-matches
>> + opensmtpd-configuration-mda-wrappers
>> + opensmtpd-configuration-mta-max-deferred
>> + opensmtpd-configuration-srs
>> + opensmtpd-configuration-smtp
>> + opensmtpd-configuration-queue
>> +
>> opensmtpd-service-type
>> %default-opensmtpd-config-file
>>
>> @@ -1651,13 +1786,1888 @@ (define (generate-dovecot-documentation)
>> ;;; OpenSMTPD.
>> ;;;
>>
>> +;; some fieldnames have a default value of #f, which is ok. They
>> cannot have a value of #t.
>> +;; for example opensmtpd-table-configuration-data can be #f, BUT NOT
>> true.
>> +;; my/sanitize procedure tests values to see if they are of the
>> right kind.
>> +;; procedure false? is needed to allow fields like 'values' to be
>> blank, (empty), or #f BUT also
>> +;; have a value like a list of strings.
>> +(define (false? var)
>> + (eq? #f var))
>
> I'm pretty sure it'd be fine to use not in lieu of false?, even at the
> risk of matching nil.

Sounds ok. I may need to double check that there are no places
that have nil values.

Toggle quote (60 lines)
>
>> +;; this procedure takes in a var and a list of procedures. It loops
>> through list of procedures passing in var to each.
>> +;; if one procedure returns #t, the function returns true.
>> Otherwise #f.
>> +;; TODO for fun rewrite this using map
>> +;; If I rewrote it in map, then it may help with sanitizing.
>> +;; eg: I could then potentially easily sanitize vars with lambda
>> procedures.
>> +(define (is-value-right-type? var list-of-procedures record
>> fieldname)
>> + (if (null? list-of-procedures)
>> + #f
>> + (cond [(procedure? (car list-of-procedures))
>> + (if ((car list-of-procedures) var)
>> + #t
>> + (is-value-right-type? var (cdr list-of-
>> procedures) record fieldname))]
>> + [(and (sanitize-configuration? (car list-of-
>> procedures))
>> + (sanitize-configuration-error-if-proc-fails (car
>> list-of-procedures))
>> + (if ((sanitize-configuration-proc (car list-of-
>> procedures)) var)
>> + #t
>> + (begin
>> + (apply string-append
>> + (sanitize-configuration-error-
>> message (car list-of-procedures)))
>> + (throw 'bad! var))))]
>> + [else (if ((sanitize-configuration-proc (car list-of-
>> procedures)) var)
>> + #t
>> + (is-value-right-type? var (cdr list-of-
>> procedures) record fieldname))])))
>
> Don't we have field sanitizers already that make this obsolete?
>
>> +;; converts strings like this:
>> +;; "apple, ham, cherry" -> "apple, ham, or cherry"
>> +;; "pineapple" -> "pinneapple".
>> +;; "cheese, grapefruit, or jam" -> "cheese, grapefruit, or jam"
>> +(define (add-comma-or string)
>> + (define last-comma-location (string-rindex string #\,))
>> + (if last-comma-location
>> + (if (string-contains string ", or" last-comma-location)
>> + string
>> + (string-replace string ", or" last-comma-location
>> + (+ 1 last-comma-location)))
>> + string))
>> +
>> +;; I could test for read-ability of a file, but then I would have to
>> +;; test the program as root everytime instead of as a normal user...
>> +(define (file-exists? file)
>> +(if (string? file)
>> + (access? file F_OK)
>> + #f))
>
> Is this not part of the Guile standard library?

I do not believe that guile has a file-exists? thunk.
I could use (access? file F_OK) every time, but I think
file-exists? is easier to use. My two cents.

Toggle quote (50 lines)
>
>> +(define (list-of-procedures->string procedures)
>> + (define string
>> + (let loop ([procedures procedures])
>> + (if (null? procedures)
>> + ""
>> + (begin
>> + (string-append
>> + (cond [(eq? false? (car procedures))
>> + "#f , "]
>> + [(eq? boolean? (car procedures))
>> + "boolean, "]
>> + [(eq? string? (car procedures))
>> + "string, "]
>> + [(eq? integer? (car procedures))
>> + "integer, "]
>> + [(eq? list-of-strings? (car procedures))
>> + "list of strings, "]
>> + [(eq? assoc-list? (car procedures))
>> + "an association list, "]
>> + [(eq? opensmtpd-pki-configuration? (car
>> procedures))
>> + "an <opensmtpd-pki-configuration> record, "]
>> + [(eq? opensmtpd-table-configuration? (car
>> procedures))
>> + "an <opensmtpd-table-configuration> record, "]
>> + [(eq? list-of-unique-opensmtpd-match-
>> configuration? (car procedures))
>> + "a list of unique <opensmtpd-match-
>> configuration> records, "]
>> + [(eq? table-whose-data-are-assoc-list? (car
>> procedures))
>> + (string-append
>> + "an <opensmtpd-table-configuration> record whose
>> fieldname 'values' are an assoc-list \n"
>> + "(eg: (opensmtpd-table-configuration (name
>> \"table\") (data '(\"joshua\" . \"$encrypted$password\")))), ")]
>> + [(eq? file-exists? (car procedures))
>> + "file, "]
>> + [else "has an incorrect value, "])
>> + (loop (cdr procedures)))))))
>> + (add-comma-or (string-append (string-drop-right string 2) ".\n")))
>
> Using a table, map and string-join might be wiser. If this is the only
> place add-comma-or is used, you can replace it by
> (string-append
> (string-join (butlast strings) ",")
> ", or " (last strings))
> where you only need to define butlast.

I'll take a look.

Toggle quote (14 lines)
>
>> +;; TODO can I M-x raise-sexp (string=? string var) in this
>> procedure? and get rid of checking
>> +;; if the var is a string? The previous string-in-list? had that
>> check.
>> +;; (string-in-list? '("hello" 5 "cat")) currently works. If I M-x
>> raise-sexp (string=? string var)
>> +;; then it will no longer work.
>> +(define (string-in-list? string list)
>> + (primitive-eval (cons 'or (map (lambda (var) (and (string? var)
>> (string=? string var))) list))))
>
> Ever heard of member?

Will use it.

Toggle quote (41 lines)
>
>> +(define (my/sanitize var record fieldname list-of-procedures)
>> + (if (is-value-right-type? var list-of-procedures record fieldname)
>> + var
>> + (begin
>> + (display (string-append "<" record "> fieldname: '"
>> fieldname "' is of type "
>> + (list-of-procedures->string list-of-
>> procedures) "\n"))
>> + (throw 'bad! var))))
>> +
>> +;; Some example opensmtpd-table-configurations:
>> +;;
>> +;; (opensmtpd-table-configuration (name "root accounts") (data
>> '(("joshua" . "root@dismail.de") ("joshua" .
>> "postmaster@dismail.de"))))
>> +;; (opensmtpd-table-configuration (name "root accounts") (data
>> (list "mysite.me" "your-site.com")))
>> +;; TODO should <opensmtpd-table-configuration> support have a
>> fieldname 'file'?
>> +;; Or should I change name to name-or-file ?
>> +(define-record-type* <opensmtpd-table-configuration>
>> + opensmtpd-table-configuration make-opensmtpd-table-configuration
>> + opensmtpd-table-configuration?
>> + this-record
>> + (name opensmtpd-table-configuration-name ;; string
>> + (default #f)
>> + (sanitize (lambda (var)
>> + (my/sanitize var "opensmtpd-table-configuration"
>> "name" (list string?)))))
>> + (file-db opensmtpd-table-configuration-file-db
>> + (default #f)
>> + (sanitize (lambda (var)
>> + (my/sanitize var "opensmtpd-table-
>> configuration" "file-db"
>> + (list boolean?)))))
>> + ;; FIXME support an aliasing table as described here:
>> + ;; https://man.openbsd.org/table.5
>> + ;; One may have to use the record file for this. I don't think
>> tables support a table like this:
>> + ;; table "name"
This message was truncated. Download the full message here.
L
L
Liliana Marie Prikler wrote on 7 Jul 2022 06:25
ce7ebbcfa7585592f2ba276b3d416172f9678f97.camel@gmail.com
Am Mittwoch, dem 06.07.2022 um 21:51 +0000 schrieb jbranso@dismail.de:
Toggle quote (3 lines)
> I do not believe that guile has a file-exists? thunk. 
> I could use (access? file F_OK) every time, but I think
> file-exists? is easier to use.  My two cents.
scheme@(guile-user)> file-exists?
$1 = #<procedure 7fa4d7da6828 at ice-9/boot-9.scm:1971:6 (str)>

Toggle quote (9 lines)
>
> > What is a "listen-on"?
>
> "listen-on" refers to the "listen on" in smtpd.conf:
> https://man.openbsd.org/smtpd.conf
>
> lan_addr = "192.168.0.1"
> listen on $lan_addr
> listen on $lan_addr tls auth
Okay, but what would you call that? An address maybe?

Toggle quote (8 lines)
> > > +(define-record-type* <opensmtpd-listen-on-socket-configuration-
> > > configuration>
> >
> > Again, could this just be <opensmtpd-socket-configuration>?
>
> I would prefer to have two data types for "listen on" and
> "listen on socket".  "listen on socket" only supports 3 options,
> where "listen on" supports 19.
I am not questioning whether it makes sense to add a configuration
record – it probably does – but whether you're using the best name for
that record. We are not Java programmers here, a little abstraction
goes a long way.

Toggle quote (13 lines)
> From the documentation:
>
> listen on interface [family] [options]
>     Listen on the interface for incoming connections, using the same
> syntax as ifconfig(8). The interface parameter may also be an
> interface group, an IP address, or a domain name. Listening can
> optionally be restricted to a specific address family, which can be
> either inet4 or inet6.
>
> listen on socket [options]
>     Listen for incoming SMTP connections on the Unix domain socket
> /var/run/smtpd.sock. This is done by default, even if the directive
> is absent.
So you can either have an opensmtp-interface (with family and a bunch
of options) or an opensmtp-socket (with a bunch of options). Sounds
like a much nicer ontology, doesn't it?

Toggle quote (11 lines)
> > > [...]
> >
> > Too much to check, too little time. Maybe return later.
>
> To summarize the tasks that you have given me are:
>
> 1) Write a proper changelog.
> 2) define "string-in-list?" with member?
>    Are there other procedures that could use this?
> 3) replace [] with ()
> 4) Shorten the sanitize procedure for opensmtpd-option-configuration
5) Review your class names.
I also don't think it makes too much sense to add -configuration for
anything but the top-level configuration record, it just requires you
to type much more configuration than you probably want.

Cheers
J
J
jbranso wrote on 7 Jul 2022 19:27
338cfc2ca96492218838280d8961bef7@dismail.de
July 7, 2022 2:48 AM, "Liliana Marie Prikler" <liliana.prikler@gmail.com> wrote:

Toggle quote (9 lines)
> Am Mittwoch, dem 06.07.2022 um 21:51 +0000 schrieb jbranso@dismail.de:
>
>> I do not believe that guile has a file-exists? thunk.
>> I could use (access? file F_OK) every time, but I think
>> file-exists? is easier to use. My two cents.
>
> scheme@(guile-user)> file-exists?
> $1 = #<procedure 7fa4d7da6828 at ice-9/boot-9.scm:1971:6 (str)>

ok. Good to know!

Toggle quote (44 lines)
>
>> What is a "listen-on"?
>>
>> "listen-on" refers to the "listen on" in smtpd.conf:
>> https://man.openbsd.org/smtpd.conf
>>
>> lan_addr = "192.168.0.1"
>> listen on $lan_addr
>> listen on $lan_addr tls auth
>
> Okay, but what would you call that? An address maybe?
>
>>> +(define-record-type* <opensmtpd-listen-on-socket-configuration-
>>> configuration>
>>
>> Again, could this just be <opensmtpd-socket-configuration>?
>>
>> I would prefer to have two data types for "listen on" and
>> "listen on socket". "listen on socket" only supports 3 options,
>> where "listen on" supports 19.
>
> I am not questioning whether it makes sense to add a configuration
> record – it probably does – but whether you're using the best name for
> that record. We are not Java programmers here, a little abstraction
> goes a long way.
>
>> From the documentation:
>>
>> listen on interface [family] [options]
>> Listen on the interface for incoming connections, using the same
>> syntax as ifconfig(8). The interface parameter may also be an
>> interface group, an IP address, or a domain name. Listening can
>> optionally be restricted to a specific address family, which can be
>> either inet4 or inet6.
>>
>> listen on socket [options]
>> Listen for incoming SMTP connections on the Unix domain socket
>> /var/run/smtpd.sock. This is done by default, even if the directive
>> is absent.
>
> So you can either have an opensmtp-interface (with family and a bunch
> of options) or an opensmtp-socket (with a bunch of options). Sounds
> like a much nicer ontology, doesn't it?

That does make much more sense! I'll do that.

Toggle quote (6 lines)
>
>>> [...]
>>
>> Too much to check, too little time. Maybe return later.
>>

To summarize the updated tasks that you have given me are:
1) Write a proper changelog.
2) define "string-in-list?" with member?
Are there other procedures that could use this?
3) DONE replace [] with ()
4) Shorten the sanitize procedure for opensmtpd-option-configuration
5) Review your class names.

I also don't think it makes too much sense to add -configuration for
anything but the top-level configuration record, it just requires you
to type much more configuration than you probably want.

Also does guix have a style guide for writing services? Do we usually
only put "-configuration" for the top level configuration? Is
that the current style recommendations?
eg: rename opensmtpd-listen-on-configuration and
opensmtpd-listen-on-socket-configuration to opensmtpd-interface
and opensmtpd-socket.
L
L
Liliana Marie Prikler wrote on 7 Jul 2022 20:20
8abb0b095fd83baa81b6dc14364ae07da4036a17.camel@gmail.com
Am Donnerstag, dem 07.07.2022 um 17:27 +0000 schrieb
jbranso@dismail.de:
Toggle quote (3 lines)
> Also does guix have a style guide for writing services?  Do we
> usually only put "-configuration" for the top level configuration? 
> Is that the current style recommendations?
Style guide #0 is "look at what already exists". For example, the
jami-service also defines jami-account via define-configuration. Hope
that helps.

Cheers
J
J
Joshua Branson wrote on 8 Jul 2022 05:06
Re: bug#56046: [PATCH] services: mail: add opensmtpd records to enhance opensmtpd-configuration.
(name . Liliana Marie Prikler)(address . liliana.prikler@gmail.com)(address . 56046@debbugs.gnu.org)
87mtdkfgl6.fsf_-_@dismail.de
Liliana Marie Prikler <liliana.prikler@gmail.com> writes:

Toggle quote (10 lines)
> Am Donnerstag, dem 07.07.2022 um 17:27 +0000 schrieb
> jbranso@dismail.de:
>> Also does guix have a style guide for writing services?  Do we
>> usually only put "-configuration" for the top level configuration? 
>> Is that the current style recommendations?
> Style guide #0 is "look at what already exists". For example, the
> jami-service also defines jami-account via define-configuration. Hope
> that helps.
>

I suppose that I was following the nginx style. It seems like most of
their records end in "-configuration". Thanks again for reviewing this.
I should have an updated patch soon.

Toggle quote (2 lines)
>
> Cheers
J
J
Joshua Branson wrote on 12 Jul 2022 17:45
(name . Liliana Marie Prikler)(address . liliana.prikler@gmail.com)(address . 56046@debbugs.gnu.org)
87a69etjvi.fsf_-_@dismail.de
Joshua Branson <jbranso@dismail.de> writes:

Just an update on progress. The main thing to report is that the best
place to find the task list is here:



The best place to find a good example configuration will always be found
here:



The main thing that I am focusing on now is how to make it easy for
users of this service to use opensmtpd filters:

search for "enable to do dkimsigning or bogofilter" is the file and
you'll see where it is. for some reason the link is REALLY long when I
try to paste it in this email.


Thanks,

Joshua
J
J
Joshua Branson wrote on 12 Jul 2022 18:38
(name . Liliana Marie Prikler)(address . liliana.prikler@gmail.com)(address . 56046@debbugs.gnu.org)
877d4ithfn.fsf_-_@dismail.de
Joshua Branson <jbranso@dismail.de> writes:

Video update!


That's a link to a video update of why
opensmtpd-filter-configuration-proc should be a string or list of
strings and/or gexps instead of just being a mixed-text-file.

It is primarily meant for nckx on irc. But anyone else is free to
comment.


Thanks,

Joshua
J
J
Joshua Branson wrote on 24 Oct 2022 19:30
[Patch master v2] services (opensmtpd): add opensmtpd records to enhance opensmtpd-configuration.
(address . 56046@debbugs.gnu.org)
a8ebf5f4f792cb98b7691c40053f30e09386b177.1666632422.git.jbranso@dismail.de
This is a V2 patch. I've added some tests that help test for various
ways that users could accidentally misconfigure their configuration.

I probably need to make those error messages, use
(guix diagnostics). Currently compiling the tests, auto runs them.
So "make" auto runs the tests. Also their error messages are output
to the terminal, and I'm not sure how to turn that off.

tl;dr this is a WIP patch, and I just wanted to submit something,
because I keep finding more things that I need to fix.

The task list as always is here:

Openmstpd-configuration may only be configured by a config-file that
uses the smtpd.conf syntax. This patch, enables one to configure
opensmtpd by using record types.

* gnu/services/mail.scm:
(opensmtpd-table-configuration,
opensmtpd-ca-configuration,
opensmtpd-pki-configuration,
opensmtpd-action-local-delivery-configuration,
opensmtpd-maildir-configuration,
opensmtpd-mda-configuration,
opensmtpd-action-relay-configuration,
opensmtpd-option-configuration,
opensmtpd-filter-phase-configuration,
opensmtpd-filter-configuration,
opensmtpd-interface,
opensmtpd-socket,
opensmtpd-match-configuration,
opensmtpd-smtp-configuration,
opensmtpd-srs-configuration,
opensmtpd-queue-configuration, and
opensmtpd-configuration): New records.

(false?, is-value-right-type, add-comma-or-string,
list-of-procedures->string, string-in-list?, my-sanitize,
opensmtpd-filter-chain?, throw-error-duplicate-option,
sanitize-list-of-options-for-match-configuration, sanitize-filters,
list-has-duplicates-or-non-filters?,
filter-phase-has-message-and-value?,
filter-phase-decision-lacks-proper-message?,
filter-phase-lacks-proper-value?,
filter-phase-has-incorrect-junk-or-bypass?,
filter-phase-junks-after-commit?,
list-of-unique-filter-or-filter-phase?, throw-error,
contains-duplicate?, list-of-type?, list-of-strings?,
list-of-unique-opensmtpd-option-configuration?,
list-of-opensmtpd-ca-configuration?,
list-of-opensmtpd-pki-configuration?,
list-of-opensmtpd-listen-on-configuration?,
list-of-unique-opensmtpd-match-configuration?, list-of-strings->string,
assoc-list? assoc-list, variable->string,
table-whose-data-are-assoc-list?,
table-whose-data-are-a-list-of-strings?, assoc-list->string,
opensmtpd-table-configuration->string,
opensmtpd-listen-on-configuration->string,
opensmtpd-listen-on-socket-configuration->string,
opensmtpd-action-relay-configuration->string,
opensmtpd-lmtp-configuration->string,
opensmtpd-mda-configuration->string,
opensmtpd-maildir-configuration->string,
opensmtpd-action-local-delivery-configuration->string,
opensmtpd-action->string, opensmtpd-option-configuration->string,
opensmtpd-match-configuration->string,
opensmtpd-ca-configuration->string, opensmtpd-pki-configuration->string,
generate-filter-chain-name, opensmtpd-filter-chain->string,
opensmtpd-filter-phase-configuration->string, opensmtpd-filters->string,
opensmtpd-configuration-listen->string,
opensmtpd-configuration-srs->string,
opensmtpd-smtp-configuration->string,
opensmtpd-configuration-queue->string, get-opensmtpd-actions,
get-opensmtpd-pki-configurations, get-opensmtpd-filters, flatten,
get-opensmtpd-tables, opensmtpd-configuration-fieldname->string,
list-of-records->string, opensmtpd-configuration->mixed-text-file): New
procedures.

* gnu/tests/mail.scm : new tests for various opensmtpd records.

* doc/guix.texi (OpenSMTPD Service): Added documentation for the
new records for opensmtpd.
---
doc/guix.texi | 1054 ++++++++++++++++++++-
gnu/services/mail.scm | 2085 ++++++++++++++++++++++++++++++++++++++++-
gnu/tests/mail.scm | 355 +++++++
3 files changed, 3475 insertions(+), 19 deletions(-)

Toggle diff (490 lines)
diff --git a/doc/guix.texi b/doc/guix.texi
index 535c8cdfc3..c80f3e9d76 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -25409,14 +25409,59 @@ could instantiate a dovecot service like this:
@subsubheading OpenSMTPD Service
@deffn {Scheme Variable} opensmtpd-service-type
-This is the type of the @uref{https://www.opensmtpd.org, OpenSMTPD}
-service, whose value should be an @code{opensmtpd-configuration} object
-as in this example:
-
-@lisp
-(service opensmtpd-service-type
- (opensmtpd-configuration
- (config-file (local-file "./my-smtpd.conf"))))
+OpenSMTPD is an easy-to-use mail transfer agent (MTA). Its configuration file is
+throughly documented in @code{man 5 smtpd.conf}. OpenSMTPD @strong{listens} for incoming
+mail and @strong{matches} the mail to @strong{actions}. The following records represent those
+stages:
+
+@multitable {aaaaaaaaa} {aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}
+@item @strong{listens}
+@tab @code{<opensmtpd-interface>}
+@item
+@tab @code{<opensmtpd-socket>}
+@item
+@tab
+@item @strong{matches}
+@tab @code{<opensmtpd-match>}
+@item
+@tab
+@item @strong{actions}
+@tab @code{<opensmtpd-local-delivery>}
+@item
+@tab @code{<opensmtpd-relay>}
+@end multitable
+
+Additionally, each @code{<opensmtpd-interface>} and
+@code{<opensmtpd-socket>} may use a list of
+@code{<opensmtpd-filter>}, and/or
+@code{<opensmtpd-filter-phase>} records to filter email/spam. Also
+numerous records' fieldnames use @code{<opensmtpd-table>} to hold lists
+or key value pairs of data.
+
+A simple example configuration is below:
+
+@lisp
+(let ((smtp.gnu.org (opensmtpd-pki
+ (domain "smtp.gnu.org")
+ (cert "file.cert")
+ (key "file.key"))))
+ (service opensmtpd-service-type
+ (opensmtpd-configuration
+ (listen-ons (list
+ (opensmtpd-interface
+ (pki smtp.gnu.org))
+ (opensmtpd-interface
+ (pki smtp.gnu.org)
+ (secure-connection "smtps"))))
+ (matches (list
+ (opensmtpd-match
+ (action
+ (opensmtpd-local-delivery
+ (name "local-delivery"))))
+ (opensmtpd-match
+ (action
+ (opensmtpd-relay
+ (name "relay")))))))))
@end lisp
@end deffn
@@ -25433,14 +25478,1007 @@ it listens on the loopback network interface, and allows for mail from
users and daemons on the local machine, as well as permitting email to
remote servers. Run @command{man smtpd.conf} for more information.
+<<<<<<< HEAD
+@item @code{bounce} (default: @code{(list "4h")})
+
+@code{bounce} is a list of strings, which send warning messages to the envelope
+sender when temporary delivery failures cause a message to remain in the
+queue for longer than string delay. Each string delay parameter consists
+of a string beginning with a positive decimal integer and a unit 's', 'm', 'h',
+or 'd'. At most four delay parameters can be specified.
+
+@item @code{listen-ons} (default: @code{(list (opensmtpd-interface))})
+
+@code{listen-ons} is a list of @code{<opensmtpd-interface>} records.
+This list details what interfaces and ports OpenSMTPD listens on as well as
+other information.
+
+@item @code{listen-on-socket} (default: @code{(opensmtpd-socket)})
+
+Listens for incoming connections on the Unix domain socket.
+
+@item @code{includes} (default: @code{#f})
+
+@code{includes} is a list of string filenames. Each filename's contents is
+additional configuration that is inserted into the top of the configuration
+file.
+
+@item @code{matches} default:
+
+@lisp
+ (list (opensmtpd-match
+ (action (opensmtpd-local-delivery
+ (name "local")
+ (method "mbox")))
+ (for (opensmtpd-option
+ (option "for local"))))
+ (opensmtpd-match
+ (action (opensmtpd-relay
+ (name "outbound")))
+ (from (opensmtpd-option
+ (option "from local")))
+ (for (opensmtpd-option
+ (option "for any")))))
+@end lisp
+
+@code{matches} is a list of @code{<opensmtpd-match>} records, which
+matches incoming mail and sends it to a correspending action. The match
+records are evaluated sequentially, with the first match winning. If an
+incoming mail does not match any match records, then it is rejected.
+@c put this backin? @end itemize
+
+@c put this back in? @itemize
+@item @code{mta-max-deferred} (default: @code{100})
+
+When delivery to a given host is suspended due to temporary failures, cache
+at most number envelopes for that host such that they can be delivered as
+soon as another delivery succeeds to that host. The default is 100.
+
+@item @code{queue} (default: @code{#f})
+
+@code{queue} expects an @code{<opensmtpd-queue>} record. With it, one may
+compress and encrypt queue-ed emails as well as set the default expiration
+time for temporarily undeliverable messages.
+
+@item @code{smtp} (default: @code{#f})
+
+@code{smtp} expects an @code{<opensmtpd-smtp>} record, which lets one
+specifiy how large email may be along with other settings.
+
+@item @code{srs} (default: @code{#f})
+
+@code{srs} expects an @code{<opensmtpd-srs>} record, which lets one set
+up SRS, the Sender Rewritting Scheme.
+=======
@item @code{setgid-commands?} (default: @code{#t})
Make the following commands setgid to @code{smtpq} so they can be
executed: @command{smtpctl}, @command{sendmail}, @command{send-mail},
@command{makemap}, @command{mailq}, and @command{newaliases}.
@xref{Setuid Programs}, for more information on setgid programs.
+>>>>>>> origin/master
@end table
@end deftp
+@itemize
+@item
+Data Type: opensmtpd-interface
+
+Data type representing the configuration of an
+@code{<opensmtpd-interface>}. Listen on the fieldname @code{interface} for
+incoming connections, using the same syntax as for ifconfig(8). The interface
+parameter may also be an string interface group, an string IP address, or a
+string domain name. Listening can optionally be restricted to a specific
+address fieldname @code{family}, which can be either ``inet4'' or ``inet6''.
+
+@itemize
+@item @code{interface} (default: ``lo'')
+
+The string interface to listen for incoming connections. These interface can
+usually be found by the command @code{ip link}.
+
+@item @code{family} (default: @code{#f})
+
+The string IP family to use. Valid strings are ``inet4'' or ``inet6''.
+
+@item @code{auth} (default: @code{#f})
+
+Support SMTPAUTH: clients may only start SMTP transactions after successful
+authentication. If @code{auth} is @code{#t}, then users are authenticated against
+their own normal login credentials. Alternatively @code{auth} may be an
+@code{<opensmtpd-table>} whose users are authenticated against
+their passwords.
+
+@item @code{auth-optional} (default: @code{#f})
+
+Support SMTPAUTH optionally: clients need not authenticate, but may do so.
+This allows the @code{<opensmtpd-interface>} to both accept
+incoming mail from untrusted senders and permit outgoing mail from
+authenticated users (using @code{<opensmtpd-match>} fieldname
+@code{auth}). It can be used in situations where it is not possible to listen on
+a separate port (usually the submission port, 587) for users to
+authenticate.
+
+@item @code{filters} (default: @code{#f})
+
+A list of one or many @code{<opensmtpd-filter>} or
+@code{<opensmtpd-filter-phase>} records. The filters are applied
+sequentially. These records listen and filter on connections handled by this
+listener.
+
+@item @code{hostname} (default: @code{#f})
+
+Use string ``hostname'' in the greeting banner instead of the default server
+name.
+
+@item @code{hostnames} (default: @code{#f})
+
+Override the server name for specific addresses. Use a
+@code{<opensmtpd-table>} containing a mapping of string IP
+addresses to hostnames. If the address on which the connection arrives
+appears in the mapping, the associated hostname is used.
+
+@item @code{mask-src} (default: @code{#f})
+
+If @code{#t}, then omit the from part when prepending “Received” headers.
+
+@item @code{disable-dsn} (default: @code{#f})
+
+When @code{#t}, then disable the DSN (Delivery Status Notification) extension.
+
+@item @code{pki} (default: @code{#f})
+
+For secure connections, use an @code{<opensmtpd-pki>}
+to prove a mail server's identity.
+
+@item @code{port} (default: @code{#f})
+
+Listen on the integer port instead of the default port of 25.
+
+@item @code{proxy-v2} (default: @code{#f})
+
+If @code{#t}, then support the PROXYv2 protocol, rewriting appropriately source
+address received from proxy.
+
+@item @code{received-auth} (default: @code{#f})
+
+If @code{#t}, then in “Received” headers, report whether the session was
+authenticated and by which local user.
+
+@item @code{senders} (default: @code{#f})
+
+Look up the authenticated user in the supplied
+@code{<opensmtpd-table>} to find the email addresses that user is
+allowed to submit mail as.
+
+@item @code{secure-connection} (default: @code{#f})
+
+This is a string of one of these options:
+
+@multitable {aaaaaaaaaaaaaaaaaaaa} {aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}
+@item ``smtps''
+@tab Support SMTPS, by default on port 465.
+@item ``tls''
+@tab Support STARTTLS, by default on port 25.
+@item ``tls-require-verify''
+@tab Like tls, but force clients to establish
+@item
+@tab a secure connection before being allowed to
+@item
+@tab start an SMTP transaction. With the verify
+@item
+@tab option, clients must also provide a valid
+@item
+@tab certificate to establish an SMTP session.
+@end multitable
+
+@item @code{tag} (default: @code{#f})
+
+Clients connecting to the listener are tagged with the given string tag.
+@end itemize
+
+@item Data Type: opensmtpd-socket
+
+Data type representing the configuration of an
+@code{<opensmtpd-socket>}. Listen for incoming SMTP
+connections on the Unix domain socket @samp{/var/run/smtpd.sock}. This is done by
+default, even if the directive is absent.
+
+@itemize
+@item @code{filters} (default: @code{#f})
+
+A list of one or many @code{<opensmtpd-filter>} or
+@code{<opensmtpd-filter-phase>} records. These filter incoming
+connections handled by this listener.
+
+@item @code{mask-src} (default: @code{#f})
+
+If @code{#t}, then omit the from part when prepending “Received” headers.
+
+@item @code{tag} (default: @code{#f})
+
+Clients connecting to the listener are tagged with the given string tag.
+@end itemize
+
+@item Data Type: opensmtpd-match
+
+This data type represents the configuration of an
+@code{<opensmtpd-match>} record.
+
+If at least one mail envelope matches the options of one match record, receive
+the incoming message, put a copy into each matching envelope, and atomically
+save the envelopes to the mail spool for later processing by the respective
+@code{<opensmtpd-action>} found in fieldname @code{action}.
+
+@itemize
+@item @code{action} (default: @code{#f})
+
+If mail matches this match configuration, then do this action. Valid values
+include @code{<opensmtpd-local-delivery>} or
+@code{<opensmtpd-relay>}.
+
+@item @code{options} (default: @code{#f}) @code{<opensmtpd-option>}
+The fieldname 'option' is a list of unique
+@code{<opensmtpd-option>} records.
+
+Each @code{<opensmtpd-option>} record's fieldname 'option' has some
+mutually exclusive options: there can be only one ``for'' and only one ``from'' option.
+
+@multitable {aaaaaaaaaaaaaaaaaaaaaaaaa} {aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}
+@headitem for
+@tab from
+@item only use one of the following:
+@tab only use one of the following:
+@item ``for any''
+@tab ``from any''
+@item ``for local''
+@tab ``from auth''
+@item ``for domain''
+@tab ``from local''
+@item ``for rcpt-to''
+@tab ``from mail-from''
+@item
+@tab ``from socket''
+@item
+@tab ``from src''
+@end multitable
+
+The following matching options are supported and can all be negated (via not
+#t). The options that support a table (anything surrounded with '<' and '>'
+eg: <table>), also support specifying regex via (regex #t).
+
+@itemize
+@item @samp{for any}
+
+Specify that session may address any destination.
+
+@item @samp{for local}
+
+Specify that session may address any local domain. This is the default,
+and may be omitted.
+
+@item @samp{for domain _domain_ | <domain>}
+
+Specify that session may address the string or list table domain.
+
+@item @samp{for rcpt-to _recipient_ | <recipient>}
+
+Specify that session may address the string or list table recipient.
+
+@item @samp{from any}
+
+Specify that session may originate from any source.
+
+@item @samp{from auth}
+
+Specify that session may originate from any authenticated user, no matter
+the source IP address.
+
+@item @samp{from auth _user_ | <user>}
+
+Specify that session may originate from authenticated user or user list
+user, no matter the source IP address.
+
+@item @samp{from local}
+
+Specify that session may only originate from a local IP address, or from
+the local enqueuer. This is the default, and may be omitted.
+
+@item @samp{from mail-from _sender_ | <sender>}
+
+Specify that session may originate from sender or table sender, no
+matter the source IP address.
+
+@item @samp{from rdns}
+
+Specify that session may only originate from an IP address that resolves
+to a reverse DNS@.
+
+@item @samp{from rdns _hostname_ | <hostname>}
+
+Specify that session may only originate from an IP address that resolves
+to a reverse DNS matching string or list string hostname.
+
+@item @samp{from socket}
+
+Specify that session may only originate from the local enqueuer.
+
+@item @samp{from src _address_ | <address>}
+
+Specify that session may only originate from string or list table address
+which can be a specific address or a subnet expressed in CIDR-notation.
+
+@item @samp{auth}
+
+Matches transactions which have been authenticated.
+
+@item @samp{auth _username_ | <username>}
+
+Matches transactions which have been authenticated for user or user list
+username.
+
+@item @samp{helo _helo-name_ | <helo-name>}
+
+Specify that session's HELO / EHLO should match the string or list table
+helo-name.
+
+@item @samp{mail-from _sender_ | <sender>}
+
+Specify that transactions's MAIL FROM should match the string or list
+table sender.
+
+@item @samp{rcpt-to _recipient_ | <recipient>}
+
+Specify that transaction's RCPT TO should match the string or list table
+recipient.
+
+@item @samp{tag tag}
+Matches transactions tagged with the given tag.
+
+@item @samp{tls}
+Specify that transaction should take place in a TLS channel.
+@end itemize
+
+Here is a simple example:
+@lisp
+ (opensmtpd-option
+ (not #t)
+ (regex #f)
+ (option "for domain")
+ (data (opensmtpd-table
+ (name "domain-table")
+ (data (list "gnu.org" "dismail.de")))))
+@end lisp
+
+The mail must NOT come from the domains @samp{gnu.org} or @samp{dismail.de}.
+
+@item Data Type: opensmtpd-option
+@end itemize
+
+@item Data Type: opensmtpd-local-delivery
+
+This data type represents the configuration of an
+@code{<opensmtpd-local-delivery>} record.
+
+@itemize
+@item
+@code{name} (default: @code{#f})
+
+@code{name} is the string name of the relay action.
+
+@item @code{method} (default: @code{"mbox"})
+
+The email delivery option. Valid options are:
+
+@itemize
+@item @code{"mbox"}
+
+Deliver the message to the user's mbox with mail.local(8).
+
+@item @code{"expand-only"}
+
+Only accept the message if a delivery method was specified in an aliases
+or .forward file.
+
+@item @code{"forward-only"}
+
+Only accept the message if the recipient results in a remote address after
+the processing of aliases or forward file.
+
+@item @code{<opensmtpd-lmtp>}
+
+Deliver the message to an LMTP server at
+@code{<opensmtpd-lmtp>}'s fieldname @code{destination}. The location
+may be expressed as string host:port or as a UNIX socket. Optionally,
+@code{<opensmtpd-lmtponfiguration>}'s fieldname @code{rcpt-to} might be specified
+to use the recipient email address (after expansion) instead of the local

This message was truncated. Download the full message here.
L
L
Liliana Marie Prikler wrote on 24 Oct 2022 20:28
b919e1ad91cd7849ea2806b7180b2c9f29e2b5b5.camel@gmail.com
Am Montag, dem 24.10.2022 um 13:30 -0400 schrieb Joshua Branson:
Toggle quote (21 lines)
> This is a V2 patch.  I've added some tests that help test for various
> ways that users could accidentally misconfigure their configuration.
>
> I probably need to make those error messages, use  
> (guix diagnostics).  Currently compiling the tests, auto runs them.
> So "make" auto runs the tests.  Also their error messages are output
> to the terminal, and I'm not sure how to turn that off.
>
> tl;dr this is a WIP patch, and I just wanted to submit something,
> because I keep finding more things that I need to fix.
>
> The task list as always is here:
> https://notabug.org/jbranso/linode-guix-system-configuration/src/master/opensmtpd.org
>  
>
> Openmstpd-configuration may only be configured by a config-file that
> uses the smtpd.conf syntax.  This patch, enables one to configure
> opensmtpd by using record types.
>
> * gnu/services/mail.scm:
> (opensmtpd-table-configuration,
ChangeLog format would be (opensmtpd-table-configuration) followed by a
new line, followed by (opensmtpd-ca-configuration) etc.
Toggle quote (160 lines)
> opensmtpd-ca-configuration,
> opensmtpd-pki-configuration,
> opensmtpd-action-local-delivery-configuration,
> opensmtpd-maildir-configuration,
> opensmtpd-mda-configuration,
> opensmtpd-action-relay-configuration,
> opensmtpd-option-configuration,
> opensmtpd-filter-phase-configuration,
> opensmtpd-filter-configuration,
> opensmtpd-interface,
> opensmtpd-socket,
> opensmtpd-match-configuration,
> opensmtpd-smtp-configuration,
> opensmtpd-srs-configuration,
> opensmtpd-queue-configuration, and
> opensmtpd-configuration): New records.
>
> (false?, is-value-right-type, add-comma-or-string,
> list-of-procedures->string, string-in-list?, my-sanitize,
> opensmtpd-filter-chain?, throw-error-duplicate-option,
> sanitize-list-of-options-for-match-configuration, sanitize-filters,
> list-has-duplicates-or-non-filters?,
> filter-phase-has-message-and-value?,
> filter-phase-decision-lacks-proper-message?,
> filter-phase-lacks-proper-value?,
> filter-phase-has-incorrect-junk-or-bypass?,
> filter-phase-junks-after-commit?,
> list-of-unique-filter-or-filter-phase?, throw-error,
> contains-duplicate?, list-of-type?, list-of-strings?,
> list-of-unique-opensmtpd-option-configuration?,
> list-of-opensmtpd-ca-configuration?,
> list-of-opensmtpd-pki-configuration?,
> list-of-opensmtpd-listen-on-configuration?,
> list-of-unique-opensmtpd-match-configuration?, list-of-strings-
> >string,
> assoc-list? assoc-list, variable->string,
> table-whose-data-are-assoc-list?,
> table-whose-data-are-a-list-of-strings?, assoc-list->string,
> opensmtpd-table-configuration->string,
> opensmtpd-listen-on-configuration->string,
> opensmtpd-listen-on-socket-configuration->string,
> opensmtpd-action-relay-configuration->string,
> opensmtpd-lmtp-configuration->string,
> opensmtpd-mda-configuration->string,
> opensmtpd-maildir-configuration->string,
> opensmtpd-action-local-delivery-configuration->string,
> opensmtpd-action->string, opensmtpd-option-configuration->string,
> opensmtpd-match-configuration->string,
> opensmtpd-ca-configuration->string, opensmtpd-pki-configuration-
> >string,
> generate-filter-chain-name, opensmtpd-filter-chain->string,
> opensmtpd-filter-phase-configuration->string, opensmtpd-filters-
> >string,
> opensmtpd-configuration-listen->string,
> opensmtpd-configuration-srs->string,
> opensmtpd-smtp-configuration->string,
> opensmtpd-configuration-queue->string, get-opensmtpd-actions,
> get-opensmtpd-pki-configurations, get-opensmtpd-filters, flatten,
> get-opensmtpd-tables, opensmtpd-configuration-fieldname->string,
> list-of-records->string, opensmtpd-configuration->mixed-text-file):
> New
> procedures.
>
> * gnu/tests/mail.scm : new tests for various opensmtpd records.
>
> * doc/guix.texi (OpenSMTPD Service): Added documentation for the
> new records for opensmtpd.
> ---
>  doc/guix.texi         | 1054 ++++++++++++++++++++-
>  gnu/services/mail.scm | 2085
> ++++++++++++++++++++++++++++++++++++++++-
>  gnu/tests/mail.scm    |  355 +++++++
>  3 files changed, 3475 insertions(+), 19 deletions(-)
>
> diff --git a/doc/guix.texi b/doc/guix.texi
> index 535c8cdfc3..c80f3e9d76 100644
> --- a/doc/guix.texi
> +++ b/doc/guix.texi
> @@ -25409,14 +25409,59 @@ could instantiate a dovecot service like
> this:
>  @subsubheading OpenSMTPD Service
>  
>  @deffn {Scheme Variable} opensmtpd-service-type
> -This is the type of the @uref{https://www.opensmtpd.org, OpenSMTPD}
> -service, whose value should be an @code{opensmtpd-configuration}
> object
> -as in this example:
> -
> -@lisp
> -(service opensmtpd-service-type
> -         (opensmtpd-configuration
> -           (config-file (local-file "./my-smtpd.conf"))))
> +OpenSMTPD is an easy-to-use mail transfer agent (MTA). Its
> configuration file is
> +throughly documented in @code{man 5 smtpd.conf}. OpenSMTPD
> @strong{listens} for incoming
> +mail and @strong{matches} the mail to @strong{actions}. The
> following records represent those
> +stages:
> +
> +@multitable {aaaaaaaaa}
> {aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}
> +@item @strong{listens}
> +@tab @code{<opensmtpd-interface>}
> +@item
> +@tab @code{<opensmtpd-socket>}
> +@item
> +@tab
> +@item @strong{matches}
> +@tab @code{<opensmtpd-match>}
> +@item
> +@tab
> +@item @strong{actions}
> +@tab @code{<opensmtpd-local-delivery>}
> +@item
> +@tab @code{<opensmtpd-relay>}
> +@end multitable
> +
> +Additionally, each @code{<opensmtpd-interface>} and
> +@code{<opensmtpd-socket>} may use a list of
> +@code{<opensmtpd-filter>}, and/or
> +@code{<opensmtpd-filter-phase>} records to filter email/spam. Also
> +numerous records' fieldnames use @code{<opensmtpd-table>} to hold
> lists
> +or key value pairs of data.
> +
> +A simple example configuration is below:
> +
> +@lisp
> +(let ((smtp.gnu.org (opensmtpd-pki
> +                        (domain "smtp.gnu.org")
> +                        (cert "file.cert")
> +                        (key "file.key"))))
> +  (service opensmtpd-service-type
> +           (opensmtpd-configuration
> +            (listen-ons (list
> +                         (opensmtpd-interface
> +                          (pki smtp.gnu.org))
> +                         (opensmtpd-interface
> +                          (pki smtp.gnu.org)
> +                          (secure-connection "smtps"))))
> +            (matches (list
> +                      (opensmtpd-match
> +                       (action
> +                        (opensmtpd-local-delivery
> +                         (name "local-delivery"))))
> +                      (opensmtpd-match
> +                       (action
> +                        (opensmtpd-relay
> +                         (name "relay")))))))))
>  @end lisp
>  @end deffn
>  
> @@ -25433,14 +25478,1007 @@ it listens on the loopback network
> interface, and allows for mail from
>  users and daemons on the local machine, as well as permitting email
> to
>  remote servers.  Run @command{man smtpd.conf} for more information.
>  
> +<<<<<<< HEAD
You have an artifact here.
Toggle quote (423 lines)
> +@item @code{bounce} (default: @code{(list "4h")})
> +
> +@code{bounce} is a list of strings, which send warning messages to
> the envelope
> +sender when temporary delivery failures cause a message to remain in
> the
> +queue for longer than string delay. Each string delay parameter
> consists
> +of a string beginning with a positive decimal integer and a unit
> 's', 'm', 'h',
> +or 'd'. At most four delay parameters can be specified.
> +
> +@item @code{listen-ons} (default: @code{(list (opensmtpd-
> interface))})
> +
> +@code{listen-ons} is a list of @code{<opensmtpd-interface>} records.
> +This list details what interfaces and ports OpenSMTPD listens on as
> well as
> +other information.
> +
> +@item @code{listen-on-socket} (default: @code{(opensmtpd-socket)})
> +
> +Listens for incoming connections on the Unix domain socket.
> +
> +@item @code{includes} (default: @code{#f})
> +
> +@code{includes} is a list of string filenames. Each filename's
> contents is
> +additional configuration that is inserted into the top of the
> configuration
> +file.
> +
> +@item @code{matches} default:
> +
> +@lisp
> +    (list (opensmtpd-match
> +           (action (opensmtpd-local-delivery
> +                    (name "local")
> +                    (method "mbox")))
> +           (for (opensmtpd-option
> +                 (option "for local"))))
> +          (opensmtpd-match
> +           (action (opensmtpd-relay
> +                    (name "outbound")))
> +           (from (opensmtpd-option
> +                  (option "from local")))
> +           (for (opensmtpd-option
> +                 (option "for any")))))
> +@end lisp
> +
> +@code{matches} is a list of @code{<opensmtpd-match>} records, which
> +matches incoming mail and sends it to a correspending action. The
> match
> +records are evaluated sequentially, with the first match winning. If
> an
> +incoming mail does not match any match records, then it is rejected.
> +@c put this backin? @end itemize
> +
> +@c put this back in? @itemize
> +@item @code{mta-max-deferred} (default: @code{100})
> +
> +When delivery to a given host is suspended due to temporary
> failures, cache
> +at most number envelopes for that host such that they can be
> delivered as
> +soon as another delivery succeeds to that host. The default is 100.
> +
> +@item @code{queue} (default: @code{#f})
> +
> +@code{queue} expects an @code{<opensmtpd-queue>} record. With it,
> one may
> +compress and encrypt queue-ed emails as well as set the default
> expiration
> +time for temporarily undeliverable messages.
> +
> +@item @code{smtp} (default: @code{#f})
> +
> +@code{smtp} expects an @code{<opensmtpd-smtp>} record, which lets
> one
> +specifiy how large email may be along with other settings.
> +
> +@item @code{srs} (default: @code{#f})
> +
> +@code{srs} expects an @code{<opensmtpd-srs>} record, which lets one
> set
> +up SRS, the Sender Rewritting Scheme.
> +=======
>  @item @code{setgid-commands?} (default: @code{#t})
>  Make the following commands setgid to @code{smtpq} so they can be
>  executed: @command{smtpctl}, @command{sendmail}, @command{send-
> mail},
>  @command{makemap}, @command{mailq}, and @command{newaliases}.
>  @xref{Setuid Programs}, for more information on setgid programs.
> +>>>>>>> origin/master
>  @end table
>  @end deftp
>  
> +@itemize
> +@item
> +Data Type: opensmtpd-interface
> +
> +Data type representing the configuration of an
> +@code{<opensmtpd-interface>}. Listen on the fieldname
> @code{interface} for
> +incoming connections, using the same syntax as for ifconfig(8). The
> interface
> +parameter may also be an string interface group, an string IP
> address, or a
> +string domain name. Listening can optionally be restricted to a
> specific
> +address fieldname @code{family}, which can be either ``inet4'' or
> ``inet6''.
> +
> +@itemize
> +@item @code{interface} (default: ``lo'')
> +
> +The string interface to listen for incoming connections. These
> interface can
> +usually be found by the command @code{ip link}.
> +
> +@item @code{family} (default: @code{#f})
> +
> +The string IP family to use.  Valid strings are ``inet4'' or
> ``inet6''.
> +
> +@item @code{auth} (default: @code{#f})
> +
> +Support SMTPAUTH: clients may only start SMTP transactions after
> successful
> +authentication. If @code{auth} is @code{#t}, then users are
> authenticated against
> +their own normal login credentials. Alternatively @code{auth} may be
> an
> +@code{<opensmtpd-table>} whose users are authenticated against
> +their passwords.
> +
> +@item @code{auth-optional} (default: @code{#f})
> +
> +Support SMTPAUTH optionally: clients need not authenticate, but may
> do so.
> +This allows the @code{<opensmtpd-interface>} to both accept
> +incoming mail from untrusted senders and permit outgoing mail from
> +authenticated users (using @code{<opensmtpd-match>} fieldname
> +@code{auth}). It can be used in situations where it is not possible
> to listen on
> +a separate port (usually the submission port, 587) for users to
> +authenticate.
> +
> +@item @code{filters} (default: @code{#f})
> +
> +A list of one or many @code{<opensmtpd-filter>} or
> +@code{<opensmtpd-filter-phase>} records. The filters are applied
> +sequentially. These records listen and filter on connections handled
> by this
> +listener.
> +
> +@item @code{hostname} (default: @code{#f})
> +
> +Use string ``hostname'' in the greeting banner instead of the
> default server
> +name.
> +
> +@item @code{hostnames} (default: @code{#f})
> +
> +Override the server name for specific addresses. Use a
> +@code{<opensmtpd-table>} containing a mapping of string IP
> +addresses to hostnames. If the address on which the connection
> arrives
> +appears in the mapping, the associated hostname is used.
> +
> +@item @code{mask-src} (default: @code{#f})
> +
> +If @code{#t}, then omit the from part when prepending “Received”
> headers.
> +
> +@item @code{disable-dsn} (default: @code{#f})
> +
> +When @code{#t}, then disable the DSN (Delivery Status Notification)
> extension.
> +
> +@item @code{pki} (default: @code{#f})
> +
> +For secure connections, use an @code{<opensmtpd-pki>}
> +to prove a mail server's identity.
> +
> +@item @code{port} (default: @code{#f})
> +
> +Listen on the integer port instead of the default port of 25.
> +
> +@item @code{proxy-v2} (default: @code{#f})
> +
> +If @code{#t}, then support the PROXYv2 protocol, rewriting
> appropriately source
> +address received from proxy.
> +
> +@item @code{received-auth} (default: @code{#f})
> +
> +If @code{#t}, then in “Received” headers, report whether the session
> was
> +authenticated and by which local user.
> +
> +@item @code{senders} (default: @code{#f})
> +
> +Look up the authenticated user in the supplied
> +@code{<opensmtpd-table>} to find the email addresses that user is
> +allowed to submit mail as.
> +
> +@item @code{secure-connection} (default: @code{#f})
> +
> +This is a string of one of these options:
> +
> +@multitable {aaaaaaaaaaaaaaaaaaaa}
> {aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}
> +@item ``smtps''
> +@tab Support SMTPS, by default on port 465.
> +@item ``tls''
> +@tab Support STARTTLS, by default on port 25.
> +@item ``tls-require-verify''
> +@tab Like tls, but force clients to establish
> +@item
> +@tab a secure connection before being allowed to
> +@item
> +@tab start an SMTP transaction.  With the verify
> +@item
> +@tab option, clients must also provide a valid
> +@item
> +@tab certificate to establish an SMTP session.
> +@end multitable
> +
> +@item @code{tag} (default: @code{#f})
> +
> +Clients connecting to the listener are tagged with the given string
> tag.
> +@end itemize
> +
> +@item Data Type: opensmtpd-socket
> +
> +Data type representing the configuration of an
> +@code{<opensmtpd-socket>}. Listen for incoming SMTP
> +connections on the Unix domain socket @samp{/var/run/smtpd.sock}.
> This is done by
> +default, even if the directive is absent.
> +
> +@itemize
> +@item @code{filters} (default: @code{#f})
> +
> +A list of one or many @code{<opensmtpd-filter>} or
> +@code{<opensmtpd-filter-phase>} records. These filter incoming
> +connections handled by this listener.
> +
> +@item @code{mask-src} (default: @code{#f})
> +
> +If @code{#t}, then omit the from part when prepending “Received”
> headers.
> +
> +@item @code{tag} (default: @code{#f})
> +
> +Clients connecting to the listener are tagged with the given string
> tag.
> +@end itemize
> +
> +@item Data Type: opensmtpd-match
> +
> +This data type represents the configuration of an
> +@code{<opensmtpd-match>} record.
> +
> +If at least one mail envelope matches the options of one match
> record, receive
> +the incoming message, put a copy into each matching envelope, and
> atomically
> +save the envelopes to the mail spool for later processing by the
> respective
> +@code{<opensmtpd-action>} found in fieldname @code{action}.
> +
> +@itemize
> +@item @code{action} (default: @code{#f})
> +
> +If mail matches this match configuration, then do this action. Valid
> values
> +include @code{<opensmtpd-local-delivery>} or
> +@code{<opensmtpd-relay>}.
> +
> +@item @code{options} (default: @code{#f}) @code{<opensmtpd-option>}
> +The fieldname 'option' is a list of unique
> +@code{<opensmtpd-option>} records.
> +
> +Each @code{<opensmtpd-option>} record's fieldname 'option' has some
> +mutually exclusive options: there can be only one ``for'' and only
> one ``from'' option.
> +
> +@multitable {aaaaaaaaaaaaaaaaaaaaaaaaa}
> {aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}
> +@headitem for
> +@tab from
> +@item only use one of the following:
> +@tab only use one of the following:
> +@item ``for any''
> +@tab ``from any''
> +@item ``for local''
> +@tab ``from auth''
> +@item ``for domain''
> +@tab ``from local''
> +@item ``for rcpt-to''
> +@tab ``from mail-from''
> +@item
> +@tab ``from socket''
> +@item
> +@tab ``from src''
> +@end multitable
> +
> +The following matching options are supported and can all be negated
> (via not
> +#t). The options that support a table (anything surrounded with '<'
> and '>'
> +eg: <table>), also support specifying regex via (regex #t).
> +
> +@itemize
> +@item @samp{for any}
> +
> +Specify that session may address any destination.
> +
> +@item @samp{for local}
> +
> +Specify that session may address any local domain.  This is the
> default,
> +and may be omitted.
> +
> +@item @samp{for domain _domain_ | <domain>}
> +
> +Specify that session may address the string or list table domain.
> +
> +@item @samp{for rcpt-to _recipient_ | <recipient>}
> +
> +Specify that session may address the string or list table recipient.
> +
> +@item @samp{from any}
> +
> +Specify that session may originate from any source.
> +
> +@item @samp{from auth}
> +
> +Specify that session may originate from any authenticated user, no
> matter
> +the source IP address.
> +
> +@item @samp{from auth _user_ | <user>}
> +
> +Specify that session may originate from authenticated user or user
> list
> +user, no matter the source IP address.
> +
> +@item @samp{from local}
> +
> +Specify that session may only originate from a local IP address, or
> from
> +the local enqueuer.  This is the default, and may be omitted.
> +
> +@item @samp{from mail-from _sender_ | <sender>}
> +
> +Specify that session may originate from sender or table sender, no
> +matter the source IP address.
> +
> +@item @samp{from rdns}
> +
> +Specify that session may only originate from an IP address that
> resolves
> +to a reverse DNS@.
> +
> +@item @samp{from rdns _hostname_ | <hostname>}
> +
> +Specify that session may only originate from an IP address that
> resolves
> +to a reverse DNS matching string or list string hostname.
> +
> +@item @samp{from socket}
> +
> +Specify that session may only originate from the local enqueuer.
> +
> +@item @samp{from src _address_ | <address>}
> +
> +Specify that session may only originate from string or list table
> address
> +which can be a specific address or a subnet expressed in CIDR-
> notation.
> +
> +@item @samp{auth}
> +
> +Matches transactions which have been authenticated.
> +
> +@item @samp{auth _username_ | <username>}
> +
> +Matches transactions which have been authenticated for user or user
> list
> +username.
> +
> +@item @samp{helo _helo-name_ | <helo-name>}
> +
> +Specify that session's HELO / EHLO should match the string or list
> table
> +helo-name.
> +
> +@item @samp{mail-from _sender_ | <sender>}
> +
> +Specify that transactions's MAIL FROM should match the string or
> list
> +table sender.
> +
> +@item @samp{rcpt-to _recipient_ | <recipient>}
> +
> +Specify that transaction's RCPT TO should match the string or list
> table
> +recipient.
> +
> +@item @samp{tag tag}
> +Matches transactions tagged with the given tag.
> +
> +@item @samp{tls}
> +Specify that transaction should take place in a TLS channel.
> +@end itemize
> +
> +Here is a simple example:
> +@lisp
> +   
This message was truncated. Download the full message here.
J
J
jbranso wrote on 25 Oct 2022 00:18
04366ffca8f1b8648acd77ae0ddb0a80@dismail.de
October 24, 2022 2:29 PM, "Liliana Marie Prikler" <liliana.prikler@gmail.com> wrote:

Toggle quote (4 lines)
> Am Montag, dem 24.10.2022 um 13:30 -0400 schrieb Joshua Branson:
>
> Cheers

Thanks for the speedy response and quick review!

I also forgot to mention that the service is actually fairly use-able now!

<opensmtpd-filter> takes in a list of strings and gexps. With a little
work you can use s-expressions to configure dkimsigning.

And it should be possible to integrate bogofilter, but I have not figured
that out yet.....


Thanks,

Joshua
J
J
Joshua Branson wrote on 23 Dec 2022 14:52
[PATCH opensmtpd-records v3] services (opensmtpd): add opensmtpd records to enhance opensmtpd-configuration.
(address . 56046@debbugs.gnu.org)
8001f404c0e54baba71ef9c5536abc54275c4167.1671803496.git.joshua@gnucode.me
From: Joshua Branson <jbranso@dismail.de>

This is V3 of my opensmtp records configuration. Hopefully soon, I will have
this WIP service is guixrus, so more people can easily play with it.


BUT the new milestone is this, I am now actually able to use opensmtpd on my
gnucode.me account! So that is pretty awesome!

Here is a link to my server config:


The best place to find documentation for this service is here:



Openmstpd-configuration may only be configured by a config-file that
uses the smtpd.conf syntax. This patch, enables one to configure
opensmtpd by using record types.

* gnu/services/mail.scm:
(opensmtpd-table,
opensmtpd-ca,
opensmtpd-pki,
opensmtpd-action-local-delivery,
opensmtpd-maildir,
opensmtpd-mda,
opensmtpd-lmtp,
opensmtpd-relay,
opensmtpd-option,
opensmtpd-filter-phase,
opensmtpd-filter,
opensmtpd-interface,
opensmtpd-socket,
opensmtpd-match,
opensmtpd-smtp,
opensmtpd-srs,
opensmtpd-queue, and
opensmtpd-configuration): New records.

(false?, is-value-right-type, add-comma-or-string,
list-of-procedures->string, string-in-list?, my-sanitize,
opensmtpd-filter-chain?, throw-error-duplicate-option,
sanitize-list-of-options-for-match, sanitize-filters,
list-has-duplicates-or-non-filters?,
filter-phase-has-message-and-value?,
filter-phase-decision-lacks-proper-message?,
filter-phase-lacks-proper-value?,
filter-phase-has-incorrect-junk-or-bypass?,
filter-phase-junks-after-commit?,
list-of-unique-filter-or-filter-phase?, throw-error,
contains-duplicate?, list-of-type?, list-of-strings?,
list-of-unique-opensmtpd-option?,
list-of-opensmtpd-ca?,
list-of-opensmtpd-pki?,
list-of-opensmtpd-listen-on?,
list-of-unique-opensmtpd-match?, list-of-strings->string,
assoc-list? assoc-list, variable->string,
tables-data-are-assoc-list?,
tables-data-are-a-list-of-strings?,
table-data-are-a-nested-list-of-strings?,
assoc-list->string,
opensmtpd-table->string,
opensmtpd-listen-on->string,
opensmtpd-listen-on-socket->string,
opensmtpd-action-relay->string,
opensmtpd-lmtp->string,
opensmtpd-mda->string,
opensmtpd-maildir->string,
opensmtpd-action-local-delivery->string,
opensmtpd-action->string, opensmtpd-option->string,
opensmtpd-match->string,
opensmtpd-ca->string, opensmtpd-pki->string,
generate-filter-chain-name, opensmtpd-filter-chain->string,
opensmtpd-filter-phase->string, opensmtpd-filters->string,
opensmtpd-listen->string,
opensmtpd-srs->string,
opensmtpd-smtp->string,
opensmtpd-queue->string, get-opensmtpd-actions,
get-opensmtpd-pkis, get-opensmtpd-filters, flatten,
get-opensmtpd-tables, opensmtpd-fieldname->string,
list-of-records->string, opensmtpd->mixed-text-file): New
procedures.

* gnu/tests/mail.scm : new tests for various opensmtpd records.

* doc/guix.texi (OpenSMTPD Service): Added documentation for the
new records for opensmtpd.
---
doc/guix.texi | 1065 ++++++++++++++++-
gnu/services/mail.scm | 2560 ++++++++++++++++++++++++++++++++++++++++-
gnu/tests/mail.scm | 713 ++++++++++++
3 files changed, 4310 insertions(+), 28 deletions(-)

Toggle diff (454 lines)
diff --git a/doc/guix.texi b/doc/guix.texi
index 535c8cdfc3..879a2ad233 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -25407,16 +25407,66 @@ could instantiate a dovecot service like this:
@end lisp
@subsubheading OpenSMTPD Service
+@cindex opensmtpd
@deffn {Scheme Variable} opensmtpd-service-type
-This is the type of the @uref{https://www.opensmtpd.org, OpenSMTPD}
-service, whose value should be an @code{opensmtpd-configuration} object
-as in this example:
+OpenSMTPD is an easy-to-use mail transfer agent (MTA). OpenSMTPD
+@strong{listens} for incoming mail and @strong{matches} the mail to
+@strong{actions}. The following records represent those stages:
-@lisp
-(service opensmtpd-service-type
- (opensmtpd-configuration
- (config-file (local-file "./my-smtpd.conf"))))
+@multitable {aaaaaaaaa} {aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}
+@item @strong{listens}
+@tab @code{<opensmtpd-interface>}
+@item
+@tab @code{<opensmtpd-socket>}
+@item
+@tab
+@item @strong{matches}
+@tab @code{<opensmtpd-match>}
+@item
+@tab
+@item @strong{actions}
+@tab @code{<opensmtpd-local-delivery>}
+@item
+@tab @code{<opensmtpd-relay>}
+@end multitable
+
+Additionally, each @code{<opensmtpd-interface>} and
+@code{<opensmtpd-socket>} may use a list of @code{<opensmtpd-filter>},
+and/or @code{<opensmtpd-filter-phase>} records to filter
+email/spam. Also numerous records' fieldnames use
+@code{<opensmtpd-table>} records to hold lists or key value pairs of
+data. Be sure to read the @code{<opensmtpd-table>} section to learn the
+differance between a @code{mapping table} and a @code{list table}.
+
+Finally, both @code{<opensmtpd-match>} and
+@code{<opensmtpd-filter-phase>} use @code{<opensmtpd-option>} to
+configure various options.
+
+A simple example opensmtpd configuration is below:
+
+@lisp
+(let ((smtp.gnu.org (opensmtpd-pki
+ (domain "smtp.gnu.org")
+ (cert "file.cert")
+ (key "file.key"))))
+ (service opensmtpd-service-type
+ (opensmtpd-configuration
+ (interfaces (list
+ (opensmtpd-interface
+ (pki smtp.gnu.org))
+ (opensmtpd-interface
+ (pki smtp.gnu.org)
+ (secure-connection "smtps"))))
+ (matches (list
+ (opensmtpd-match
+ (action
+ (opensmtpd-local-delivery
+ (name "local-delivery"))))
+ (opensmtpd-match
+ (action
+ (opensmtpd-relay
+ (name "relay")))))))))
@end lisp
@end deffn
@@ -25425,7 +25475,7 @@ Data type representing the configuration of opensmtpd.
@table @asis
@item @code{package} (default: @var{opensmtpd})
-Package object of the OpenSMTPD SMTP server.
+Package object of the OpenSMTPD server.
@item @code{config-file} (default: @code{%default-opensmtpd-config-file})
File-like object of the OpenSMTPD configuration file to use. By default
@@ -25433,14 +25483,1013 @@ it listens on the loopback network interface, and allows for mail from
users and daemons on the local machine, as well as permitting email to
remote servers. Run @command{man smtpd.conf} for more information.
+@item @code{bounce} (default: @code{(list "4h")})
+@code{bounce} is a list of strings, which send warning messages to the
+envelope sender when temporary delivery failures cause a message to
+remain in the queue for longer than a specified delay. Each delay option
+is a string parameter beginning with a positive decimal integer and a
+unit, which can be 's', 'm', 'h', or 'd'. At most four delay parameters
+can be specified.
+
+@item @code{interfaces} default:
+@lisp
+(list
+ (opensmtpd-interface
+ (interface "lo")
+ (port 25)))
+@end lisp
+@code{interfaces} is a list of @code{<opensmtpd-interface>} records.
+This list details what interfaces and ports OpenSMTPD listens on as well as
+other options.
+
+@item @code{socket} (default: @code{(opensmtpd-socket)})
+Listens for incoming connections on the Unix domain socket.
+
+@item @code{includes} (default: @code{#f})
+@code{includes} is a list of string filenames. Each filename's contents is
+additional configuration that is inserted into the top of the configuration
+file. Run @code{man smtpd.conf} for more information.
+
+@item @code{matches} default:
+@lisp
+(list (opensmtpd-match
+ (action (opensmtpd-local-delivery
+ (name "local")
+ (method "mbox")
+ (options
+ (list
+ (opensmtpd-option
+ (option "for local")))))))
+ (opensmtpd-match
+ (action (opensmtpd-relay
+ (name "outbound")))
+ (options
+ (list
+ (opensmtpd-option
+ (option "from local"))
+ (opensmtpd-option
+ (option "for any"))))))
+@end lisp
+@code{matches} is a list of @code{<opensmtpd-match>} records, which
+matches incoming mail and sends it to a correspending action. The match
+records are evaluated sequentially, with the first match winning.
+Therefore @emph{the order that you arrange your matches is important}.
+It's a good idea to put specific matches first and an all emcompassing
+match (like @code{(option "for any")}) @strong{last}. If an incoming
+mail does not match any match records, then it is rejected.
+
+@item @code{mta-max-deferred} (default: @code{100})
+When delivery to a given host is suspended due to temporary failures, cache
+at most number envelopes for that host such that they can be delivered as
+soon as another delivery succeeds to that host. The default is 100.
+
+@item @code{queue} (default: @code{#f})
+@code{queue} expects an @code{<opensmtpd-queue>} record. With it, one may
+compress and encrypt queue-ed emails as well as set the default expiration
+time for temporarily undeliverable messages.
+
+@item @code{smtp} (default: @code{#f})
+@code{smtp} expects an @code{<opensmtpd-smtp>} record, which lets one
+specifiy how large email may be along with other settings.
+
+@item @code{srs} (default: @code{#f})
+@code{srs} expects an @code{<opensmtpd-srs>} record, which lets one set
+up SRS, the Sender Rewritting Scheme.
+
@item @code{setgid-commands?} (default: @code{#t})
Make the following commands setgid to @code{smtpq} so they can be
executed: @command{smtpctl}, @command{sendmail}, @command{send-mail},
@command{makemap}, @command{mailq}, and @command{newaliases}.
@xref{Setuid Programs}, for more information on setgid programs.
+
@end table
@end deftp
+@itemize
+@item Data Type: opensmtpd-interface
+Data type representing the configuration of an
+@code{<opensmtpd-interface>}. It listens on the fieldname
+@code{interface} for incoming connections, using the same syntax as
+@code{ifconfig}. The interface parameter may also be an string interface
+group, an string IP address, or a string domain name. Listening can
+optionally be restricted to a specific address via the fieldname
+@code{family}, which can be either @code{"inet4"} or @code{"inet6"}.
+
+@itemize
+@item @code{interface} (default: @code{"lo"})
+
+The string interface to listen for incoming connections. This string
+may be an interface group, an IP address, or a domain name. These
+interfaces can usually be found by the command @code{ip link}.
+
+@item @code{family} (default: @code{#f})
+
+Only listen on a specific address family. Valid strings are
+@code{"inet4"} or @code{"inet6"}, which will only listen on IPv4 or IPv6
+respectfully. If @code{(family #f)}, then opensmtpd will listen on both
+IPv4 and IPv6.
+
+@item @code{auth} (default: @code{#f})
+Support SMTPAUTH: clients may only start SMTP transactions after
+successful authentication. If @code{auth} is @code{#t}, then users are
+authenticated against their own normal login credentials. Alternatively
+@code{auth} may be a @code{mapping table} that maps usernames to
+encrypted passwords. The password can be encrypted via the
+@code{smtpctl} @code{encrypt} subcommand.
+
+@item @code{auth-optional} (default: @code{#f})
+Support SMTPAUTH optionally: clients need not authenticate, but may do
+so. This allows the @code{<opensmtpd-interface>} to both accept
+incoming mail from untrusted senders and permit outgoing mail from
+authenticated users. It can be used in situations where it is not
+possible to listen on a separate port (usually the submission port, 587)
+for users to authenticate. This option also accepts a @code{mapping
+table} that maps usernames to encrypted passwords.
+
+@item @code{filters} (default: @code{#f})
+A list of one or many @code{<opensmtpd-filter>} or
+@code{<opensmtpd-filter-phase>} records. The filters are applied
+sequentially. These records listen and filter on connections handled by this
+listener.
+
+@item @code{hostname} (default: @code{#f})
+Change the default server name in the greeting banner instead of the
+default one.
+
+@item @code{hostnames} (default: @code{#f})
+Override the server name for specific addresses. Use a @code{mapping
+table} that maps string IP addresses to string hostnames. If the address
+on which the connection arrives appears in the mapping, the associated
+hostname is used.
+
+@item @code{mask-src} (default: @code{#f})
+If @code{#t}, then omit the from part when prepending “Received” headers.
+
+@item @code{disable-dsn} (default: @code{#f})
+When @code{#t}, then disable the DSN (Delivery Status Notification) extension.
+
+@item @code{pki} (default: @code{#f})
+For secure connections, use an @code{<opensmtpd-pki>} record to prove a
+mail server's identity.
+
+@item @code{port} (default: @code{25})
+Listen on the integer port instead of the default port of 25.
+
+@item @code{proxy-v2} (default: @code{#f})
+If @code{#t}, then support the PROXYv2 protocol, rewriting appropriately source
+address received from proxy.
+
+@item @code{received-auth} (default: @code{#f})
+If @code{#t}, then in “Received” headers, report whether the session was
+authenticated and by which local user.
+
+@item @code{senders} (default: @code{#f})
+Look up the authenticated user in the supplied @code{mapping table} to
+find the email addresses that user is allowed to submit mail as.
+
+@item @code{masquerade} (default: @code{#f})
+@code{masquerade}, is used in conjunction with @code{senders}. If
+@code{#t}, then the From header is rewritten to match the sender
+provided in the SMTP session. If @code{senders} is @code{#false}, then
+@code{masquerade} cannot be @code{#t}.
+
+@item @code{secure-connection} (default: @code{#f})
+This is a string of one of these options:
+
+@multitable {aaaaaaaaaaaaaaaaaaaa} {aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}
+@item @code{"smtps"}
+@tab Support SMTPS, by default on port 465.
+@item @code{"tls"}
+@tab Support STARTTLS, by default on port 25.
+@item @code{"tls-require"}
+@tab Like @code{"tls"}, but force clients to
+@item
+@tab establish a secure connection before being
+@item
+@tab allowed to start an SMTP transaction.
+@item @code{"tls-require-verify"}
+@tab Like @code{"tls-require"}, but clients must
+@item
+@tab also provide a valid certificate
+@item
+@tab to establish an SMTP session.
+@end multitable
+
+@item @code{tag} (default: @code{#f})
+Clients connecting to the listener are tagged with the given string tag.
+@end itemize
+
+@item Data Type: opensmtpd-socket
+Data type representing the configuration of an
+@code{<opensmtpd-socket>}. Listen for incoming SMTP connections on the
+Unix domain socket @samp{/var/run/smtpd.sock}. This is done by default,
+even if the record is absent.
+
+@itemize
+@item @code{filters} (default: @code{#f})
+A list of one or many @code{<opensmtpd-filter>} or
+@code{<opensmtpd-filter-phase>} records. These filter incoming
+connections handled by this listener.
+
+@item @code{mask-src} (default: @code{#f})
+If @code{#t}, then omit the from part when prepending “Received” headers.
+
+@item @code{tag} (default: @code{#f})
+Clients connecting to the listener are tagged with the given string tag.
+@end itemize
+
+@item Data Type: opensmtpd-match
+@cindex opensmtpd-match
+This data type represents the configuration of an
+@code{<opensmtpd-match>} record.
+
+If at least one mail envelope matches the options of one match record,
+receive the incoming message, put a copy into each matching envelope,
+and atomically save the envelopes to the mail spool for later processing
+by the respective @code{<opensmtpd-action>} found in fieldname
+@code{action}. Here is an example @code{opensmtpd-match}
+record.
+
+@lisp
+(opensmtpd-match
+ (action (opensmtpd-local-delivery
+ (name "receive")
+ (method (opensmtpd-maildir
+ (pathname "/home/%@{rcpt.user@}/Maildir")
+ (junk #t)))
+ (virtual (opensmtpd-table
+ (name "virt")
+ (data '(("carmen" . "carmen@@gnu.org")))))))
+ (options (list (opensmtpd-option
+ (option "from any"))
+ (opensmtpd-option
+ (option "for domain")
+ (data (opensmtpd-table
+ (name "domain-table")
+ (data (list "gnu.org" "fsf.org"))))))))
+@end lisp
+
+@itemize
+@item @code{action} (default: @code{#f})
+
+If mail matches this match configuration, then do this action. Valid values
+include @code{<opensmtpd-local-delivery>} or
+@code{<opensmtpd-relay>}.
+
+@item @code{options} (default: @code{#f})
+The fieldname @code{option} is a list of unique
+@code{<opensmtpd-option>} records.
+
+There are some mutually exclusive options: there can be only one ``for''
+and only one ``from'' option.
+
+@multitable {aaaaaaaaaaaaaaaaaaaaaaaaa} {aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}
+@headitem for
+@tab from
+@item only use one of the following:
+@tab only use one of the following:
+@item @code{"for any"}
+@tab @code{"from any"}
+@item @code{"for local"}
+@tab @code{"from auth"}
+@item @code{"for domain"}
+@tab @code{"from local"}
+@item @code{"for rcpt-to"}
+@tab @code{"from mail-from"}
+@item
+@tab @code{"from socket"}
+@item
+@tab @code{"from src"}
+@end multitable
+
+Additionally, some options require additional data via
+@code{<opensmtpd-option>}'s fieldname @code{data}. The following list
+will explain the below syntax.
+
+@itemize
+@item @code{"for any"}
+This option only requires fieldname @code{option} to have the string
+@code{"for any"}:
+
+@lisp
+ (opensmtpd-option
+ (option "for any"))
+@end lisp
+
+@item @code{"tag"} _tag_
+This option only requires fieldname @code{option} to have the string
+@code{"tag"} with a string in fieldname @code{data}:
+
+@lisp
+ (opensmtpd-option
+ (option "tag")
+ (data "this-tag"))
+@end lisp
+
+@item @code{"for rcpt"} _domain_ | <list table>
+This option requires fieldname @code{data} to have a string domain or
+@code{list table}:
+
+@lisp
+ (opensmtpd-option
+ (option "for rcpt")
+ (data "gnu.org"))
+@end lisp
+
+OR
+
+@lisp
+ (opensmtpd-option
+ (option "for rcpt")
+ (data (list "gnu.org" "fsf.org")))
+@end lisp
+@end itemize
+
+The following matching options are supported and can all be negated (via not
+#t). The options that support a table (anything surrounded with '<' and '>'
+eg: <table>), also support specifying regex via (regex #t).
+
+@itemize
+@item @code{"for any"}
+Specify that session may address any destination.
+
+@item @code{"for local"}
+Specify that session may address any local domain. This is the default,
+and may be omitted.
+
+@item @code{"for domain"} _domain_ | <domain>
+Specify that session may address the string _domain_ or
+@code{list table} <domain>.
+
+@item @code{"for rcpt-to"} _recipient_ | <recipient>
+Specify that session may address the string _recipient_ or list table
+<recipient>.
+
+@item @code{"from any"}
+Specify that session may originate from any source.
+
+@item @code{"from auth"}
+Specify that session may originate from any authenticated user, no matter
+the source IP address.
+
+@item @code{"from auth"} _user_ | <user>
+Specify that the session may originate from authenticated _user_ or
+@code{list table} <user>, no matter the source IP address.
+
+@item @code{"from local"}
+Specify that session may only originate from a local IP address, or from
+the local enqueuer. This is the default, and may be omitted.
+
+@item @code{"from mail-from"} _sender_ | <sender>
+Specify that session may originate from _sender_ or @code{list table}
+<sender>, no matter the source IP address.
+
+@item @code{"from rdns"}
+Specify that session may
This message was truncated. Download the full message here.
J
J
Joshua Branson wrote on 23 Dec 2022 17:39
[PATCH opensmtpd-records v4 fixing charset=y error] services (opensmtpd): add opensmtpd records to enhance opensmtpd-configuration.
(address . 56046@debbugs.gnu.org)(name . Joshua Branson)(address . jbranso@dismail.de)
8001f404c0e54baba71ef9c5536abc54275c4167.1671813513.git.jbranso@dismail.de
Whoops the last sent patch had some charset=y errors. Hopefully this is better.

This is V3 of my opensmtp records configuration. Hopefully soon, I will have
this WIP service is guixrus, so more people can easily play with it.


BUT the new milestone is this, I am now actually able to use opensmtpd on my
gnucode.me account! So that is pretty awesome!

Here is a link to my server config:


The best place to find documentation for this service is here:



Openmstpd-configuration may only be configured by a config-file that
uses the smtpd.conf syntax. This patch, enables one to configure
opensmtpd by using record types.

* gnu/services/mail.scm:
(opensmtpd-table,
opensmtpd-ca,
opensmtpd-pki,
opensmtpd-action-local-delivery,
opensmtpd-maildir,
opensmtpd-mda,
opensmtpd-lmtp,
opensmtpd-relay,
opensmtpd-option,
opensmtpd-filter-phase,
opensmtpd-filter,
opensmtpd-interface,
opensmtpd-socket,
opensmtpd-match,
opensmtpd-smtp,
opensmtpd-srs,
opensmtpd-queue, and
opensmtpd-configuration): New records.

(false?, is-value-right-type, add-comma-or-string,
list-of-procedures->string, string-in-list?, my-sanitize,
opensmtpd-filter-chain?, throw-error-duplicate-option,
sanitize-list-of-options-for-match, sanitize-filters,
list-has-duplicates-or-non-filters?,
filter-phase-has-message-and-value?,
filter-phase-decision-lacks-proper-message?,
filter-phase-lacks-proper-value?,
filter-phase-has-incorrect-junk-or-bypass?,
filter-phase-junks-after-commit?,
list-of-unique-filter-or-filter-phase?, throw-error,
contains-duplicate?, list-of-type?, list-of-strings?,
list-of-unique-opensmtpd-option?,
list-of-opensmtpd-ca?,
list-of-opensmtpd-pki?,
list-of-opensmtpd-listen-on?,
list-of-unique-opensmtpd-match?, list-of-strings->string,
assoc-list? assoc-list, variable->string,
tables-data-are-assoc-list?,
tables-data-are-a-list-of-strings?,
table-data-are-a-nested-list-of-strings?,
assoc-list->string,
opensmtpd-table->string,
opensmtpd-listen-on->string,
opensmtpd-listen-on-socket->string,
opensmtpd-action-relay->string,
opensmtpd-lmtp->string,
opensmtpd-mda->string,
opensmtpd-maildir->string,
opensmtpd-action-local-delivery->string,
opensmtpd-action->string, opensmtpd-option->string,
opensmtpd-match->string,
opensmtpd-ca->string, opensmtpd-pki->string,
generate-filter-chain-name, opensmtpd-filter-chain->string,
opensmtpd-filter-phase->string, opensmtpd-filters->string,
opensmtpd-listen->string,
opensmtpd-srs->string,
opensmtpd-smtp->string,
opensmtpd-queue->string, get-opensmtpd-actions,
get-opensmtpd-pkis, get-opensmtpd-filters, flatten,
get-opensmtpd-tables, opensmtpd-fieldname->string,
list-of-records->string, opensmtpd->mixed-text-file): New
procedures.

* gnu/tests/mail.scm : new tests for various opensmtpd records.

* doc/guix.texi (OpenSMTPD Service): Added documentation for the
new records for opensmtpd.
---
doc/guix.texi | 1065 ++++++++++++++++-
gnu/services/mail.scm | 2560 ++++++++++++++++++++++++++++++++++++++++-
gnu/tests/mail.scm | 713 ++++++++++++
3 files changed, 4310 insertions(+), 28 deletions(-)

Toggle diff (453 lines)
diff --git a/doc/guix.texi b/doc/guix.texi
index 535c8cdfc3..879a2ad233 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -25407,16 +25407,66 @@ could instantiate a dovecot service like this:
@end lisp
@subsubheading OpenSMTPD Service
+@cindex opensmtpd
@deffn {Scheme Variable} opensmtpd-service-type
-This is the type of the @uref{https://www.opensmtpd.org, OpenSMTPD}
-service, whose value should be an @code{opensmtpd-configuration} object
-as in this example:
+OpenSMTPD is an easy-to-use mail transfer agent (MTA). OpenSMTPD
+@strong{listens} for incoming mail and @strong{matches} the mail to
+@strong{actions}. The following records represent those stages:
-@lisp
-(service opensmtpd-service-type
- (opensmtpd-configuration
- (config-file (local-file "./my-smtpd.conf"))))
+@multitable {aaaaaaaaa} {aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}
+@item @strong{listens}
+@tab @code{<opensmtpd-interface>}
+@item
+@tab @code{<opensmtpd-socket>}
+@item
+@tab
+@item @strong{matches}
+@tab @code{<opensmtpd-match>}
+@item
+@tab
+@item @strong{actions}
+@tab @code{<opensmtpd-local-delivery>}
+@item
+@tab @code{<opensmtpd-relay>}
+@end multitable
+
+Additionally, each @code{<opensmtpd-interface>} and
+@code{<opensmtpd-socket>} may use a list of @code{<opensmtpd-filter>},
+and/or @code{<opensmtpd-filter-phase>} records to filter
+email/spam. Also numerous records' fieldnames use
+@code{<opensmtpd-table>} records to hold lists or key value pairs of
+data. Be sure to read the @code{<opensmtpd-table>} section to learn the
+differance between a @code{mapping table} and a @code{list table}.
+
+Finally, both @code{<opensmtpd-match>} and
+@code{<opensmtpd-filter-phase>} use @code{<opensmtpd-option>} to
+configure various options.
+
+A simple example opensmtpd configuration is below:
+
+@lisp
+(let ((smtp.gnu.org (opensmtpd-pki
+ (domain "smtp.gnu.org")
+ (cert "file.cert")
+ (key "file.key"))))
+ (service opensmtpd-service-type
+ (opensmtpd-configuration
+ (interfaces (list
+ (opensmtpd-interface
+ (pki smtp.gnu.org))
+ (opensmtpd-interface
+ (pki smtp.gnu.org)
+ (secure-connection "smtps"))))
+ (matches (list
+ (opensmtpd-match
+ (action
+ (opensmtpd-local-delivery
+ (name "local-delivery"))))
+ (opensmtpd-match
+ (action
+ (opensmtpd-relay
+ (name "relay")))))))))
@end lisp
@end deffn
@@ -25425,7 +25475,7 @@ Data type representing the configuration of opensmtpd.
@table @asis
@item @code{package} (default: @var{opensmtpd})
-Package object of the OpenSMTPD SMTP server.
+Package object of the OpenSMTPD server.
@item @code{config-file} (default: @code{%default-opensmtpd-config-file})
File-like object of the OpenSMTPD configuration file to use. By default
@@ -25433,14 +25483,1013 @@ it listens on the loopback network interface, and allows for mail from
users and daemons on the local machine, as well as permitting email to
remote servers. Run @command{man smtpd.conf} for more information.
+@item @code{bounce} (default: @code{(list "4h")})
+@code{bounce} is a list of strings, which send warning messages to the
+envelope sender when temporary delivery failures cause a message to
+remain in the queue for longer than a specified delay. Each delay option
+is a string parameter beginning with a positive decimal integer and a
+unit, which can be 's', 'm', 'h', or 'd'. At most four delay parameters
+can be specified.
+
+@item @code{interfaces} default:
+@lisp
+(list
+ (opensmtpd-interface
+ (interface "lo")
+ (port 25)))
+@end lisp
+@code{interfaces} is a list of @code{<opensmtpd-interface>} records.
+This list details what interfaces and ports OpenSMTPD listens on as well as
+other options.
+
+@item @code{socket} (default: @code{(opensmtpd-socket)})
+Listens for incoming connections on the Unix domain socket.
+
+@item @code{includes} (default: @code{#f})
+@code{includes} is a list of string filenames. Each filename's contents is
+additional configuration that is inserted into the top of the configuration
+file. Run @code{man smtpd.conf} for more information.
+
+@item @code{matches} default:
+@lisp
+(list (opensmtpd-match
+ (action (opensmtpd-local-delivery
+ (name "local")
+ (method "mbox")
+ (options
+ (list
+ (opensmtpd-option
+ (option "for local")))))))
+ (opensmtpd-match
+ (action (opensmtpd-relay
+ (name "outbound")))
+ (options
+ (list
+ (opensmtpd-option
+ (option "from local"))
+ (opensmtpd-option
+ (option "for any"))))))
+@end lisp
+@code{matches} is a list of @code{<opensmtpd-match>} records, which
+matches incoming mail and sends it to a correspending action. The match
+records are evaluated sequentially, with the first match winning.
+Therefore @emph{the order that you arrange your matches is important}.
+It's a good idea to put specific matches first and an all emcompassing
+match (like @code{(option "for any")}) @strong{last}. If an incoming
+mail does not match any match records, then it is rejected.
+
+@item @code{mta-max-deferred} (default: @code{100})
+When delivery to a given host is suspended due to temporary failures, cache
+at most number envelopes for that host such that they can be delivered as
+soon as another delivery succeeds to that host. The default is 100.
+
+@item @code{queue} (default: @code{#f})
+@code{queue} expects an @code{<opensmtpd-queue>} record. With it, one may
+compress and encrypt queue-ed emails as well as set the default expiration
+time for temporarily undeliverable messages.
+
+@item @code{smtp} (default: @code{#f})
+@code{smtp} expects an @code{<opensmtpd-smtp>} record, which lets one
+specifiy how large email may be along with other settings.
+
+@item @code{srs} (default: @code{#f})
+@code{srs} expects an @code{<opensmtpd-srs>} record, which lets one set
+up SRS, the Sender Rewritting Scheme.
+
@item @code{setgid-commands?} (default: @code{#t})
Make the following commands setgid to @code{smtpq} so they can be
executed: @command{smtpctl}, @command{sendmail}, @command{send-mail},
@command{makemap}, @command{mailq}, and @command{newaliases}.
@xref{Setuid Programs}, for more information on setgid programs.
+
@end table
@end deftp
+@itemize
+@item Data Type: opensmtpd-interface
+Data type representing the configuration of an
+@code{<opensmtpd-interface>}. It listens on the fieldname
+@code{interface} for incoming connections, using the same syntax as
+@code{ifconfig}. The interface parameter may also be an string interface
+group, an string IP address, or a string domain name. Listening can
+optionally be restricted to a specific address via the fieldname
+@code{family}, which can be either @code{"inet4"} or @code{"inet6"}.
+
+@itemize
+@item @code{interface} (default: @code{"lo"})
+
+The string interface to listen for incoming connections. This string
+may be an interface group, an IP address, or a domain name. These
+interfaces can usually be found by the command @code{ip link}.
+
+@item @code{family} (default: @code{#f})
+
+Only listen on a specific address family. Valid strings are
+@code{"inet4"} or @code{"inet6"}, which will only listen on IPv4 or IPv6
+respectfully. If @code{(family #f)}, then opensmtpd will listen on both
+IPv4 and IPv6.
+
+@item @code{auth} (default: @code{#f})
+Support SMTPAUTH: clients may only start SMTP transactions after
+successful authentication. If @code{auth} is @code{#t}, then users are
+authenticated against their own normal login credentials. Alternatively
+@code{auth} may be a @code{mapping table} that maps usernames to
+encrypted passwords. The password can be encrypted via the
+@code{smtpctl} @code{encrypt} subcommand.
+
+@item @code{auth-optional} (default: @code{#f})
+Support SMTPAUTH optionally: clients need not authenticate, but may do
+so. This allows the @code{<opensmtpd-interface>} to both accept
+incoming mail from untrusted senders and permit outgoing mail from
+authenticated users. It can be used in situations where it is not
+possible to listen on a separate port (usually the submission port, 587)
+for users to authenticate. This option also accepts a @code{mapping
+table} that maps usernames to encrypted passwords.
+
+@item @code{filters} (default: @code{#f})
+A list of one or many @code{<opensmtpd-filter>} or
+@code{<opensmtpd-filter-phase>} records. The filters are applied
+sequentially. These records listen and filter on connections handled by this
+listener.
+
+@item @code{hostname} (default: @code{#f})
+Change the default server name in the greeting banner instead of the
+default one.
+
+@item @code{hostnames} (default: @code{#f})
+Override the server name for specific addresses. Use a @code{mapping
+table} that maps string IP addresses to string hostnames. If the address
+on which the connection arrives appears in the mapping, the associated
+hostname is used.
+
+@item @code{mask-src} (default: @code{#f})
+If @code{#t}, then omit the from part when prepending “Received” headers.
+
+@item @code{disable-dsn} (default: @code{#f})
+When @code{#t}, then disable the DSN (Delivery Status Notification) extension.
+
+@item @code{pki} (default: @code{#f})
+For secure connections, use an @code{<opensmtpd-pki>} record to prove a
+mail server's identity.
+
+@item @code{port} (default: @code{25})
+Listen on the integer port instead of the default port of 25.
+
+@item @code{proxy-v2} (default: @code{#f})
+If @code{#t}, then support the PROXYv2 protocol, rewriting appropriately source
+address received from proxy.
+
+@item @code{received-auth} (default: @code{#f})
+If @code{#t}, then in “Received” headers, report whether the session was
+authenticated and by which local user.
+
+@item @code{senders} (default: @code{#f})
+Look up the authenticated user in the supplied @code{mapping table} to
+find the email addresses that user is allowed to submit mail as.
+
+@item @code{masquerade} (default: @code{#f})
+@code{masquerade}, is used in conjunction with @code{senders}. If
+@code{#t}, then the From header is rewritten to match the sender
+provided in the SMTP session. If @code{senders} is @code{#false}, then
+@code{masquerade} cannot be @code{#t}.
+
+@item @code{secure-connection} (default: @code{#f})
+This is a string of one of these options:
+
+@multitable {aaaaaaaaaaaaaaaaaaaa} {aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}
+@item @code{"smtps"}
+@tab Support SMTPS, by default on port 465.
+@item @code{"tls"}
+@tab Support STARTTLS, by default on port 25.
+@item @code{"tls-require"}
+@tab Like @code{"tls"}, but force clients to
+@item
+@tab establish a secure connection before being
+@item
+@tab allowed to start an SMTP transaction.
+@item @code{"tls-require-verify"}
+@tab Like @code{"tls-require"}, but clients must
+@item
+@tab also provide a valid certificate
+@item
+@tab to establish an SMTP session.
+@end multitable
+
+@item @code{tag} (default: @code{#f})
+Clients connecting to the listener are tagged with the given string tag.
+@end itemize
+
+@item Data Type: opensmtpd-socket
+Data type representing the configuration of an
+@code{<opensmtpd-socket>}. Listen for incoming SMTP connections on the
+Unix domain socket @samp{/var/run/smtpd.sock}. This is done by default,
+even if the record is absent.
+
+@itemize
+@item @code{filters} (default: @code{#f})
+A list of one or many @code{<opensmtpd-filter>} or
+@code{<opensmtpd-filter-phase>} records. These filter incoming
+connections handled by this listener.
+
+@item @code{mask-src} (default: @code{#f})
+If @code{#t}, then omit the from part when prepending “Received” headers.
+
+@item @code{tag} (default: @code{#f})
+Clients connecting to the listener are tagged with the given string tag.
+@end itemize
+
+@item Data Type: opensmtpd-match
+@cindex opensmtpd-match
+This data type represents the configuration of an
+@code{<opensmtpd-match>} record.
+
+If at least one mail envelope matches the options of one match record,
+receive the incoming message, put a copy into each matching envelope,
+and atomically save the envelopes to the mail spool for later processing
+by the respective @code{<opensmtpd-action>} found in fieldname
+@code{action}. Here is an example @code{opensmtpd-match}
+record.
+
+@lisp
+(opensmtpd-match
+ (action (opensmtpd-local-delivery
+ (name "receive")
+ (method (opensmtpd-maildir
+ (pathname "/home/%@{rcpt.user@}/Maildir")
+ (junk #t)))
+ (virtual (opensmtpd-table
+ (name "virt")
+ (data '(("carmen" . "carmen@@gnu.org")))))))
+ (options (list (opensmtpd-option
+ (option "from any"))
+ (opensmtpd-option
+ (option "for domain")
+ (data (opensmtpd-table
+ (name "domain-table")
+ (data (list "gnu.org" "fsf.org"))))))))
+@end lisp
+
+@itemize
+@item @code{action} (default: @code{#f})
+
+If mail matches this match configuration, then do this action. Valid values
+include @code{<opensmtpd-local-delivery>} or
+@code{<opensmtpd-relay>}.
+
+@item @code{options} (default: @code{#f})
+The fieldname @code{option} is a list of unique
+@code{<opensmtpd-option>} records.
+
+There are some mutually exclusive options: there can be only one ``for''
+and only one ``from'' option.
+
+@multitable {aaaaaaaaaaaaaaaaaaaaaaaaa} {aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}
+@headitem for
+@tab from
+@item only use one of the following:
+@tab only use one of the following:
+@item @code{"for any"}
+@tab @code{"from any"}
+@item @code{"for local"}
+@tab @code{"from auth"}
+@item @code{"for domain"}
+@tab @code{"from local"}
+@item @code{"for rcpt-to"}
+@tab @code{"from mail-from"}
+@item
+@tab @code{"from socket"}
+@item
+@tab @code{"from src"}
+@end multitable
+
+Additionally, some options require additional data via
+@code{<opensmtpd-option>}'s fieldname @code{data}. The following list
+will explain the below syntax.
+
+@itemize
+@item @code{"for any"}
+This option only requires fieldname @code{option} to have the string
+@code{"for any"}:
+
+@lisp
+ (opensmtpd-option
+ (option "for any"))
+@end lisp
+
+@item @code{"tag"} _tag_
+This option only requires fieldname @code{option} to have the string
+@code{"tag"} with a string in fieldname @code{data}:
+
+@lisp
+ (opensmtpd-option
+ (option "tag")
+ (data "this-tag"))
+@end lisp
+
+@item @code{"for rcpt"} _domain_ | <list table>
+This option requires fieldname @code{data} to have a string domain or
+@code{list table}:
+
+@lisp
+ (opensmtpd-option
+ (option "for rcpt")
+ (data "gnu.org"))
+@end lisp
+
+OR
+
+@lisp
+ (opensmtpd-option
+ (option "for rcpt")
+ (data (list "gnu.org" "fsf.org")))
+@end lisp
+@end itemize
+
+The following matching options are supported and can all be negated (via not
+#t). The options that support a table (anything surrounded with '<' and '>'
+eg: <table>), also support specifying regex via (regex #t).
+
+@itemize
+@item @code{"for any"}
+Specify that session may address any destination.
+
+@item @code{"for local"}
+Specify that session may address any local domain. This is the default,
+and may be omitted.
+
+@item @code{"for domain"} _domain_ | <domain>
+Specify that session may address the string _domain_ or
+@code{list table} <domain>.
+
+@item @code{"for rcpt-to"} _recipient_ | <recipient>
+Specify that session may address the string _recipient_ or list table
+<recipient>.
+
+@item @code{"from any"}
+Specify that session may originate from any source.
+
+@item @code{"from auth"}
+Specify that session may originate from any authenticated user, no matter
+the source IP address.
+
+@item @code{"from auth"} _user_ | <user>
+Specify that the session may originate from authenticated _user_ or
+@code{list table} <user>, no matter the source IP address.
+
+@item @code{"from local"}
+Specify that session may only originate from a local IP address, or from
+the local enqueuer. This is the default, and may be omitted.
+
+@item @code{"from mail-from"} _sender_ | <sender>
+Specify that session may originate from _sender_ or @code{list table}
+<sender>, no matter the source IP address.
+
+@item @code{
This message was truncated. Download the full message here.
L
L
Liliana Marie Prikler wrote on 26 Dec 2022 20:34
Re: [PATCH opensmtpd-records v3] services (opensmtpd): add opensmtpd records to enhance opensmtpd-configuration.
(name . Joshua Branson)(address . jbranso@dismail.de)
37239abae388f1fadcba559b62c0aae07de9d319.camel@gmail.com
Am Freitag, dem 23.12.2022 um 08:52 -0500 schrieb Joshua Branson:
Toggle quote (20 lines)
>
> * gnu/services/mail.scm:
> (opensmtpd-table,
> opensmtpd-ca,
> opensmtpd-pki,
> opensmtpd-action-local-delivery,
> opensmtpd-maildir,
> opensmtpd-mda,
> opensmtpd-lmtp,
> opensmtpd-relay,
> opensmtpd-option,
> opensmtpd-filter-phase,
> opensmtpd-filter,
> opensmtpd-interface,
> opensmtpd-socket,
> opensmtpd-match,
> opensmtpd-smtp,
> opensmtpd-srs,
> opensmtpd-queue, and
> opensmtpd-configuration): New records.
Don't forget to put closing parentheses at the end of lines. Also,
feel free to group them to save vertical space.

Toggle quote (81 lines)
> (false?, is-value-right-type, add-comma-or-string,
> list-of-procedures->string, string-in-list?, my-sanitize,
> opensmtpd-filter-chain?, throw-error-duplicate-option,
> sanitize-list-of-options-for-match, sanitize-filters,
> list-has-duplicates-or-non-filters?,
> filter-phase-has-message-and-value?,
> filter-phase-decision-lacks-proper-message?,
> filter-phase-lacks-proper-value?,
> filter-phase-has-incorrect-junk-or-bypass?,
> filter-phase-junks-after-commit?,
> list-of-unique-filter-or-filter-phase?, throw-error,
> contains-duplicate?, list-of-type?, list-of-strings?,
> list-of-unique-opensmtpd-option?,
> list-of-opensmtpd-ca?,
> list-of-opensmtpd-pki?,
> list-of-opensmtpd-listen-on?,
> list-of-unique-opensmtpd-match?, list-of-strings->string,
> assoc-list? assoc-list, variable->string,
> tables-data-are-assoc-list?,
> tables-data-are-a-list-of-strings?,
> table-data-are-a-nested-list-of-strings?,
> assoc-list->string,
> opensmtpd-table->string,
> opensmtpd-listen-on->string,
> opensmtpd-listen-on-socket->string,
> opensmtpd-action-relay->string,
> opensmtpd-lmtp->string,
> opensmtpd-mda->string,
> opensmtpd-maildir->string,
> opensmtpd-action-local-delivery->string,
> opensmtpd-action->string, opensmtpd-option->string,
> opensmtpd-match->string,
> opensmtpd-ca->string, opensmtpd-pki->string,
> generate-filter-chain-name, opensmtpd-filter-chain->string,
> opensmtpd-filter-phase->string, opensmtpd-filters->string,
> opensmtpd-listen->string,
> opensmtpd-srs->string,
> opensmtpd-smtp->string,
> opensmtpd-queue->string, get-opensmtpd-actions,
> get-opensmtpd-pkis, get-opensmtpd-filters, flatten,
> get-opensmtpd-tables, opensmtpd-fieldname->string,
> list-of-records->string, opensmtpd->mixed-text-file): New
> procedures.
>
> * gnu/tests/mail.scm : new tests for various opensmtpd records.
>
> * doc/guix.texi (OpenSMTPD Service): Added documentation for the
> new records for opensmtpd.
> ---
>  doc/guix.texi         | 1065 ++++++++++++++++-
>  gnu/services/mail.scm | 2560
> ++++++++++++++++++++++++++++++++++++++++-
>  gnu/tests/mail.scm    |  713 ++++++++++++
>  3 files changed, 4310 insertions(+), 28 deletions(-)
>
> diff --git a/doc/guix.texi b/doc/guix.texi
> index 535c8cdfc3..879a2ad233 100644
> --- a/doc/guix.texi
> +++ b/doc/guix.texi
> @@ -25407,16 +25407,66 @@ could instantiate a dovecot service like
> this:
>  @end lisp
>  
>  @subsubheading OpenSMTPD Service
> +@cindex opensmtpd
>  
>  @deffn {Scheme Variable} opensmtpd-service-type
> -This is the type of the @uref{https://www.opensmtpd.org, OpenSMTPD}
> -service, whose value should be an @code{opensmtpd-configuration}
> object
> -as in this example:
> +OpenSMTPD is an easy-to-use mail transfer agent (MTA).  OpenSMTPD
> +@strong{listens} for incoming mail and @strong{matches} the mail to
> +@strong{actions}. The following records represent those stages:
>  
> -@lisp
> -(service opensmtpd-service-type
> -         (opensmtpd-configuration
> -           (config-file (local-file "./my-smtpd.conf"))))
> +@multitable {aaaaaaaaa}
> {aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}
I hope this will receive proper documentation.
Toggle quote (285 lines)
> +@item @strong{listens}
> +@tab @code{<opensmtpd-interface>}
> +@item
> +@tab @code{<opensmtpd-socket>}
> +@item
> +@tab
> +@item @strong{matches}
> +@tab @code{<opensmtpd-match>}
> +@item
> +@tab
> +@item @strong{actions}
> +@tab @code{<opensmtpd-local-delivery>}
> +@item
> +@tab @code{<opensmtpd-relay>}
> +@end multitable
> +
> +Additionally, each @code{<opensmtpd-interface>} and
> +@code{<opensmtpd-socket>} may use a list of @code{<opensmtpd-
> filter>},
> +and/or @code{<opensmtpd-filter-phase>} records to filter
> +email/spam. Also numerous records' fieldnames use
> +@code{<opensmtpd-table>} records to hold lists or key value pairs of
> +data.  Be sure to read the @code{<opensmtpd-table>} section to learn
> the
> +differance between a @code{mapping table} and a @code{list table}.
> +
> +Finally, both @code{<opensmtpd-match>} and
> +@code{<opensmtpd-filter-phase>} use @code{<opensmtpd-option>} to
> +configure various options.
> +
> +A simple example opensmtpd configuration is below:
> +
> +@lisp
> +(let ((smtp.gnu.org (opensmtpd-pki
> +                        (domain "smtp.gnu.org")
> +                        (cert "file.cert")
> +                        (key "file.key"))))
> +  (service opensmtpd-service-type
> +           (opensmtpd-configuration
> +            (interfaces (list
> +                         (opensmtpd-interface
> +                          (pki smtp.gnu.org))
> +                         (opensmtpd-interface
> +                          (pki smtp.gnu.org)
> +                          (secure-connection "smtps"))))
> +            (matches (list
> +                      (opensmtpd-match
> +                       (action
> +                        (opensmtpd-local-delivery
> +                         (name "local-delivery"))))
> +                      (opensmtpd-match
> +                       (action
> +                        (opensmtpd-relay
> +                         (name "relay")))))))))
>  @end lisp
>  @end deffn
>  
> @@ -25425,7 +25475,7 @@ Data type representing the configuration of
> opensmtpd.
>  
>  @table @asis
>  @item @code{package} (default: @var{opensmtpd})
> -Package object of the OpenSMTPD SMTP server.
> +Package object of the OpenSMTPD server.
>  
>  @item @code{config-file} (default: @code{%default-opensmtpd-config-
> file})
>  File-like object of the OpenSMTPD configuration file to use.  By
> default
> @@ -25433,14 +25483,1013 @@ it listens on the loopback network
> interface, and allows for mail from
>  users and daemons on the local machine, as well as permitting email
> to
>  remote servers.  Run @command{man smtpd.conf} for more information.
>  
> +@item @code{bounce} (default: @code{(list "4h")})
> +@code{bounce} is a list of strings, which send warning messages to
> the
> +envelope sender when temporary delivery failures cause a message to
> +remain in the queue for longer than a specified delay. Each delay
> option
> +is a string parameter beginning with a positive decimal integer and
> a
> +unit, which can be 's', 'm', 'h', or 'd'. At most four delay
> parameters
> +can be specified.
> +
> +@item @code{interfaces} default:
> +@lisp
> +(list
> +  (opensmtpd-interface
> +    (interface "lo")
> +    (port 25)))
> +@end lisp
> +@code{interfaces} is a list of @code{<opensmtpd-interface>} records.
> +This list details what interfaces and ports OpenSMTPD listens on as
> well as
> +other options.
> +
> +@item @code{socket} (default: @code{(opensmtpd-socket)})
> +Listens for incoming connections on the Unix domain socket.
> +
> +@item @code{includes} (default: @code{#f})
> +@code{includes} is a list of string filenames. Each filename's
> contents is
> +additional configuration that is inserted into the top of the
> configuration
> +file.  Run @code{man smtpd.conf} for more information.
> +
> +@item @code{matches} default:
> +@lisp
> +(list (opensmtpd-match
> +       (action (opensmtpd-local-delivery
> +                (name "local")
> +                (method "mbox")
> +                (options
> +                 (list
> +                  (opensmtpd-option
> +                   (option "for local")))))))
> +      (opensmtpd-match
> +       (action (opensmtpd-relay
> +                (name "outbound")))
> +       (options
> +        (list
> +         (opensmtpd-option
> +          (option "from local"))
> +         (opensmtpd-option
> +          (option "for any"))))))
> +@end lisp
> +@code{matches} is a list of @code{<opensmtpd-match>} records, which
> +matches incoming mail and sends it to a correspending action. The
> match
> +records are evaluated sequentially, with the first match winning.
> +Therefore @emph{the order that you arrange your matches is
> important}.
> +It's a good idea to put specific matches first and an all
> emcompassing
> +match (like @code{(option "for any")}) @strong{last}. If an incoming
> +mail does not match any match records, then it is rejected.
> +
> +@item @code{mta-max-deferred} (default: @code{100})
> +When delivery to a given host is suspended due to temporary
> failures, cache
> +at most number envelopes for that host such that they can be
> delivered as
> +soon as another delivery succeeds to that host. The default is 100.
> +
> +@item @code{queue} (default: @code{#f})
> +@code{queue} expects an @code{<opensmtpd-queue>} record. With it,
> one may
> +compress and encrypt queue-ed emails as well as set the default
> expiration
> +time for temporarily undeliverable messages.
> +
> +@item @code{smtp} (default: @code{#f})
> +@code{smtp} expects an @code{<opensmtpd-smtp>} record, which lets
> one
> +specifiy how large email may be along with other settings.
> +
> +@item @code{srs} (default: @code{#f})
> +@code{srs} expects an @code{<opensmtpd-srs>} record, which lets one
> set
> +up SRS, the Sender Rewritting Scheme.
> +
>  @item @code{setgid-commands?} (default: @code{#t})
>  Make the following commands setgid to @code{smtpq} so they can be
>  executed: @command{smtpctl}, @command{sendmail}, @command{send-
> mail},
>  @command{makemap}, @command{mailq}, and @command{newaliases}.
>  @xref{Setuid Programs}, for more information on setgid programs.
> +
>  @end table
>  @end deftp
>  
> +@itemize
> +@item Data Type: opensmtpd-interface
> +Data type representing the configuration of an
> +@code{<opensmtpd-interface>}. It listens on the fieldname
> +@code{interface} for incoming connections, using the same syntax as
> +@code{ifconfig}. The interface parameter may also be an string
> interface
> +group, an string IP address, or a string domain name. Listening can
> +optionally be restricted to a specific address via the fieldname
> +@code{family}, which can be either @code{"inet4"} or @code{"inet6"}.
> +
> +@itemize
> +@item @code{interface} (default: @code{"lo"})
> +
> +The string interface to listen for incoming connections.  This
> string
> +may be an interface group, an IP address, or a domain name. These
> +interfaces can usually be found by the command @code{ip link}.
> +
> +@item @code{family} (default: @code{#f})
> +
> +Only listen on a specific address family.  Valid strings are
> +@code{"inet4"} or @code{"inet6"}, which will only listen on IPv4 or
> IPv6
> +respectfully.  If @code{(family #f)}, then opensmtpd will listen on
> both
> +IPv4 and IPv6.
> +
> +@item @code{auth} (default: @code{#f})
> +Support SMTPAUTH: clients may only start SMTP transactions after
> +successful authentication. If @code{auth} is @code{#t}, then users
> are
> +authenticated against their own normal login credentials.
> Alternatively
> +@code{auth} may be a @code{mapping table} that maps usernames to
> +encrypted passwords.  The password can be encrypted via the
> +@code{smtpctl} @code{encrypt} subcommand.
> +
> +@item @code{auth-optional} (default: @code{#f})
> +Support SMTPAUTH optionally: clients need not authenticate, but may
> do
> +so.  This allows the @code{<opensmtpd-interface>} to both accept
> +incoming mail from untrusted senders and permit outgoing mail from
> +authenticated users. It can be used in situations where it is not
> +possible to listen on a separate port (usually the submission port,
> 587)
> +for users to authenticate.  This option also accepts a @code{mapping
> +table} that maps usernames to encrypted passwords.
> +
> +@item @code{filters} (default: @code{#f})
> +A list of one or many @code{<opensmtpd-filter>} or
> +@code{<opensmtpd-filter-phase>} records. The filters are applied
> +sequentially. These records listen and filter on connections handled
> by this
> +listener.
> +
> +@item @code{hostname} (default: @code{#f})
> +Change the default server name in the greeting banner instead of the
> +default one.
> +
> +@item @code{hostnames} (default: @code{#f})
> +Override the server name for specific addresses. Use a @code{mapping
> +table} that maps string IP addresses to string hostnames. If the
> address
> +on which the connection arrives appears in the mapping, the
> associated
> +hostname is used.
> +
> +@item @code{mask-src} (default: @code{#f})
> +If @code{#t}, then omit the from part when prepending “Received”
> headers.
> +
> +@item @code{disable-dsn} (default: @code{#f})
> +When @code{#t}, then disable the DSN (Delivery Status Notification)
> extension.
> +
> +@item @code{pki} (default: @code{#f})
> +For secure connections, use an @code{<opensmtpd-pki>} record to
> prove a
> +mail server's identity.
> +
> +@item @code{port} (default: @code{25})
> +Listen on the integer port instead of the default port of 25.
> +
> +@item @code{proxy-v2} (default: @code{#f})
> +If @code{#t}, then support the PROXYv2 protocol, rewriting
> appropriately source
> +address received from proxy.
> +
> +@item @code{received-auth} (default: @code{#f})
> +If @code{#t}, then in “Received” headers, report whether the session
> was
> +authenticated and by which local user.
> +
> +@item @code{senders} (default: @code{#f})
> +Look up the authenticated user in the supplied @code{mapping table}
> to
> +find the email addresses that user is allowed to submit mail as.
> +
> +@item @code{masquerade} (default: @code{#f})
> +@code{masquerade}, is used in conjunction with @code{senders}.  If
> +@code{#t}, then the From header is rewritten to match the sender
> +provided in the SMTP session.  If @code{senders} is @code{#false},
> then
> +@code{masquerade} cannot be @code{#t}.
> +
> +@item @code{secure-connection} (default: @code{#f})
> +This is a string of one of these options:
> +
> +@multitable {aaaaaaaaaaaaaaaaaaaa}
> {aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}
Same here
Toggle quote (98 lines)
> +@item @code{"smtps"}
> +@tab Support SMTPS, by default on port 465.
> +@item @code{"tls"}
> +@tab Support STARTTLS, by default on port 25.
> +@item @code{"tls-require"}
> +@tab Like @code{"tls"}, but force clients to
> +@item
> +@tab establish a secure connection before being
> +@item
> +@tab allowed to start an SMTP transaction.
> +@item @code{"tls-require-verify"}
> +@tab Like @code{"tls-require"}, but clients must
> +@item
> +@tab also provide a valid certificate
> +@item
> +@tab to establish an SMTP session.
> +@end multitable
> +
> +@item @code{tag} (default: @code{#f})
> +Clients connecting to the listener are tagged with the given string
> tag.
> +@end itemize
> +
> +@item Data Type: opensmtpd-socket
> +Data type representing the configuration of an
> +@code{<opensmtpd-socket>}. Listen for incoming SMTP connections on
> the
> +Unix domain socket @samp{/var/run/smtpd.sock}. This is done by
> default,
> +even if the record is absent.
> +
> +@itemize
> +@item @code{filters} (default: @code{#f})
> +A list of one or many @code{<opensmtpd-filter>} or
> +@code{<opensmtpd-filter-phase>} records. These filter incoming
> +connections handled by this listener.
> +
> +@item @code{mask-src} (default: @code{#f})
> +If @code{#t}, then omit the from part when prepending “Received”
> headers.
> +
> +@item @code{tag} (default: @code{#f})
> +Clients connecting to the listener are tagged with the given string
> tag.
> +@end itemize
> +
> +@item Data Type: opensmtpd-match
> +@cindex opensmtpd-match
> +This data type represents the configuration of an
> +@code{<opensmtpd-match>} record.
> +
> +If at least one mail envelope matches the options of one match
> record,
> +receive the incoming message, put a copy into each matching
> envelope,
> +and atomically save the envelopes to the mail spool for later
> processing
> +by the respective @code{<opensmtpd-action>} found in fieldname
> +@code{action}.  Here is an example @code{opensmtpd-match}
> +record.
> +
> +@lisp
> +(opensmtpd-match
> + (action (opensmtpd-local-delivery
> +          (name "receive")
> +          (method (opensmtpd-maildir
> +                   (pathname "/home/%@{rcpt.user@}/Maildir")
> +                   (junk #t)))
> +          (virtual (opensmtpd-table
> +                    (name "virt")
> +                    (data '(("carmen" . "carmen@@gnu.org")))))))
> + (options (list (opensmtpd-option
> +                 (option "from any"))
> +                (opensmtpd-option
> +                 (option "for domain")
> +                 (data (opensmtpd-table
> +                        (name "domain-table")
> +                        (data (list "gnu.org" "fsf.org"))))))))
> +@end lisp
> +
> +@itemize
> +@item @code{action} (default: @code{#f})
> +
> +If mail matches this match configuration, then do this action. Valid
> values
> +include @code{<opensmtpd-local-delivery>} or
> +@code{<opensmtpd-relay>}.
> +
> +@item @code{options} (default: @code{#f})
> +The fieldname @code{option} is a list of unique
> +@code{<opensmtpd-option>} records.
> +
> +There are some mutually exclusive options: there can be only one
> ``for''
> +and only one ``from'' option.
> +
> +@multitable {aaaaaaaaaaaaaaaaaaaaaaaaa}
> {aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}
and here.
Toggle quote (95 lines)
> +@headitem for
> +@tab from
> +@item only use one of the following:
> +@tab only use one of the following:
> +@item @code{"for any"}
> +@tab @code{"from any"}
> +@item @code{"for local"}
> +@tab @code{"from auth"}
> +@item @code{"for domain"}
> +@tab @code{"from local"}
> +@item @code{"for rcpt-to"}
> +@tab @code{"from mail-from"}
> +@item
> +@tab @code{"from socket"}
> +@item
> +@tab @code{"from src"}
> +@end multitable
> +
> +Additionally, some options require additional data via
> +@code{<opensmtpd-option>}'s fieldname @code{data}.  The following
> list
> +will explain the below syntax.
> +
> +@itemize
> +@item @code{"for any"}
> +This option only requires fieldname @code{option} to have the string
> +@code{"for any"}:
> +
> +@lisp
> +      (opensmtpd-option
> +       (option "for any"))
> +@end lisp
> +
> +@item @code{"tag"} _tag_
> +This option only requires fieldname @code{option} to have the string
> +@code{"tag"} with a string in fieldname @code{data}:
> +
> +@lisp
> +      (opensmtpd-option
> +       (option "tag")
> +       (data "this-tag"))
> +@end lisp
> +
> +@item @code{"for rcpt"} _domain_ | <list table>
> +This option requires fieldname @code{data} to have a string domain
> or
> +@code{list table}:
> +
> +@lisp
> +      (opensmtpd-option
> +       (option "for rcpt")
> +       (data "gnu.org"))
> +@end lisp
> +
> +OR
> +
> +@lisp
> +      (opensmtpd-option
> +       (option "for rcpt")
> +       (data (list "gnu.org" "fsf.org")))
> +@end lisp
> +@end itemize
> +
> +The following matching options are supported and can all be negated
> (via not
> +#t). The options that support a table (anything surrounded with '<'
> and '>'
> +eg: <table>), also support specifying regex via (regex #t).
> +
> +@itemize
> +@item @code{"for any"}
> +Specify that session may address any destination.
> +
> +@item @code{"for local"}
> +Specify that session may address any local domain.  This is the
> default,
> +and may be omitted.
> +
> +@item @code{"for domain"} _domain_ | <domain>
> +Specify that session may address the string _domain_ or
> +@code{list table} <domain>.
> +
> +@item @code{"for rcpt-to"} _recipient_ | <recipient>
> +Specify that session may address the string _recipient_ or list
> table
> +<recipient>.
> +
> +@item @code{"from any"}
> +Specify that session may originate from any source.
> +
> +@item @code{"from auth"}
> +Specify that session may originate from any authenticated user, no
> matter
> +the source IP address.
> +
This message was truncated. Download the full message here.
J
J
Joshua Branson wrote on 28 Dec 2022 01:16
(name . Liliana Marie Prikler)(address . liliana.prikler@gmail.com)
87k02co01c.fsf@dismail.de
Liliana Marie Prikler <liliana.prikler@gmail.com> writes:

Toggle quote (24 lines)
> Am Freitag, dem 23.12.2022 um 08:52 -0500 schrieb Joshua Branson:
>>
>> * gnu/services/mail.scm:
>> (opensmtpd-table,
>> opensmtpd-ca,
>> opensmtpd-pki,
>> opensmtpd-action-local-delivery,
>> opensmtpd-maildir,
>> opensmtpd-mda,
>> opensmtpd-lmtp,
>> opensmtpd-relay,
>> opensmtpd-option,
>> opensmtpd-filter-phase,
>> opensmtpd-filter,
>> opensmtpd-interface,
>> opensmtpd-socket,
>> opensmtpd-match,
>> opensmtpd-smtp,
>> opensmtpd-srs,
>> opensmtpd-queue, and
>> opensmtpd-configuration): New records.
> Don't forget to put closing parentheses at the end of lines. Also,
> feel free to group them to save vertical space.

Thanks again for your speedy review! I am sending this from my gnucode.me email
address you'll notice. And it is using these new records. :)

Toggle quote (84 lines)
>
>> (false?, is-value-right-type, add-comma-or-string,
>> list-of-procedures->string, string-in-list?, my-sanitize,
>> opensmtpd-filter-chain?, throw-error-duplicate-option,
>> sanitize-list-of-options-for-match, sanitize-filters,
>> list-has-duplicates-or-non-filters?,
>> filter-phase-has-message-and-value?,
>> filter-phase-decision-lacks-proper-message?,
>> filter-phase-lacks-proper-value?,
>> filter-phase-has-incorrect-junk-or-bypass?,
>> filter-phase-junks-after-commit?,
>> list-of-unique-filter-or-filter-phase?, throw-error,
>> contains-duplicate?, list-of-type?, list-of-strings?,
>> list-of-unique-opensmtpd-option?,
>> list-of-opensmtpd-ca?,
>> list-of-opensmtpd-pki?,
>> list-of-opensmtpd-listen-on?,
>> list-of-unique-opensmtpd-match?, list-of-strings->string,
>> assoc-list? assoc-list, variable->string,
>> tables-data-are-assoc-list?,
>> tables-data-are-a-list-of-strings?,
>> table-data-are-a-nested-list-of-strings?,
>> assoc-list->string,
>> opensmtpd-table->string,
>> opensmtpd-listen-on->string,
>> opensmtpd-listen-on-socket->string,
>> opensmtpd-action-relay->string,
>> opensmtpd-lmtp->string,
>> opensmtpd-mda->string,
>> opensmtpd-maildir->string,
>> opensmtpd-action-local-delivery->string,
>> opensmtpd-action->string, opensmtpd-option->string,
>> opensmtpd-match->string,
>> opensmtpd-ca->string, opensmtpd-pki->string,
>> generate-filter-chain-name, opensmtpd-filter-chain->string,
>> opensmtpd-filter-phase->string, opensmtpd-filters->string,
>> opensmtpd-listen->string,
>> opensmtpd-srs->string,
>> opensmtpd-smtp->string,
>> opensmtpd-queue->string, get-opensmtpd-actions,
>> get-opensmtpd-pkis, get-opensmtpd-filters, flatten,
>> get-opensmtpd-tables, opensmtpd-fieldname->string,
>> list-of-records->string, opensmtpd->mixed-text-file): New
>> procedures.
>>
>> * gnu/tests/mail.scm : new tests for various opensmtpd records.
>>
>> * doc/guix.texi (OpenSMTPD Service): Added documentation for the
>> new records for opensmtpd.
>> ---
>>  doc/guix.texi         | 1065 ++++++++++++++++-
>>  gnu/services/mail.scm | 2560
>> ++++++++++++++++++++++++++++++++++++++++-
>>  gnu/tests/mail.scm    |  713 ++++++++++++
>>  3 files changed, 4310 insertions(+), 28 deletions(-)
>>
>> diff --git a/doc/guix.texi b/doc/guix.texi
>> index 535c8cdfc3..879a2ad233 100644
>> --- a/doc/guix.texi
>> +++ b/doc/guix.texi
>> @@ -25407,16 +25407,66 @@ could instantiate a dovecot service like
>> this:
>>  @end lisp
>>  
>>  @subsubheading OpenSMTPD Service
>> +@cindex opensmtpd
>>  
>>  @deffn {Scheme Variable} opensmtpd-service-type
>> -This is the type of the @uref{https://www.opensmtpd.org, OpenSMTPD}
>> -service, whose value should be an @code{opensmtpd-configuration}
>> object
>> -as in this example:
>> +OpenSMTPD is an easy-to-use mail transfer agent (MTA).  OpenSMTPD
>> +@strong{listens} for incoming mail and @strong{matches} the mail to
>> +@strong{actions}. The following records represent those stages:
>>  
>> -@lisp
>> -(service opensmtpd-service-type
>> -         (opensmtpd-configuration
>> -           (config-file (local-file "./my-smtpd.conf"))))
>> +@multitable {aaaaaaaaa}
>> {aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}
> I hope this will receive proper documentation.

Users can still use

(service opensmtpd-service-type
         (opensmtpd-configuration
           (config-file (local-file "./my-smtpd.conf"))))

config-file is still a fieldname of <opensmtpd-configuration>. Is that what you mean?

Also the generated documentation is available here:


Toggle quote (287 lines)
>> +@item @strong{listens}
>> +@tab @code{<opensmtpd-interface>}
>> +@item
>> +@tab @code{<opensmtpd-socket>}
>> +@item
>> +@tab
>> +@item @strong{matches}
>> +@tab @code{<opensmtpd-match>}
>> +@item
>> +@tab
>> +@item @strong{actions}
>> +@tab @code{<opensmtpd-local-delivery>}
>> +@item
>> +@tab @code{<opensmtpd-relay>}
>> +@end multitable
>> +
>> +Additionally, each @code{<opensmtpd-interface>} and
>> +@code{<opensmtpd-socket>} may use a list of @code{<opensmtpd-
>> filter>},
>> +and/or @code{<opensmtpd-filter-phase>} records to filter
>> +email/spam. Also numerous records' fieldnames use
>> +@code{<opensmtpd-table>} records to hold lists or key value pairs of
>> +data.  Be sure to read the @code{<opensmtpd-table>} section to learn
>> the
>> +differance between a @code{mapping table} and a @code{list table}.
>> +
>> +Finally, both @code{<opensmtpd-match>} and
>> +@code{<opensmtpd-filter-phase>} use @code{<opensmtpd-option>} to
>> +configure various options.
>> +
>> +A simple example opensmtpd configuration is below:
>> +
>> +@lisp
>> +(let ((smtp.gnu.org (opensmtpd-pki
>> +                        (domain "smtp.gnu.org")
>> +                        (cert "file.cert")
>> +                        (key "file.key"))))
>> +  (service opensmtpd-service-type
>> +           (opensmtpd-configuration
>> +            (interfaces (list
>> +                         (opensmtpd-interface
>> +                          (pki smtp.gnu.org))
>> +                         (opensmtpd-interface
>> +                          (pki smtp.gnu.org)
>> +                          (secure-connection "smtps"))))
>> +            (matches (list
>> +                      (opensmtpd-match
>> +                       (action
>> +                        (opensmtpd-local-delivery
>> +                         (name "local-delivery"))))
>> +                      (opensmtpd-match
>> +                       (action
>> +                        (opensmtpd-relay
>> +                         (name "relay")))))))))
>>  @end lisp
>>  @end deffn
>>  
>> @@ -25425,7 +25475,7 @@ Data type representing the configuration of
>> opensmtpd.
>>  
>>  @table @asis
>>  @item @code{package} (default: @var{opensmtpd})
>> -Package object of the OpenSMTPD SMTP server.
>> +Package object of the OpenSMTPD server.
>>  
>>  @item @code{config-file} (default: @code{%default-opensmtpd-config-
>> file})
>>  File-like object of the OpenSMTPD configuration file to use.  By
>> default
>> @@ -25433,14 +25483,1013 @@ it listens on the loopback network
>> interface, and allows for mail from
>>  users and daemons on the local machine, as well as permitting email
>> to
>>  remote servers.  Run @command{man smtpd.conf} for more information.
>>  
>> +@item @code{bounce} (default: @code{(list "4h")})
>> +@code{bounce} is a list of strings, which send warning messages to
>> the
>> +envelope sender when temporary delivery failures cause a message to
>> +remain in the queue for longer than a specified delay. Each delay
>> option
>> +is a string parameter beginning with a positive decimal integer and
>> a
>> +unit, which can be 's', 'm', 'h', or 'd'. At most four delay
>> parameters
>> +can be specified.
>> +
>> +@item @code{interfaces} default:
>> +@lisp
>> +(list
>> +  (opensmtpd-interface
>> +    (interface "lo")
>> +    (port 25)))
>> +@end lisp
>> +@code{interfaces} is a list of @code{<opensmtpd-interface>} records.
>> +This list details what interfaces and ports OpenSMTPD listens on as
>> well as
>> +other options.
>> +
>> +@item @code{socket} (default: @code{(opensmtpd-socket)})
>> +Listens for incoming connections on the Unix domain socket.
>> +
>> +@item @code{includes} (default: @code{#f})
>> +@code{includes} is a list of string filenames. Each filename's
>> contents is
>> +additional configuration that is inserted into the top of the
>> configuration
>> +file.  Run @code{man smtpd.conf} for more information.
>> +
>> +@item @code{matches} default:
>> +@lisp
>> +(list (opensmtpd-match
>> +       (action (opensmtpd-local-delivery
>> +                (name "local")
>> +                (method "mbox")
>> +                (options
>> +                 (list
>> +                  (opensmtpd-option
>> +                   (option "for local")))))))
>> +      (opensmtpd-match
>> +       (action (opensmtpd-relay
>> +                (name "outbound")))
>> +       (options
>> +        (list
>> +         (opensmtpd-option
>> +          (option "from local"))
>> +         (opensmtpd-option
>> +          (option "for any"))))))
>> +@end lisp
>> +@code{matches} is a list of @code{<opensmtpd-match>} records, which
>> +matches incoming mail and sends it to a correspending action. The
>> match
>> +records are evaluated sequentially, with the first match winning.
>> +Therefore @emph{the order that you arrange your matches is
>> important}.
>> +It's a good idea to put specific matches first and an all
>> emcompassing
>> +match (like @code{(option "for any")}) @strong{last}. If an incoming
>> +mail does not match any match records, then it is rejected.
>> +
>> +@item @code{mta-max-deferred} (default: @code{100})
>> +When delivery to a given host is suspended due to temporary
>> failures, cache
>> +at most number envelopes for that host such that they can be
>> delivered as
>> +soon as another delivery succeeds to that host. The default is 100.
>> +
>> +@item @code{queue} (default: @code{#f})
>> +@code{queue} expects an @code{<opensmtpd-queue>} record. With it,
>> one may
>> +compress and encrypt queue-ed emails as well as set the default
>> expiration
>> +time for temporarily undeliverable messages.
>> +
>> +@item @code{smtp} (default: @code{#f})
>> +@code{smtp} expects an @code{<opensmtpd-smtp>} record, which lets
>> one
>> +specifiy how large email may be along with other settings.
>> +
>> +@item @code{srs} (default: @code{#f})
>> +@code{srs} expects an @code{<opensmtpd-srs>} record, which lets one
>> set
>> +up SRS, the Sender Rewritting Scheme.
>> +
>>  @item @code{setgid-commands?} (default: @code{#t})
>>  Make the following commands setgid to @code{smtpq} so they can be
>>  executed: @command{smtpctl}, @command{sendmail}, @command{send-
>> mail},
>>  @command{makemap}, @command{mailq}, and @command{newaliases}.
>>  @xref{Setuid Programs}, for more information on setgid programs.
>> +
>>  @end table
>>  @end deftp
>>  
>> +@itemize
>> +@item Data Type: opensmtpd-interface
>> +Data type representing the configuration of an
>> +@code{<opensmtpd-interface>}. It listens on the fieldname
>> +@code{interface} for incoming connections, using the same syntax as
>> +@code{ifconfig}. The interface parameter may also be an string
>> interface
>> +group, an string IP address, or a string domain name. Listening can
>> +optionally be restricted to a specific address via the fieldname
>> +@code{family}, which can be either @code{"inet4"} or @code{"inet6"}.
>> +
>> +@itemize
>> +@item @code{interface} (default: @code{"lo"})
>> +
>> +The string interface to listen for incoming connections.  This
>> string
>> +may be an interface group, an IP address, or a domain name. These
>> +interfaces can usually be found by the command @code{ip link}.
>> +
>> +@item @code{family} (default: @code{#f})
>> +
>> +Only listen on a specific address family.  Valid strings are
>> +@code{"inet4"} or @code{"inet6"}, which will only listen on IPv4 or
>> IPv6
>> +respectfully.  If @code{(family #f)}, then opensmtpd will listen on
>> both
>> +IPv4 and IPv6.
>> +
>> +@item @code{auth} (default: @code{#f})
>> +Support SMTPAUTH: clients may only start SMTP transactions after
>> +successful authentication. If @code{auth} is @code{#t}, then users
>> are
>> +authenticated against their own normal login credentials.
>> Alternatively
>> +@code{auth} may be a @code{mapping table} that maps usernames to
>> +encrypted passwords.  The password can be encrypted via the
>> +@code{smtpctl} @code{encrypt} subcommand.
>> +
>> +@item @code{auth-optional} (default: @code{#f})
>> +Support SMTPAUTH optionally: clients need not authenticate, but may
>> do
>> +so.  This allows the @code{<opensmtpd-interface>} to both accept
>> +incoming mail from untrusted senders and permit outgoing mail from
>> +authenticated users. It can be used in situations where it is not
>> +possible to listen on a separate port (usually the submission port,
>> 587)
>> +for users to authenticate.  This option also accepts a @code{mapping
>> +table} that maps usernames to encrypted passwords.
>> +
>> +@item @code{filters} (default: @code{#f})
>> +A list of one or many @code{<opensmtpd-filter>} or
>> +@code{<opensmtpd-filter-phase>} records. The filters are applied
>> +sequentially. These records listen and filter on connections handled
>> by this
>> +listener.
>> +
>> +@item @code{hostname} (default: @code{#f})
>> +Change the default server name in the greeting banner instead of the
>> +default one.
>> +
>> +@item @code{hostnames} (default: @code{#f})
>> +Override the server name for specific addresses. Use a @code{mapping
>> +table} that maps string IP addresses to string hostnames. If the
>> address
>> +on which the connection arrives appears in the mapping, the
>> associated
>> +hostname is used.
>> +
>> +@item @code{mask-src} (default: @code{#f})
>> +If @code{#t}, then omit the from part when prepending “Received”
>> headers.
>> +
>> +@item @code{disable-dsn} (default: @code{#f})
>> +When @code{#t}, then disable the DSN (Delivery Status Notification)
>> extension.
>> +
>> +@item @code{pki} (default: @code{#f})
>> +For secure connections, use an @code{<opensmtpd-pki>} record to
>> prove a
>> +mail server's identity.
>> +
>> +@item @code{port} (default: @code{25})
>> +Listen on the integer port instead of the default port of 25.
>> +
>> +@item @code{proxy-v2} (default: @code{#f})
>> +If @code{#t}, then support the PROXYv2 protocol, rewriting
>> appropriately source
>> +address received from proxy.
>> +
>> +@item @code{received-auth} (default: @code{#f})
>> +If @code{#t}, then in “Received” headers, report whether the session
>> was
>> +authenticated and by which local user.
>> +
>> +@item @code{senders} (default: @code{#f})
>> +Look up the authenticated user in the supplied @code{mapping table}
>> to
>> +find the email addresses that user is allowed to submit mail as.
>> +
>> +@item @code{masquerade} (default: @code{#f})
>> +@code{masquerade}, is used in conjunction with @code{senders}.  If
>> +@code{#t}, then the From header is rewritten to match the sender
>> +provided in the SMTP session.  If @code{senders} is @code{#false},
>> then
>> +@code{masquerade} cannot be @code{#t}.
>> +
>> +@item @code{secure-connection} (default: @code{#f})
>> +This is a string of one of these options:
>> +
>> +@multitable {aaaaaaaaaaaaaaaaaaaa}
>> {aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}
> Same here

Are you saying secure-connection is not documented?

It's documented in the table just below:

Toggle quote (100 lines)
>> +@item @code{"smtps"}
>> +@tab Support SMTPS, by default on port 465.
>> +@item @code{"tls"}
>> +@tab Support STARTTLS, by default on port 25.
>> +@item @code{"tls-require"}
>> +@tab Like @code{"tls"}, but force clients to
>> +@item
>> +@tab establish a secure connection before being
>> +@item
>> +@tab allowed to start an SMTP transaction.
>> +@item @code{"tls-require-verify"}
>> +@tab Like @code{"tls-require"}, but clients must
>> +@item
>> +@tab also provide a valid certificate
>> +@item
>> +@tab to establish an SMTP session.
>> +@end multitable
>> +
>> +@item @code{tag} (default: @code{#f})
>> +Clients connecting to the listener are tagged with the given string
>> tag.
>> +@end itemize
>> +
>> +@item Data Type: opensmtpd-socket
>> +Data type representing the configuration of an
>> +@code{<opensmtpd-socket>}. Listen for incoming SMTP connections on
>> the
>> +Unix domain socket @samp{/var/run/smtpd.sock}. This is done by
>> default,
>> +even if the record is absent.
>> +
>> +@itemize
>> +@item @code{filters} (default: @code{#f})
>> +A list of one or many @code{<opensmtpd-filter>} or
>> +@code{<opensmtpd-filter-phase>} records. These filter incoming
>> +connections handled by this listener.
>> +
>> +@item @code{mask-src} (default: @code{#f})
>> +If @code{#t}, then omit the from part when prepending “Received”
>> headers.
>> +
>> +@item @code{tag} (default: @code{#f})
>> +Clients connecting to the listener are tagged with the given string
>> tag.
>> +@end itemize
>> +
>> +@item Data Type: opensmtpd-match
>> +@cindex opensmtpd-match
>> +This data type represents the configuration of an
>> +@code{<opensmtpd-match>} record.
>> +
>> +If at least one mail envelope matches the options of one match
>> record,
>> +receive the incoming message, put a copy into each matching
>> envelope,
>> +and atomically save the envelopes to the mail spool for later
>> processing
>> +by the respective @code{<opensmtpd-action>} found in fieldname
>> +@code{action}.  Here is an example @code{opensmtpd-match}
>> +record.
>> +
>> +@lisp
>> +(opensmtpd-match
>> + (action (opensmtpd-local-delivery
>> +          (name "receive")
>> +          (method (opensmtpd-maildir
>> +                   (pathname "/home/%@{rcpt.user@}/Maildir")
>> +                   (junk #t)))
>> +          (virtual (opensmtpd-table
>> +                    (name "virt")
>> +                    (data '(("carmen" . "carmen@@gnu.org")))))))
>> + (options (list (opensmtpd-option
>> +                 (option "from any"))
>> +                (opensmtpd-option
>> +                 (option "for domain")
>> +                 (data (opensmtpd-table
>> +                        (name "domain-table")
>> +                        (data (list "gnu.org" "fsf.org"))))))))
>> +@end lisp
>> +
>> +@itemize
>> +@item @code{action} (default: @code{#f})
>> +
>> +If mail matches this match configuration, then do this action. Valid
>> values
>> +include @code{<opensmtpd-local-delivery>} or
>> +@code{<opensmtpd-relay>}.
>> +
>> +@item @code{options} (default: @code{#f})
>> +The fieldname @code{option} is a list of unique
>> +@code{<opensmtpd-option>} records.
>> +
>> +There are some mutually exclusive options: there can be only one
>> ``for''
>> +and only one ``from'' option.
>> +
>> +@multitable {aaaaaaaaaaaaaaaaaaaaaaaaa}
>> {aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}
> and here.

If you are referring to <opensmtpd-option> is it documented like this:

• Data Type: opensmtpd-option This data type represents the
configuration of an ‘<opensmtpd-option>’, which is used by
‘<opensmtpd-filter-phase>’ and ‘<opensmtpd-match>’ to match various
options for email.

(sorry about the above formatting). That is currently how the documentation is
generated. I need to go through the documentation is fix that. I did
<opensmtpd-configuration> correctly.


Toggle quote (31 lines)
>> +@headitem for
>> +@tab from
>> +@item only use one of the following:
>> +@tab only use one of the following:
>> +@item @code{"for any"}
>> +@tab @code{"from any"}
>> +@item @code{"for local"}
>> +@tab @code{"from auth"}
>> +@item @code{"for domain"}
>> +@tab @code{"from local"}
>> +@item @code{"for rcpt-to"}
>> +@tab @code{"from mail-from"}
>> +@item
>> +@tab @code{"from socket"}
>> +@item
>> +@tab @code{"from src"}
>> +@end multitable
>> +
>> +Additionally, some options require additional data via
>> +@code{<opensmtpd-option>}'s fieldname @code{data}.  The following
>> list
>> +will explain the below syntax.
>> +
>> +@itemize
>> +@item @code{"for any"}
>> +This option only requires fieldname @code{option} to have the string
>> +@code{"for any"}:
>> +
>> +@lisp
>> +      (opensmtpd-option
>> +      
This message was truncated. Download the full message here.
L
L
Liliana Marie Prikler wrote on 28 Dec 2022 21:04
(name . Joshua Branson)(address . jbranso@dismail.de)
91b2d3a6834780b36b876dd55699c2941349b5bf.camel@gmail.com
Am Dienstag, dem 27.12.2022 um 19:16 -0500 schrieb Joshua Branson:
Toggle quote (3 lines)
> Are you giving me a triple A+ ? :) Org generated the the like that. I
> think you mentioned that I should use fractions last time. Sorry I
> did not do that.
Do you have to convert your documentation from org? Writing Texinfo
code manually is an option, as is generating it from define-
configuration IIRC. There is also nothing wrong with manually touching
up generated docs, but I imagine doing so consistently might be a bit
more adventurous.

Toggle quote (3 lines)
> If I wait 'til I implement every one of your suggestions, I will
> probably never submit it. I am really probably "perfecting" this
> service.
You can submit whatever, but don't expect me or any other committer to
upstream the patches while there are open points to address.
Toggle quote (6 lines)
>

> > Instead of a string, take 'no-verify as symbol perhaps?
>
> Sounds good to me. May I ask why you prefer a symbol instead of a
> string?
Symbols can be compared with eq?, case et al.

Toggle quote (22 lines)
> > > -;;;
> > >  ;;; OpenSMTPD.
> > >  ;;;
> > > +;;; This next bit of code helps me create my own sanitizer
> > > functions.
> > > +
> > > +;; some fieldnames have a default value of #f, which is ok. 
> > > They
> > > cannot have
> > > +;; a value of #t.
> > > +;; for example opensmtpd-table-data can be #f, BUT NOT true.
> > > +;; my/sanitize procedure tests values to see if they are of the
> > > right kind.
> > > +;; procedure false? is needed to allow fields like 'values' to
> > > be
> > > blank,
> > > +;; (empty), or #f BUT also have a value like a list of strings.
> > Use less egocentric comments ;)
>
> I'm not sure what you mean here? I know I had a comment in my task
> list that said something like my sanitizer function are probably
> better than those found in guix. Apologies for that.
For what it's worth, it definitely wasn't I. [1]

Toggle quote (13 lines)
> >
> > > +(define (false? var)
> > > +  (eq? #f var))
> > > +
> > > +;; TODO I have to have this procedure, or I need to change
> > > my/sanitize
> > > +;; procedure.
> > > +(define (my-file-exists? file)
> > > +  (and (string? file)
> > > +       (access? file F_OK)))
> > Does file-exists? not work for you?
>
> The file-exists? function causes my-sanitize function to break.
Why?

Toggle quote (1 lines)
> I think. 
Prove it.

Toggle quote (2 lines)
> If you get rid of it, then what happens when a user types in (file
> 4), you get an raise-exception. 
(file-exists? "(file 4)") ; => #f

Toggle quote (5 lines)
> I can probably just rework my-sanitizer function to
> deal with that possibility, but I have not yet. I would love some
> guidance on how to do that. Because I feel like having to handle that
> exception is hard.

From the Guile manual:

-- Scheme Procedure: stat object [exception-on-error?]
-- C Function: scm_stat (object, exception_on_error)
[...]
If the optional EXCEPTION_ON_ERROR argument is true, which is the
default, an exception will be raised if the underlying system call
returns an error, for example if the file is not found or is not
readable. Otherwise, an error will cause ‘stat’ to return ‘#f’.

Now, in (ice-9 boot-9), file-exists? is defined (assuming posix) as

(lambda (str)
(->bool (stat str #f)))

Thus, I am pretty sure that no exception should be raised from the
check ;)

Toggle quote (40 lines)
> >
> > > +;; This procedure takes in a var and a list of procedures.  It
> > > loops
> > > through
> > > +;; list of procedures passing in var to each.
> > > +;; if one procedure returns #t, the function returns true. 
> > > Otherwise #f.
> > > +;; TODO for fun rewrite this using map
> > > +;; If I rewrote it in map, then it may help with sanitizing.
> > > +;; eg: I could then potentially easily sanitize vars with lambda
> > > procedures.
> > > +(define (is-value-right-type? var list-of-procedures record
> > > fieldname)
> > > +  (if (null? list-of-procedures)
> > > +      #f
> > > +      (if ((car list-of-procedures) var)
> > > +          #t
> > > +          (is-value-right-type? var (cdr list-of-procedures)
> > > record
> > > +                                fieldname))))
> > Alternatively, (any (cut <> var) list-of-procedures).
>
> You mentioned that in the last review, I just can't figure out how to
> use your
> suggestion. This is the code that I have in the task list WIP:
>
> *** TODO simplify my sanitizing funcions  (any (cut <> var))
>
> #+BEGIN_SRC scheme
> (use-modules (ice-9 curried-definitions)
>              (srfi srfi-26))
>
> (define (((expect-any predicates) record field) var)
>   (if (any (cut <> var) predicates)
>       var
>       (begin
>         ;; code code code
>         ;; how do I tell the user which function failed?
>         (display "error")
>         (throw 'bad! var))))
All of them failed, that's the point. As for constructing a string
from a list of procedures, see list-of-procedures->string.

Toggle quote (13 lines)
> ;; here is how you use it.
>   (name opensmtpd-table-name ;; string
>         (default #f)
>         (sanitize (lambda (var)
>                     (((expect-any (list string? number?)) "hello"
> "that") var))))
>
> #+END_SRC
>
> Does that look close to what you want? I feel like it is way off, but
> I don't know. Honestly when I say this suggestion I was completely
> blown away, I have been using (any ) and (every) in a few places to
> get rid of some uses of primitive eval.
I don't see that, but I do see functions that have been dropped still
mentioned in the ChangeLog. Another hint at this patch being too
convoluted for its own sake ;)

Toggle quote (8 lines)
> > This procedure needs a proper name, like sanitize/check-type, but
> > more importantly, why not simply use define-configuration?
>
> Yes! I have slowly been realizing that I have been clumsily re-
> inventing define-configuration. I hope to switch to define-
> configuration, because a lot of this code would go away. But I need
> to explore how define-configuration works.
> That would be quite a major change. :)
Manchmal erspart einem monatelange Implementier-Arbeit einen Nachmittag
in der Bücherei.

Cheers

J
J
jbranso wrote on 28 Dec 2022 21:42
(name . Liliana Marie Prikler)(address . liliana.prikler@gmail.com)
69ac260cb40f16a47a6683f11f2b9af0@dismail.de
December 28, 2022 3:04 PM, "Liliana Marie Prikler" <liliana.prikler@gmail.com> wrote:

Toggle quote (12 lines)
> Am Dienstag, dem 27.12.2022 um 19:16 -0500 schrieb Joshua Branson:
>
>> Are you giving me a triple A+ ? :) Org generated the the like that. I
>> think you mentioned that I should use fractions last time. Sorry I
>> did not do that.
>
> Do you have to convert your documentation from org? Writing Texinfo
> code manually is an option, as is generating it from define-
> configuration IIRC. There is also nothing wrong with manually touching
> up generated docs, but I imagine doing so consistently might be a bit
> more adventurous.

I wrote the first draft of the documentation in org. Then converted it
to texinfo. I have been writing in texinfo ever since. :)

Toggle quote (8 lines)
>
>> If I wait 'til I implement every one of your suggestions, I will
>> probably never submit it. I am really probably "perfecting" this
>> service.
>
> You can submit whatever, but don't expect me or any other committer to
> upstream the patches while there are open points to address.

Of course. :) I wish I could implement all of your suggestions sooner,
but I am still learning. And I might be a bit of a slow coder. :(

Toggle quote (51 lines)
>> Instead of a string, take 'no-verify as symbol perhaps?
>>
>> Sounds good to me. May I ask why you prefer a symbol instead of a
>> string?
>
> Symbols can be compared with eq?, case et al.
>
>>> -;;;
>>> ;;; OpenSMTPD.
>>> ;;;
>>> +;;; This next bit of code helps me create my own sanitizer
>>> functions.
>>> +
>>> +;; some fieldnames have a default value of #f, which is ok.
>>> They
>>> cannot have
>>> +;; a value of #t.
>>> +;; for example opensmtpd-table-data can be #f, BUT NOT true.
>>> +;; my/sanitize procedure tests values to see if they are of the
>>> right kind.
>>> +;; procedure false? is needed to allow fields like 'values' to
>>> be
>>> blank,
>>> +;; (empty), or #f BUT also have a value like a list of strings.
>> Use less egocentric comments ;)
>>
>> I'm not sure what you mean here? I know I had a comment in my task
>> list that said something like my sanitizer function are probably
>> better than those found in guix. Apologies for that.
>
> For what it's worth, it definitely wasn't I. [1]
>
>>> +(define (false? var)
>>> + (eq? #f var))
>>> +
>>> +;; TODO I have to have this procedure, or I need to change
>>> my/sanitize
>>> +;; procedure.
>>> +(define (my-file-exists? file)
>>> + (and (string? file)
>>> + (access? file F_OK)))
>> Does file-exists? not work for you?
>>
>> The file-exists? function causes my-sanitize function to break.
>
> Why?
>
>> I think.
>
> Prove it.

Oh, the last time I used guile's file-exist? It broke a one of
my tests. I intend to use guile's file-exist? I just have not
figured out how to yet. :)

Toggle quote (6 lines)
>
>> If you get rid of it, then what happens when a user types in (file
>> 4), you get an raise-exception.
>
> (file-exists? "(file 4)") ; => #f

The way I am sanitizing it, something like this happens.
A silly user puts this in their configuration:

(opensmtpd-configuration
(config-file 4))


(file-exists? (openstmtpd-configuration-config-file record))

(file-exists? 4) => raise-exception

Toggle quote (84 lines)
>> I can probably just rework my-sanitizer function to
>> deal with that possibility, but I have not yet. I would love some
>> guidance on how to do that. Because I feel like having to handle that
>> exception is hard.
>
> From the Guile manual:
>
> -- Scheme Procedure: stat object [exception-on-error?]
> -- C Function: scm_stat (object, exception_on_error)
> [...]
> If the optional EXCEPTION_ON_ERROR argument is true, which is the
> default, an exception will be raised if the underlying system call
> returns an error, for example if the file is not found or is not
> readable. Otherwise, an error will cause ‘stat’ to return ‘#f’.
>
> Now, in (ice-9 boot-9), file-exists? is defined (assuming posix) as
>
> (lambda (str)
> (->bool (stat str #f)))
>
> Thus, I am pretty sure that no exception should be raised from the
> check ;)
>
>>> +;; This procedure takes in a var and a list of procedures. It
>>> loops
>>> through
>>> +;; list of procedures passing in var to each.
>>> +;; if one procedure returns #t, the function returns true.
>>> Otherwise #f.
>>> +;; TODO for fun rewrite this using map
>>> +;; If I rewrote it in map, then it may help with sanitizing.
>>> +;; eg: I could then potentially easily sanitize vars with lambda
>>> procedures.
>>> +(define (is-value-right-type? var list-of-procedures record
>>> fieldname)
>>> + (if (null? list-of-procedures)
>>> + #f
>>> + (if ((car list-of-procedures) var)
>>> + #t
>>> + (is-value-right-type? var (cdr list-of-procedures)
>>> record
>>> + fieldname))))
>> Alternatively, (any (cut <> var) list-of-procedures).
>>
>> You mentioned that in the last review, I just can't figure out how to
>> use your
>> suggestion. This is the code that I have in the task list WIP:
>>
>> *** TODO simplify my sanitizing funcions (any (cut <> var))
>>
>> #+BEGIN_SRC scheme
>> (use-modules (ice-9 curried-definitions)
>> (srfi srfi-26))
>>
>> (define (((expect-any predicates) record field) var)
>> (if (any (cut <> var) predicates)
>> var
>> (begin
>> ;; code code code
>> ;; how do I tell the user which function failed?
>> (display "error")
>> (throw 'bad! var))))
>
> All of them failed, that's the point. As for constructing a string
> from a list of procedures, see list-of-procedures->string.
>
>> ;; here is how you use it.
>> (name opensmtpd-table-name ;; string
>> (default #f)
>> (sanitize (lambda (var)
>> (((expect-any (list string? number?)) "hello"
>> "that") var))))
>>
>> #+END_SRC
>>
>> Does that look close to what you want? I feel like it is way off, but
>> I don't know. Honestly when I say this suggestion I was completely
>> blown away, I have been using (any ) and (every) in a few places to
>> get rid of some uses of primitive eval.
>
> I don't see that, but I do see functions that have been dropped still
> mentioned in the ChangeLog. Another hint at this patch being too
> convoluted for its own sake ;)

How would I unconvoluted it? Use define-configuration?

Toggle quote (16 lines)
>
>> This procedure needs a proper name, like sanitize/check-type, but
>> more importantly, why not simply use define-configuration?
>>
>> Yes! I have slowly been realizing that I have been clumsily re-
>> inventing define-configuration. I hope to switch to define-
>> configuration, because a lot of this code would go away. But I need
>> to explore how define-configuration works.
>> That would be quite a major change. :)
>
> Manchmal erspart einem monatelange Implementier-Arbeit einen Nachmittag
> in der Bücherei.
>
> Cheers
>
> [1] https://issues.guix.gnu.org/issue/56046#4-lineno323
V
V
Vivien Kraus wrote on 15 Jun 2023 18:06
Re: [PATCH] services: mail: add opensmtpd records to enhance opensmtpd-configuration.
(address . 56046@debbugs.gnu.org)
2016cf7456ca5290d1232f2e47ab18d74e6e3f61.camel@planete-kraus.eu
Hello guix,

I would very much like to have better support (more modular) for
opensmtpd. This patch series seems to go in the right direction. What
is its status?

Best regards,

Vivien
J
J
Joshua Branson wrote on 18 Aug 2023 13:16
Re: bug#56046: [PATCH] services: mail: add opensmtpd records to enhance opensmtpd-configuration.
(name . Vivien Kraus)(address . vivien@planete-kraus.eu)
87a5uoy519.fsf_-_@dismail.de
Vivien Kraus <vivien@planete-kraus.eu> writes:

Toggle quote (10 lines)
> Hello guix,
>
> I would very much like to have better support (more modular) for
> opensmtpd. This patch series seems to go in the right direction. What
> is its status?
>
> Best regards,
>
> Vivien

So, I recently just got my email server up and running again, which is
awesome! What is its status?

It works! You can configure fairly basic email configurations. You
should try to run it on your server. This blog post walks you through how:


You might not be able to use guix deploy with this service at the
moment. You might have to ssh into your server and do a "guix system
reconfigure". I fixed that bug, but have not pushed it to guixrus yet.

Feel free to ask me any questions.

In terms of upstreaming this to guix proper. It seems like I should
* convert all of the (define-record-type* ...) -> (define-configuration)
* make sure all of the tests still work:
* try to generate Tobias' smtpd.conf
* host a guix system is awesome party


There's a ton more in the task here:

Joshua
?