all messages for Guix-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
From: Nils Landt <nils@landt.email>
To: 66557@debbugs.gnu.org
Cc: "Nils Landt" <nils.landt@nlsoft.de>
Subject: [bug#66557] [PATCH] home: services: Add goimapnotify service.
Date: Sun, 26 Nov 2023 11:31:03 +0100	[thread overview]
Message-ID: <dd6cf27935471a6b96dc319fde798f97547f6fa2.1700994663.git.nils@landt.email> (raw)
In-Reply-To: <c9d8798670448a18779e3c24b9b8a88902942936.1697378478.git.nils@landt.email>

From: Nils Landt <nils.landt@nlsoft.de>

* gnu/home/services/mail.scm: (home-goimapnotify-configuration,
home-goimapnotify-service-type, goimapnotify-account,
goimapnotify-tls-options): New variables.
(goimapnotify-format-field, goimapnotify-serialize-field,  goimapnotify-serialize-goimapnotify-tls-options): New procedures.
* doc/guix.texi (Mail Home Services): New node.
---
 doc/guix.texi              | 139 ++++++++++++++++++++++
 gnu/home/services/mail.scm | 232 ++++++++++++++++++++++++++++++++++++-
 2 files changed, 370 insertions(+), 1 deletion(-)

diff --git a/doc/guix.texi b/doc/guix.texi
index 1fd2e21608..aed15685e5 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -44996,6 +44996,145 @@ Mail Home Services
 The @code{(gnu home services mail)} module provides services that help
 you set up the tools to work with emails in your home environment.
  
+@cindex goimapnotify
+@uref{https://gitlab.com/shackra/goimapnotify, goimapnotify} watches your
+mailbox(es) and executes a script on (new / deleted / updated) messages.
+
+Using @code{home-goimapnotify-configuration}, you can generate a config file
+for each account you want to watch (file name relative to @code{$HOME}), e.g.:
+
+@lisp
+(simple-service 'mail-imapnotify-config-examples
+                home-goimapnotify-service-type
+                (home-goimapnotify-configuration
+                  (accounts (list
+                              `(".config/goimapnotify/private-account.conf"
+                                ,(goimapnotify-account
+                                    (host "imap.example.org")
+                                    (port 993)
+                                    (tls #t)
+                                    (username "example")
+                                    (password-cmd
+                                      (file-append password-store
+                                        "/bin/pass my-private-email-account")
+                                    (on-new-mail
+                                      (file-append mbsync "/bin/mbsync private-account"))
+                                    (on-new-mail-post
+                                      (file-append mu "/bin/mu index"))
+                                    (boxes '("INBOX"))))
+                              `(".config/goimapnotify/work-account.conf"
+                                ,(goimapnotify-account
+                                    (host "imap.work.example.org")
+                                    (port 993)
+                                    (tls #t)
+                                    (username "example")
+                                    (password "12345")
+                                    (on-new-mail
+                                      (file-append mbsync "/bin/mbsync work-account"))
+                                    (on-new-mail-post
+                                      "notify-send 'New mail'")
+                                    (boxes '("INBOX"
+                                             "On Call")))))))))
+@end lisp
+
+Note: to utilize the config files, you need to start a separate goimapnotify
+process for each one.  Continuing the example above:
+@code{goimapnotify -conf "$HOME/.config/goimapnotify/private-account.conf"} and
+@code{goimapnotify -conf "$HOME/.config/goimapnotify/work-account.conf"}.
+
+@c %start of fragment
+@deftp {Data Type} home-goimapnotify-configuration
+Available @code{home-goimapnotify-configuration} fields are:
+
+@table @asis
+@item @code{accounts} (default: @code{()}) (type: list-of-goimapnotify-accounts)
+List of accounts that goimapnotify should watch.  For each account, a
+separate configuration file will be generated.
+@end table
+
+@end deftp
+@c %end of fragment
+
+@c %start of fragment
+
+@deftp {Data Type} goimapnotify-account
+Available @code{goimapnotify-account} fields are:
+
+@table @asis
+@item @code{host} (type: maybe-string)
+Address of the IMAP server to connect to.
+
+@item @code{host-cmd} (type: maybe-string-or-file-like)
+An executable or script that retrieves your host from somewhere, we
+cannot pass arguments to this command from stdin.
+
+@item @code{port} (type: maybe-integer)
+Port of the IMAP server to connect to.
+
+@item @code{tls?} (type: maybe-boolean)
+
+Use TLS?
+
+@item @code{tls-options} (type: maybe-goimapnotify-tls-options)
+Option(s) for the TLS connection.  Currently, only one option is
+supported.
+
+@item @code{username} (type: maybe-string)
+Username for authentication.
+
+@item @code{username-cmd} (type: maybe-string-or-file-like)
+An executable or script that retrieves your username from
+somewhere, we cannot pass arguments to this command from stdin.
+
+@item @code{password} (type: maybe-string)
+Password for authentication.
+
+@item @code{password-cmd} (type:
+ maybe-string-or-file-like)
+An executable or script that retrieves your password from somewhere, we
+cannot pass arguments to this command from stdin.
+
+@item @code{xoauth2?}
+(type: maybe-boolean)
+You can also use xoauth2 instead of password based authentication by
+setting the xoauth2 option to true and the output of a tool which can
+provide xoauth2 encoded tokens in passwordCmd.  Examples:
+@uref{https://github.com/google/oauth2l,Google oauth2l} or
+@uref{https://github.com/harishkrupo/oauth2ms,xoauth2 fetcher for O36
+5}.
+
+@item @code{on-new-mail} (type: maybe-string-or-file-like)
+An executable or script to run when new mail has arrived.
+
+@item @code{on-new-mail-post} (type: maybe-string-or-file-like)
+An executable or script to run after onNewMail has ran.
+
+@item @code{wait} (type: maybe-integer)
+The delay in seconds before the mail syncing is triggered.
+
+@item @code{boxes} (type: maybe-list-of-strings)
+Mailboxes to watch.
+
+@end table
+
+@end deftp
+
+@c %end of fragment
+
+@c %start of fragment
+
+@deftp {Data Type} goimapnotify-tls-options
+Available @code{goimapnotify-tls-options} fields are:
+
+@table @asis
+@item @code{reject-unauthorized?} (type: maybe-boolean)
+Skip verifying CA server identify?
+
+@end table
+
+@end deftp
+@c %end of fragment
+
 @cindex msmtp
 @uref{https://marlam.de/msmtp, MSMTP} is a @acronym{SMTP, Simple Mail
 Transfer Protocol} client.  It sends mail to a predefined SMTP server
diff --git a/gnu/home/services/mail.scm b/gnu/home/services/mail.scm
index 5445c82c67..b86a787963 100644
--- a/gnu/home/services/mail.scm
+++ b/gnu/home/services/mail.scm
@@ -18,15 +18,44 @@
 
 (define-module (gnu home services mail)
   #:use-module (guix gexp)
+  #:use-module (guix records)
   #:use-module (gnu services)
   #:use-module (gnu services configuration)
   #:use-module (gnu home services)
   #:use-module (gnu home services shepherd)
+  #:use-module (gnu home services utils)
   #:use-module (gnu packages mail)
+  #:use-module (gnu packages guile)
+  #:use-module (ice-9 match)
   #:use-module (ice-9 string-fun)
   #:use-module (srfi srfi-1)
   #:use-module (srfi srfi-26)
-  #:export (home-msmtp-configuration
+  #:export (home-goimapnotify-configuration
+            home-goimapnotify-configuration-fields
+            home-goimapnotify-configuration?
+            home-goimapnotify-configuration-accounts
+            home-goimapnotify-service-type
+            goimapnotify-account
+            goimapnotify-account-fields
+            goimapnotify-account-host
+            goimapnotify-account-host-cmd
+            goimapnotify-account-port
+            goimapnotify-account-tls
+            goimapnotify-account-tls-options
+            goimapnotify-account-username
+            goimapnotify-account-username-cmd
+            goimapnotify-account-password
+            goimapnotify-account-password-cmd
+            goimapnotify-account-xoauth2
+            goimapnotify-account-on-new-mail
+            goimapnotify-account-on-new-mail-post
+            goimapnotify-account-wait
+            goimapnotify-account-boxes
+            goimapnotify-tls-options
+            goimapnotify-tls-options-fields
+            goimapnotify-tls-options-reject-unauthorized
+
+            home-msmtp-configuration
             home-msmtp-configuration?
             home-msmtp-configuration-defaults
             home-msmtp-configuration-accounts
@@ -220,3 +249,204 @@ (define home-msmtp-service-type
                 (description "Configure msmtp, a simple
 @acronym{SMTP, Simple Mail Transfer Protocol} client that can relay email
 to SMTP servers.")))
+
+; Configuration for goimapnotify from (gnu packages mail)
+
+(define-maybe string)
+(define-maybe integer)
+(define-maybe boolean)
+(define-maybe list-of-strings)
+(define-maybe string-or-file-like)
+
+(define (string-or-file-like? value)
+  (or (string? value)
+      (file-like? value)))
+
+(define (goimapnotify-format-field field-name)
+  (object->camel-case-string
+    (string-trim-right
+      (object->string field-name)
+      #\?)))
+
+(define (goimapnotify-serialize-field field-name value)
+  "This is converted to JSON later, so we don't return a string here"
+  #~(#$(goimapnotify-format-field field-name) . #$value))
+
+(define (goimapnotify-serialize-string-or-file-like field-name value)
+  (goimapnotify-serialize-string field-name value))
+
+(define (goimapnotify-maybe-serialize field-name value serialization-function)
+  (if (maybe-value-set? value)
+    (serialization-function field-name value)
+    ""))
+
+(define (goimapnotify-serialize-maybe-string-or-file-like field-name value)
+ (goimapnotify-maybe-serialize field-name value
+                               goimapnotify-serialize-string-or-file-like))
+
+(define goimapnotify-serialize-string goimapnotify-serialize-field)
+(define (goimapnotify-serialize-maybe-string field-name value)
+ (goimapnotify-maybe-serialize field-name value goimapnotify-serialize-string))
+
+(define (goimapnotify-serialize-maybe-integer field-name value)
+ (goimapnotify-maybe-serialize field-name value goimapnotify-serialize-integer))
+(define goimapnotify-serialize-integer goimapnotify-serialize-field)
+
+(define (goimapnotify-serialize-maybe-boolean field-name value)
+  (goimapnotify-maybe-serialize field-name value goimapnotify-serialize-boolean))
+(define goimapnotify-serialize-boolean goimapnotify-serialize-field)
+
+(define (goimapnotify-serialize-maybe-list-of-strings field-name value)
+  (goimapnotify-maybe-serialize field-name value goimapnotify-serialize-list-of-strings))
+(define (goimapnotify-serialize-list-of-strings field-name value)
+  (goimapnotify-serialize-field field-name (list->array 1 value)))
+
+(define (goimapnotify-serialize-maybe-goimapnotify-tls-options field-name config)
+  (goimapnotify-maybe-serialize field-name config
+                                goimapnotify-serialize-goimapnotify-tls-options))
+
+(define (goimapnotify-serialize-goimapnotify-tls-options field-name config)
+  (goimapnotify-serialize-field
+    field-name
+    (prepare-configuration-for-json config goimapnotify-tls-options-fields)))
+
+(define (prepare-configuration-for-json config fields)
+  "Convert the configuration to the format expected by guile-json.
+  Unset maybe-values do not appear in the configuration file."
+  (fold
+    (lambda (field accu)
+      (let ((value ((configuration-field-getter field) config)))
+        (append accu
+          (if (maybe-value-set? value)
+            (list ((configuration-field-serializer field)
+                   (configuration-field-name field)
+                   value))
+            '()))))
+    '()
+    fields))
+
+(define-configuration goimapnotify-tls-options
+                      (reject-unauthorized?
+                        maybe-boolean
+                        "Skip verifying CA server identify?")
+                      (prefix goimapnotify-))
+
+(define-maybe goimapnotify-tls-options)
+
+; See https://gitlab.com/shackra/goimapnotify/-/blob/423f0e65350f7e042edbd2c373f252c5a0d31dc2/config.go#L46-62
+(define-configuration goimapnotify-account
+                      (host
+                        maybe-string
+                        "Address of the IMAP server to connect to.")
+                      (host-cmd
+                        maybe-string-or-file-like
+                        "An executable or script that retrieves your host from somewhere,
+                        we cannot pass arguments to this command from stdin.")
+                      (port
+                        maybe-integer
+                        "Port of the IMAP server to connect to.")
+                      (tls?
+                        maybe-boolean
+                        "Use TLS?")
+                      (tls-options
+                        maybe-goimapnotify-tls-options
+                        "Option(s) for the TLS connection. Currently, only one option is
+                        supported.")
+                      (username
+                        maybe-string
+                        "Username for authentication.")
+                      (username-cmd
+                        maybe-string-or-file-like
+                        "An executable or script that retrieves your username from
+                        somewhere, we cannot pass arguments to this command from stdin.")
+                      (password
+                        maybe-string
+                        "Password for authentication.")
+                      (password-cmd
+                        maybe-string-or-file-like
+                        "An executable or script that retrieves your password from
+                        somewhere, we cannot pass arguments to this command from stdin.")
+                      (xoauth2?
+                        maybe-boolean
+                        "You can also use xoauth2 instead of password based authentication
+                        by setting the xoauth2 option to true and the output of a tool
+                        which can provide xoauth2 encoded tokens in passwordCmd.
+                        Examples: @url{https://github.com/google/oauth2l, Google oauth2l}
+                        or
+                        @url{https://github.com/harishkrupo/oauth2ms, xoauth2 fetcher for O365}.")
+                      (on-new-mail
+                        maybe-string-or-file-like
+                        "An executable or script to run when new mail has arrived.")
+                      (on-new-mail-post
+                        maybe-string-or-file-like
+                        "An executable or script to run after on-new-mail has ran.")
+                      (wait
+                        maybe-integer
+                        "The delay in seconds before the mail syncing is triggered.")
+                      (boxes
+                        maybe-list-of-strings
+                        "Mailboxes to watch.")
+                      (prefix goimapnotify-))
+
+(define (list-of-goimapnotify-accounts? lst)
+  "List is in the form of '((file-name file-like))"
+  (every (compose goimapnotify-account? second) lst))
+
+(define-configuration/no-serialization home-goimapnotify-configuration
+                                       (accounts
+                                         (list-of-goimapnotify-accounts '())
+                                         "List of accounts that goimapnotify should watch.
+                                         For each account, a separate configuration file
+                                         will be generated."))
+
+(define (home-goimapnotify-extension old-config extensions)
+  (match-record old-config <home-goimapnotify-configuration>
+                (accounts)
+                (home-goimapnotify-configuration
+                  (inherit old-config)
+                  (accounts (append accounts
+                                    (append-map
+                                      home-goimapnotify-configuration-accounts
+                                      extensions))))))
+
+(define (goimapnotify-files config)
+  (define* (account->json account-config-and-path)
+    (match
+      account-config-and-path
+      ((path account-config)
+       (let ((prepared-config
+               (prepare-configuration-for-json
+                 account-config
+                 goimapnotify-account-fields)))
+         `((,path
+            ,(computed-file
+               (string-append
+                 "mail-imapnotify-config-"
+                 (goimapnotify-account-host account-config))
+               (with-extensions (list guile-json-4)
+                   #~(begin
+                       (use-modules (json builder))
+
+                       (with-output-to-file #$output
+                         (lambda ()
+                           (scm->json '(#$@prepared-config)
+                                      #:pretty #t))))))))))))
+
+  (match-record config <home-goimapnotify-configuration>
+                (accounts)
+                (append-map
+                  (cut account->json <>)
+                  accounts)))
+
+(define home-goimapnotify-service-type
+  (service-type
+    (name 'home-goimapnotify-service)
+    (extensions
+      (list (service-extension
+              home-files-service-type
+              goimapnotify-files)))
+    (compose identity)
+    (extend home-goimapnotify-extension)
+    (default-value (home-goimapnotify-configuration))
+    (description "Configure goimapnotify to execute scripts on IMAP
+                 mailbox changes.")))

base-commit: 513bf164592e2b44e3e556cc5099a19bd6977790
-- 
2.41.0





  parent reply	other threads:[~2023-11-26 10:33 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-10-15 14:01 [bug#66557] [PATCH] home: services: Add goimapnotify service Nils Landt
2023-11-02  8:55 ` Ricardo Wurmus
2023-11-20 17:16 ` Bruno Victal
2023-11-21 15:25   ` Nils Landt
2023-11-28 20:37     ` Bruno Victal
2023-11-21 15:30 ` Nils Landt
2023-11-26 10:31 ` Nils Landt [this message]
2023-11-26 11:14 ` Nils Landt
2023-11-29 17:20   ` Bruno Victal
2023-12-03 15:56     ` Nils Landt
2023-12-03 15:53 ` Nils Landt

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=dd6cf27935471a6b96dc319fde798f97547f6fa2.1700994663.git.nils@landt.email \
    --to=nils@landt.email \
    --cc=66557@debbugs.gnu.org \
    --cc=nils.landt@nlsoft.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this external index

	https://git.savannah.gnu.org/cgit/guix.git

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.