Message ID | 20230420144230.9392-1-tanguy@bioneland.org |
---|---|
State | New |
Headers | show |
Series | [bug#62969] home: Add msmtp service. | expand |
Hi Tanguy, On 2023-04-20 15:42, Tanguy Le Carrour wrote: > - one that I don't know how to solve > ``` > + ;; FIXME `In procedure every: Wrong type argument: #<syntax-transformer msmtp-account?>` > + ;(every msmtp-account? lst)) > ``` Place this after '(define-configuration mstmp-account ...)'. You might want to place this block before '(define-configuration msmtp-configuration ...)'. > +@deftp {Data Type} home-msmtp-configuration > +Available @code{home-msmtp-configuration} fields are: > + > +@table @asis > +@item @code{defaults} (type: msmtp-configuration) > +The configuration that will be set as default for all accounts. > + > +@item @code{accounts} (default: @code{()}) (type: list-of-msmtp-accounts) > +A list of @code{msmtp-account} records which contain information about > +all your accounts. > + > +@item @code{default-account} (type: maybe-string) > +Set the default account. > + > +@item @code{extra-content} (default: @code{""}) (type: raw-configuration-string) > +Extra content appended as-is to the configuration file. Run > +@command{man msmtp} for more information about the configuration file > +format. > + > +@end table > + > +@end deftp You should preserve the @c lines from configuration->documentation to make it clear that the block of text was generated. > + > +(define-module (gnu home services mail) > + #:use-module (guix gexp) > + #:use-module (gnu packages) > + #:use-module (gnu services) > + #:use-module (gnu services configuration) > + #:use-module (gnu home services) > + #:use-module (gnu home services shepherd) > + #:use-module (ice-9 string-fun) > + #:use-module (srfi srfi-26) > + #:export (home-msmtp-configuration > + home-msmtp-configuration? > + home-msmtp-service-type > + msmtp-account > + msmtp-configuration)) You should export the accessors for the fields. You can use this snippet within 'guix repl' to automate the typing for you: --8<---------------cut here---------------start------------->8--- (define (helper-configuration-exports fields) (map (lambda (s) (let* ((f (compose object->string configuration-field-getter)) (g (compose cadr string-tokenize)) (s* ((compose g f) s))) (string->symbol (substring s* 1 (string-contains s* "-procedure"))))) fields)) (define (helper-formatted-exports fields) (format #t "~{~a~%~}" (helper-configuration-exports fields))) --8<---------------cut here---------------end--------------->8--- Example usage: --8<---------------cut here---------------start------------->8--- ;; paste snippet above into repl scheme@(guix-user)> ,m (gnu services audio) scheme@(gnu services audio)> (helper-formatted-exports mpd-configuration-fields) mpd-configuration-user mpd-configuration-group mpd-configuration-shepherd-requirement mpd-configuration-environment-variables mpd-configuration-log-file mpd-configuration-log-level mpd-configuration-music-directory mpd-configuration-music-dir mpd-configuration-playlist-directory mpd-configuration-playlist-dir mpd-configuration-db-file mpd-configuration-state-file mpd-configuration-sticker-file mpd-configuration-default-port mpd-configuration-endpoints mpd-configuration-address mpd-configuration-database mpd-configuration-partitions mpd-configuration-neighbors mpd-configuration-inputs mpd-configuration-archive-plugins mpd-configuration-input-cache-size mpd-configuration-decoders mpd-configuration-resampler mpd-configuration-filters mpd-configuration-outputs mpd-configuration-playlist-plugins mpd-configuration-extra-options $1 = #t --8<---------------cut here---------------end--------------->8--- > + > +(define raw-configuration-string? string?) This isn't necessary, continued below. [1] > + > +(define (configuration-serialize-maybe-string field-name value) > + #~(if #$(maybe-value-set? value) > + (string-append #$(uglify-symbol field-name) " " #$value "\n") > + ""))> + > +(define (configuration-serialize-maybe-integer field-name value) > + #~(if #$(maybe-value-set? value) > + (string-append #$(uglify-symbol field-name) " " (number->string #$value) "\n") > + "")) > + > +(define (configuration-serialize-maybe-boolean field-name value) > + #~(if #$(maybe-value-set? value) > + (string-append #$(uglify-symbol field-name) " " (if #$value "on" "off") "\n") > + "")) You don't have to perform the maybe-value-set? checks, it is automatically done for you. The only cases where this isn't true is if you explicitly override the serializer in define-configuration. [2] > +(define (account-serialize-string field-name value) > + #~(string-append " " #$(uglify-symbol field-name) " " #$value "\n")) > + > +(define (account-serialize-string field-name value) > + #~(string-append " " #$(uglify-symbol field-name) " " #$value "\n")) Duplicated? > + > +(define (account-serialize-msmtp-configuration field-name value) > + ; FIXME Begin each line inside an account section with a space. > + #~(string-append #$(serialize-configuration value msmtp-configuration-fields))) This doesn't do anything and since it's a cosmetic change I'd just ignore it, since the file is managed with guix anyways. > +(define (home-configuration-serialize-default-account field-name value) > + #~(if #$(maybe-value-set? value) > + (string-append "\naccount default : " #$value "\n") > + "")) See [2] above. > +;; Source <https://marlam.de/msmtp/msmtp.html#Configuration-files>. > +(define-configuration msmtp-configuration > + (auth? > + maybe-boolean > + "Enable or disable authentication.") > + (tls? > + maybe-boolean > + "Enable or disable TLS (also known as SSL) for secured connections.") > + (tls-starttls > + maybe-boolean > + "Choose the TLS variant: start TLS from within the session (‘on’, default), > +or tunnel the session through TLS (‘off’).") > + (tls-trust-file > + maybe-string > + "Activate server certificate verification using a list of > +trusted Certification Authorities (CAs).") > + (logfile > + maybe-string > + "Enable logging to the specified file. An empty argument disables logging. > +The file name ‘-’ directs the log information to standard output.") > + (host > + maybe-string > + "The SMTP server to send the mail to.") > + (port > + maybe-integer > + "The port that the SMTP server listens on. The default is 25 (\"smtp\"), > +unless TLS without STARTTLS is used, in which case it is 465 (\"smtps\").") > + (user > + maybe-string > + "Set the user name for authentication.") > + (from > + maybe-string > + "Set the envelope-from address.") > + (passwordeval > + maybe-string > + "Set the password for authentication to the output (stdout) of the command cmd.") > + (extra-content > + (raw-configuration-string "") > + "Extra content appended as-is to the configuration block. Run > +@command{man msmtp} for more information about the configuration file > +format.") Instead of defining a raw-configuration-string? predicate, simply use string? and set the serializer to '(serializer my-custom-string-serializer)' or '(serializer (lambda ...))'. [1] > + (prefix configuration-)) These are poor prefix choices for a module named (gnu home services mail). If it were (gnu home services msmtp) or (gnu home services mail msmtp) it would be acceptable but a module named (gnu home services mail) is expected to eventually contain multiple services that have to co-exist. These prefixes are too non-specific and confusion prone for such circumstances. I'd set this to (prefix msmtp-configuration-). (the same logic applies to the remaining (prefix ...) lines) > + > +(define-configuration msmtp-account > + (name > + (string) > + "The unique name of the account." > + (serializer account-serialize-name)) > + (configuration > + (msmtp-configuration) > + "The configuration for this given account.") > + (prefix account-)) > + > +(define-configuration home-msmtp-configuration > + (defaults > + (msmtp-configuration (msmtp-configuration)) > + "The configuration that will be set as default for all accounts.") > + (accounts > + (list-of-msmtp-accounts '()) > + "A list of @code{msmtp-account} records which contain > +information about all your accounts.") > + (default-account > + maybe-string > + "Set the default account." > + (serializer home-configuration-serialize-default-account)) > + (extra-content > + (raw-configuration-string "") > + "Extra content appended as-is to the configuration file. Run > +@command{man msmtp} for more information about the configuration file > +format.") > + (prefix home-configuration-)) You might want to separate each field with a space to make things easier to read but this is optional. Cheers, Bruno
Hi Bruno, Thank you so much for you comments! I've applied (almost, see below) all of your suggestions and I will send a v2. Quoting Bruno Victal (2023-04-20 18:36:59) > On 2023-04-20 15:42, Tanguy Le Carrour wrote: > > +(define (configuration-serialize-maybe-string field-name value) > > + #~(if #$(maybe-value-set? value) > > + (string-append #$(uglify-symbol field-name) " " #$value "\n") > > + ""))> + > > +(define (configuration-serialize-maybe-integer field-name value) > > + #~(if #$(maybe-value-set? value) > > + (string-append #$(uglify-symbol field-name) " " (number->string #$value) "\n") > > + "")) > > + > > +(define (configuration-serialize-maybe-boolean field-name value) > > + #~(if #$(maybe-value-set? value) > > + (string-append #$(uglify-symbol field-name) " " (if #$value "on" "off") "\n") > > + "")) > You don't have to perform the maybe-value-set? checks, it is automatically done for you. > The only cases where this isn't true is if you explicitly override the serializer in > define-configuration. [2] This is the only thing I can't figure out how to make work?! When I remove the `(if #$(maybe-value-set? value) …)` I get the following error: ``` Backtrace: 10 (primitive-load "/gnu/store/ajcf46q8yr9sb9n90psa5ay96jw?") In ice-9/ports.scm: 433:17 9 (call-with-output-file _ _ #:binary _ #:encoding _) In ice-9/eval.scm: 159:9 8 (_ #(#(#<directory (guile-user) 7ffff3fd7c80>) #<outp?>)) 155:9 7 (_ #(#(#<directory (guile-user) 7ffff3fd7c80>) #<outp?>)) 173:39 6 (_ #(#(#<directory (guile-user) 7ffff3fd7c80>) #<outp?>)) 159:9 5 (_ #(#(#<directory (guile-user) 7ffff3fd7c80>) #<outp?>)) 173:55 4 (_ #(#(#<directory (guile-user) 7ffff3fd7c80>) #<outp?>)) 173:55 3 (_ #(#(#<directory (guile-user) 7ffff3fd7c80>) #<outp?>)) 279:15 2 (_ #(#(#<directory (guile-user) 7ffff3fd7c80>) #<outp?>)) 223:20 1 (proc #(#(#<directory (guile-user) 7ffff3fd7c80>) #<o?>)) In unknown file: 0 (%resolve-variable (7 . %unset-marker%) #<directory (gu?>) ERROR: In procedure %resolve-variable: Unbound variable: %unset-marker% ``` > > + (prefix configuration-)) > These are poor prefix choices for a module named (gnu home services mail). > If it were (gnu home services msmtp) or (gnu home services mail msmtp) it would be acceptable > but a module named (gnu home services mail) is expected to eventually contain multiple services that > have to co-exist. These prefixes are too non-specific and confusion prone for such circumstances. > > I'd set this to (prefix msmtp-configuration-). (the same logic applies to the remaining (prefix ...) lines) I totally agree! You guessed correctly, this home service was living inside `(bioneland home services msmtp)`, so the naming seemed to make sense at the time, but not any more! Thanks again for your time and help!
diff --git a/doc/guix.texi b/doc/guix.texi index adb1975935..5a1e215d17 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -114,6 +114,7 @@ Copyright @copyright{} 2022 Ivan Vilata-i-Balaguer@* Copyright @copyright{} 2023 Giacomo Leidi@* Copyright @copyright{} 2022 Antero Mejr@* Copyright @copyright{} 2023 Karl Hallsby +Copyright @copyright{} 2023 Tanguy Le Carrour Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or @@ -41880,6 +41881,7 @@ services)}. * Guix: Guix Home Services. Services for Guix. * Fonts: Fonts Home Services. Services for managing User's fonts. * Sound: Sound Home Services. Dealing with audio. +* Mail: Mail Home Services. Services for managing mail. * Messaging: Messaging Home Services. Services for managing messaging. * Media: Media Home Services. Services for managing media. @end menu @@ -43082,6 +43084,99 @@ Stopping the Shepherd service turns off broadcasting. This is the multicast address used by default by the two services above. @end defvar +@node Mail Home Services +@subsection Mail Home Services + +@cindex msmtp +@uref{https://marlam.de/msmtp, MSMTP} is an SMTP client. + +@deftp {Data Type} home-msmtp-configuration +Available @code{home-msmtp-configuration} fields are: + +@table @asis +@item @code{defaults} (type: msmtp-configuration) +The configuration that will be set as default for all accounts. + +@item @code{accounts} (default: @code{()}) (type: list-of-msmtp-accounts) +A list of @code{msmtp-account} records which contain information about +all your accounts. + +@item @code{default-account} (type: maybe-string) +Set the default account. + +@item @code{extra-content} (default: @code{""}) (type: raw-configuration-string) +Extra content appended as-is to the configuration file. Run +@command{man msmtp} for more information about the configuration file +format. + +@end table + +@end deftp + +@deftp {Data Type} msmtp-account +Available @code{msmtp-account} fields are: + +@table @asis +@item @code{name} (type: string) +The unique name of the account. + +@item @code{configuration} (type: msmtp-configuration) +The configuration for this given account. + +@end table + +@end deftp + +@deftp {Data Type} msmtp-configuration +Available @code{msmtp-configuration} fields are: + +@table @asis +@item @code{auth?} (type: maybe-boolean) +Enable or disable authentication. + +@item @code{tls?} (type: maybe-boolean) +Enable or disable TLS (also known as SSL) for secured connections. + +@item @code{tls-starttls} (type: maybe-boolean) +Choose the TLS variant: start TLS from within the session (‘on’, +default), or tunnel the session through TLS (‘off’). + +@item @code{tls-trust-file} (type: maybe-string) +Activate server certificate verification using a list of trusted +Certification Authorities (CAs). + +@item @code{logfile} (type: maybe-string) +Enable logging to the specified file. An empty argument disables +logging. The file name ‘-’ directs the log information to standard +output. + +@item @code{host} (type: maybe-string) +The SMTP server to send the mail to. + +@item @code{port} (type: maybe-integer) +The port that the SMTP server listens on. The default is 25 ("smtp"), +unless TLS without STARTTLS is used, in which case it is 465 ("smtps"). + +@item @code{user} (type: maybe-string) +Set the user name for authentication. + +@item @code{from} (type: maybe-string) +Set the envelope-from address. + +@item @code{passwordeval} (type: maybe-string) +Set the password for authentication to the output (stdout) of the +command cmd. + +@item @code{extra-content} (default: @code{""}) (type: raw-configuration-string) +Extra content appended as-is to the configuration block. Run +@command{man msmtp} for more information about the configuration file +format. + +@end table + +@end deftp + + @node Messaging Home Services @subsection Messaging Home Services diff --git a/gnu/home/services/mail.scm b/gnu/home/services/mail.scm new file mode 100644 index 0000000000..b31f68d2ca --- /dev/null +++ b/gnu/home/services/mail.scm @@ -0,0 +1,196 @@ +;;; GNU Guix --- Functional package management for GNU +;;; Copyright © 2023 Tanguy Le Carrour <tanguy@bioneland.org> +;;; +;;; This file is part of GNU Guix. +;;; +;;; GNU Guix is free software; you can redistribute it and/or modify it +;;; under the terms of the GNU General Public License as published by +;;; the Free Software Foundation; either version 3 of the License, or (at +;;; your option) any later version. +;;; +;;; GNU Guix is distributed in the hope that it will be useful, but +;;; WITHOUT ANY WARRANTY; without even the implied warranty of +;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;;; GNU General Public License for more details. +;;; +;;; You should have received a copy of the GNU General Public License +;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>. + +(define-module (gnu home services mail) + #:use-module (guix gexp) + #:use-module (gnu packages) + #:use-module (gnu services) + #:use-module (gnu services configuration) + #:use-module (gnu home services) + #:use-module (gnu home services shepherd) + #:use-module (ice-9 string-fun) + #:use-module (srfi srfi-26) + #:export (home-msmtp-configuration + home-msmtp-configuration? + home-msmtp-service-type + msmtp-account + msmtp-configuration)) + +(define raw-configuration-string? string?) + +(define-maybe string) +(define-maybe boolean) +(define-maybe integer) + +;; Serialization of 'msmtp'. +(define (uglify-symbol field-name) + (let* ((name (symbol->string field-name)) + (ugly-name (string-replace-substring name "-" "_"))) + (if (string-suffix? "?" ugly-name) + (string-drop-right ugly-name 1) + ugly-name))) + +(define (configuration-serialize-maybe-string field-name value) + #~(if #$(maybe-value-set? value) + (string-append #$(uglify-symbol field-name) " " #$value "\n") + "")) + +(define (configuration-serialize-maybe-integer field-name value) + #~(if #$(maybe-value-set? value) + (string-append #$(uglify-symbol field-name) " " (number->string #$value) "\n") + "")) + +(define (configuration-serialize-maybe-boolean field-name value) + #~(if #$(maybe-value-set? value) + (string-append #$(uglify-symbol field-name) " " (if #$value "on" "off") "\n") + "")) + +(define (configuration-serialize-raw-configuration-string field-name value) + #~(if #$(string=? value "") "" (string-append #$value "\n"))) + +(define (account-serialize-name field-name value) + #~(string-append "\naccount " #$value "\n")) + +(define (account-serialize-string field-name value) + #~(string-append " " #$(uglify-symbol field-name) " " #$value "\n")) + +(define (account-serialize-string field-name value) + #~(string-append " " #$(uglify-symbol field-name) " " #$value "\n")) + +(define (account-serialize-msmtp-configuration field-name value) + ; FIXME Begin each line inside an account section with a space. + #~(string-append #$(serialize-configuration value msmtp-configuration-fields))) + +(define (home-configuration-serialize-list-of-msmtp-accounts field-name value) + #~(string-append #$@(map (cut serialize-configuration <> msmtp-account-fields) + value))) + +(define (home-configuration-serialize-msmtp-configuration field-name value) + #~(string-append "defaults\n" + #$(serialize-configuration value msmtp-configuration-fields))) + +(define (home-configuration-serialize-string field-name value) + #~(string-append #$(uglify-symbol field-name) " " #$value "\n")) + +(define (home-configuration-serialize-default-account field-name value) + #~(if #$(maybe-value-set? value) + (string-append "\naccount default : " #$value "\n") + "")) + +(define (home-configuration-serialize-raw-configuration-string field-name value) + #~(if #$(string=? value "") "" (string-append #$value "\n"))) + +;; Configuration of 'msmtp'. +(define (list-of-msmtp-accounts? lst) + ;; FIXME `In procedure every: Wrong type argument: #<syntax-transformer msmtp-account?>` + ;(every msmtp-account? lst)) + #t) + +;; Source <https://marlam.de/msmtp/msmtp.html#Configuration-files>. +(define-configuration msmtp-configuration + (auth? + maybe-boolean + "Enable or disable authentication.") + (tls? + maybe-boolean + "Enable or disable TLS (also known as SSL) for secured connections.") + (tls-starttls + maybe-boolean + "Choose the TLS variant: start TLS from within the session (‘on’, default), +or tunnel the session through TLS (‘off’).") + (tls-trust-file + maybe-string + "Activate server certificate verification using a list of +trusted Certification Authorities (CAs).") + (logfile + maybe-string + "Enable logging to the specified file. An empty argument disables logging. +The file name ‘-’ directs the log information to standard output.") + (host + maybe-string + "The SMTP server to send the mail to.") + (port + maybe-integer + "The port that the SMTP server listens on. The default is 25 (\"smtp\"), +unless TLS without STARTTLS is used, in which case it is 465 (\"smtps\").") + (user + maybe-string + "Set the user name for authentication.") + (from + maybe-string + "Set the envelope-from address.") + (passwordeval + maybe-string + "Set the password for authentication to the output (stdout) of the command cmd.") + (extra-content + (raw-configuration-string "") + "Extra content appended as-is to the configuration block. Run +@command{man msmtp} for more information about the configuration file +format.") + (prefix configuration-)) + +(define-configuration msmtp-account + (name + (string) + "The unique name of the account." + (serializer account-serialize-name)) + (configuration + (msmtp-configuration) + "The configuration for this given account.") + (prefix account-)) + +(define-configuration home-msmtp-configuration + (defaults + (msmtp-configuration (msmtp-configuration)) + "The configuration that will be set as default for all accounts.") + (accounts + (list-of-msmtp-accounts '()) + "A list of @code{msmtp-account} records which contain +information about all your accounts.") + (default-account + maybe-string + "Set the default account." + (serializer home-configuration-serialize-default-account)) + (extra-content + (raw-configuration-string "") + "Extra content appended as-is to the configuration file. Run +@command{man msmtp} for more information about the configuration file +format.") + (prefix home-configuration-)) + +(define (home-msmtp-files-service config) + (list + `(".config/msmtp/config" + ,(mixed-text-file "config" + (serialize-configuration config home-msmtp-configuration-fields))))) + +(define (home-msmtp-profile-service config) + (specifications->packages (list "msmtp"))) + +(define home-msmtp-service-type + (service-type (name 'home-msmtp) + (extensions + (list + (service-extension + home-profile-service-type + home-msmtp-profile-service) + (service-extension + home-files-service-type + home-msmtp-files-service))) + (default-value (home-msmtp-configuration)) + (description "Configures msmtp."))) diff --git a/gnu/local.mk b/gnu/local.mk index 01ffe3fdb6..3f57ca3c98 100644 --- a/gnu/local.mk +++ b/gnu/local.mk @@ -93,6 +93,7 @@ GNU_SYSTEM_MODULES = \ %D%/home/services/fontutils.scm \ %D%/home/services/gnupg.scm \ %D%/home/services/guix.scm \ + %D%/home/services/mail.scm \ %D%/home/services/media.scm \ %D%/home/services/messaging.scm \ %D%/home/services/pm.scm \