neomutt: Initial IMAP support (#4597)
neomutt: Updated options and added tests neomutt: Added test for individual mailbox type neomutt: Formatted code neomutt: Enable ssl_force_tls based on IMAP instead of SMTP neomutt: Applied suggestions from @chayleaf neomutt: fix breaking tests
This commit is contained in:
parent
bfd0ae29a8
commit
a09cfdbaf1
|
@ -17,6 +17,14 @@ let
|
|||
default = null;
|
||||
description = "Name to display";
|
||||
};
|
||||
|
||||
type = mkOption {
|
||||
type = types.nullOr (types.enum [ "maildir" "imap" ]);
|
||||
example = "imap";
|
||||
default = null;
|
||||
description =
|
||||
"Whether this mailbox is a maildir folder or an IMAP mailbox";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -75,6 +83,14 @@ in {
|
|||
description = "Use a different name as mailbox name";
|
||||
};
|
||||
|
||||
mailboxType = mkOption {
|
||||
type = types.enum [ "maildir" "imap" ];
|
||||
default = "maildir";
|
||||
example = "imap";
|
||||
description =
|
||||
"Whether this account uses maildir folders or IMAP mailboxes";
|
||||
};
|
||||
|
||||
extraMailboxes = mkOption {
|
||||
type = with types; listOf (either str (submodule extraMailboxOptions));
|
||||
default = [ ];
|
||||
|
|
|
@ -8,6 +8,59 @@ let
|
|||
neomuttAccounts =
|
||||
filter (a: a.neomutt.enable) (attrValues config.accounts.email.accounts);
|
||||
|
||||
accountCommandNeeded = any (a:
|
||||
a.neomutt.enable && (a.neomutt.mailboxType == "imap"
|
||||
|| (any (m: !isString m && m.type == "imap") a.neomutt.extraMailboxes)))
|
||||
(attrValues config.accounts.email.accounts);
|
||||
|
||||
accountCommand = let
|
||||
imapAccounts = filter (a:
|
||||
a.neomutt.enable && a.imap.host != null && a.userName != null
|
||||
&& a.passwordCommand != null) (attrValues config.accounts.email.accounts);
|
||||
accountCase = account:
|
||||
let passwordCmd = toString account.passwordCommand;
|
||||
in ''
|
||||
${account.userName}@${account.imap.host})
|
||||
found=1
|
||||
username="${account.userName}"
|
||||
password="$(${passwordCmd})"
|
||||
;;'';
|
||||
in pkgs.writeShellScriptBin "account-command.sh" ''
|
||||
# Automatically set login variables based on the current account.
|
||||
# This requires NeoMutt >= 2022-05-16
|
||||
|
||||
while [ ! -z "$1" ]; do
|
||||
case "$1" in
|
||||
--hostname)
|
||||
shift
|
||||
hostname="$1"
|
||||
;;
|
||||
--username)
|
||||
shift
|
||||
username="$1@"
|
||||
;;
|
||||
--type)
|
||||
shift
|
||||
type="$1"
|
||||
;;
|
||||
*)
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
found=
|
||||
case "''${username}''${hostname}" in
|
||||
${concatMapStringsSep "\n" accountCase imapAccounts}
|
||||
esac
|
||||
|
||||
if [ -n "$found" ]; then
|
||||
echo "username: $username"
|
||||
echo "password: $password"
|
||||
fi
|
||||
'';
|
||||
|
||||
sidebarModule = types.submodule {
|
||||
options = {
|
||||
enable = mkEnableOption "sidebar support";
|
||||
|
@ -101,6 +154,21 @@ let
|
|||
|
||||
accountFilename = account: config.xdg.configHome + "/neomutt/" + account.name;
|
||||
|
||||
accountRootIMAP = account:
|
||||
let
|
||||
userName =
|
||||
lib.optionalString (account.userName != null) "${account.userName}@";
|
||||
port = lib.optionalString (account.imap.port != null)
|
||||
":${toString account.imap.port}";
|
||||
protocol = if account.imap.tls.enable then "imaps" else "imap";
|
||||
in "${protocol}://${userName}${account.imap.host}${port}";
|
||||
|
||||
accountRoot = account:
|
||||
if account.neomutt.mailboxType == "imap" then
|
||||
accountRootIMAP account
|
||||
else
|
||||
account.maildir.absPath;
|
||||
|
||||
genCommonFolderHooks = account:
|
||||
with account; {
|
||||
from = "'${address}'";
|
||||
|
@ -128,12 +196,12 @@ let
|
|||
smtp_pass = ''"`${passCmd}`"'';
|
||||
};
|
||||
|
||||
genMaildirAccountConfig = account:
|
||||
genAccountConfig = account:
|
||||
with account;
|
||||
let
|
||||
folderHook = mapAttrsToList setOption (genCommonFolderHooks account
|
||||
// optionalAttrs cfg.changeFolderWhenSourcingAccount {
|
||||
folder = "'${account.maildir.absPath}'";
|
||||
folder = "'${accountRoot account}'";
|
||||
});
|
||||
in ''
|
||||
${concatStringsSep "\n" folderHook}
|
||||
|
@ -145,29 +213,40 @@ let
|
|||
"mailboxes"
|
||||
else
|
||||
''named-mailboxes "${account.neomutt.mailboxName}"'';
|
||||
extraMailboxes = concatMapStringsSep "\n" (extra:
|
||||
if isString extra then
|
||||
''mailboxes "${account.maildir.absPath}/${extra}"''
|
||||
else if extra.name == null then
|
||||
''mailboxes "${account.maildir.absPath}/${extra.mailbox}"''
|
||||
mailroot = accountRoot account;
|
||||
hookName = if account.neomutt.mailboxType == "imap" then
|
||||
"account-hook"
|
||||
else
|
||||
''
|
||||
named-mailboxes "${extra.name}" "${account.maildir.absPath}/${extra.mailbox}"'')
|
||||
"folder-hook";
|
||||
extraMailboxes = concatMapStringsSep "\n" (extra:
|
||||
let
|
||||
mailboxroot = if !isString extra && extra.type == "imap" then
|
||||
accountRootIMAP account
|
||||
else if !isString extra && extra.type == "maildir" then
|
||||
account.maildir.absPath
|
||||
else
|
||||
mailroot;
|
||||
in if isString extra then
|
||||
''mailboxes "${mailboxroot}/${extra}"''
|
||||
else if extra.name == null then
|
||||
''mailboxes "${mailboxroot}/${extra.mailbox}"''
|
||||
else
|
||||
''named-mailboxes "${extra.name}" "${mailboxroot}/${extra.mailbox}"'')
|
||||
account.neomutt.extraMailboxes;
|
||||
in with account; ''
|
||||
# register account ${name}
|
||||
${mailboxes} "${maildir.absPath}/${folders.inbox}"
|
||||
${mailboxes} "${mailroot}/${folders.inbox}"
|
||||
${extraMailboxes}
|
||||
folder-hook ${maildir.absPath}/ " \
|
||||
${hookName} ${mailroot}/ " \
|
||||
source ${accountFilename account} "
|
||||
'';
|
||||
|
||||
mraSection = account:
|
||||
with account;
|
||||
if account.maildir != null then
|
||||
genMaildirAccountConfig account
|
||||
if account.imap.host != null || account.maildir != null then
|
||||
genAccountConfig account
|
||||
else
|
||||
throw "Only maildir is supported at the moment";
|
||||
throw "Only maildir and IMAP is supported at the moment";
|
||||
|
||||
optionsStr = attrs: concatStringsSep "\n" (mapAttrsToList setOption attrs);
|
||||
|
||||
|
@ -219,7 +298,7 @@ let
|
|||
in ''
|
||||
# Generated by Home Manager.
|
||||
set ssl_force_tls = ${
|
||||
lib.hm.booleans.yesNo (smtp.tls.enable || smtp.tls.useStartTls)
|
||||
lib.hm.booleans.yesNo (imap.tls.enable || imap.tls.useStartTls)
|
||||
}
|
||||
set certificate_file=${toString config.accounts.email.certificatesFile}
|
||||
|
||||
|
@ -366,7 +445,11 @@ in {
|
|||
"source ${pkgs.neomutt}/share/doc/neomutt/vim-keys/vim-keys.rc"}
|
||||
|
||||
# Register accounts
|
||||
${concatMapStringsSep "\n" registerAccount neomuttAccounts}
|
||||
${
|
||||
optionalString (accountCommandNeeded) ''
|
||||
set account_command = '${accountCommand}/bin/account-command.sh'
|
||||
''
|
||||
}${concatMapStringsSep "\n" registerAccount neomuttAccounts}
|
||||
|
||||
# Source primary account
|
||||
source ${accountFilename primary}
|
||||
|
|
39
tests/modules/programs/neomutt/account-command.sh-expected
Normal file
39
tests/modules/programs/neomutt/account-command.sh-expected
Normal file
|
@ -0,0 +1,39 @@
|
|||
#!/nix/store/00000000000000000000000000000000-bash/bin/bash
|
||||
# Automatically set login variables based on the current account.
|
||||
# This requires NeoMutt >= 2022-05-16
|
||||
|
||||
while [ ! -z "$1" ]; do
|
||||
case "$1" in
|
||||
--hostname)
|
||||
shift
|
||||
hostname="$1"
|
||||
;;
|
||||
--username)
|
||||
shift
|
||||
username="$1@"
|
||||
;;
|
||||
--type)
|
||||
shift
|
||||
type="$1"
|
||||
;;
|
||||
*)
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
found=
|
||||
case "${username}${hostname}" in
|
||||
home.manager@imap.example.com)
|
||||
found=1
|
||||
username="home.manager"
|
||||
password="$(password-command)"
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ -n "$found" ]; then
|
||||
echo "username: $username"
|
||||
echo "password: $password"
|
||||
fi
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
{
|
||||
neomutt-simple = ./neomutt.nix;
|
||||
neomutt-with-msmtp = ./neomutt-with-msmtp.nix;
|
||||
neomutt-with-imap = ./neomutt-with-imap.nix;
|
||||
neomutt-not-primary = ./neomutt-not-primary.nix;
|
||||
neomutt-with-binds = ./neomutt-with-binds.nix;
|
||||
neomutt-with-binds-with-warning = ./neomutt-with-binds-with-warning.nix;
|
||||
|
@ -9,6 +10,7 @@
|
|||
neomutt-with-gpg = ./neomutt-with-gpg.nix;
|
||||
neomutt-no-folder-change = ./neomutt-no-folder-change.nix;
|
||||
neomutt-with-named-mailboxes = ./neomutt-with-named-mailboxes.nix;
|
||||
neomutt-with-imap-type-mailboxes = ./neomutt-with-imap-type-mailboxes.nix;
|
||||
neomutt-with-signature = ./neomutt-with-signature.nix;
|
||||
neomutt-with-signature-command = ./neomutt-with-signature-command.nix;
|
||||
neomutt-with-starttls = ./neomutt-with-starttls.nix;
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
# Generated by Home Manager.
|
||||
set ssl_force_tls = yes
|
||||
set certificate_file=/etc/ssl/certs/ca-certificates.crt
|
||||
|
||||
# GPG section
|
||||
set crypt_use_gpgme = yes
|
||||
set crypt_autosign = no
|
||||
set crypt_opportunistic_encrypt = no
|
||||
set pgp_use_gpg_agent = yes
|
||||
set mbox_type = Maildir
|
||||
set sort = "threads"
|
||||
|
||||
# MTA section
|
||||
set smtp_pass="`password-command`"
|
||||
set smtp_url='smtps://home.manager@smtp.example.com'
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# MRA section
|
||||
set folder='imaps://home.manager@imap.example.com:993'
|
||||
set from='hm@example.com'
|
||||
set postponed='+Drafts'
|
||||
set realname='H. M. Test'
|
||||
set record='+Sent'
|
||||
set spoolfile='+Inbox'
|
||||
set trash='+Trash'
|
||||
|
||||
|
||||
# Extra configuration
|
||||
color status cyan default
|
||||
|
||||
|
||||
unset signature
|
|
@ -0,0 +1,34 @@
|
|||
# Generated by Home Manager.
|
||||
set header_cache = "/home/hm-user/.cache/neomutt/headers/"
|
||||
set message_cachedir = "/home/hm-user/.cache/neomutt/messages/"
|
||||
set editor = "$EDITOR"
|
||||
set implicit_autoview = yes
|
||||
|
||||
alternative_order text/enriched text/plain text
|
||||
|
||||
set delete = yes
|
||||
|
||||
# Binds
|
||||
|
||||
|
||||
# Macros
|
||||
|
||||
|
||||
|
||||
|
||||
# Register accounts
|
||||
set account_command = '/nix/store/00000000000000000000000000000000-account-command.sh/bin/account-command.sh'
|
||||
# register account hm@example.com
|
||||
mailboxes "imaps://home.manager@imap.example.com:993/Inbox"
|
||||
|
||||
account-hook imaps://home.manager@imap.example.com:993/ " \
|
||||
source /home/hm-user/.config/neomutt/hm@example.com "
|
||||
|
||||
|
||||
# Source primary account
|
||||
source /home/hm-user/.config/neomutt/hm@example.com
|
||||
|
||||
# Extra configuration
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
# Generated by Home Manager.
|
||||
set header_cache = "/home/hm-user/.cache/neomutt/headers/"
|
||||
set message_cachedir = "/home/hm-user/.cache/neomutt/messages/"
|
||||
set editor = "$EDITOR"
|
||||
set implicit_autoview = yes
|
||||
|
||||
alternative_order text/enriched text/plain text
|
||||
|
||||
set delete = yes
|
||||
|
||||
# Binds
|
||||
|
||||
|
||||
# Macros
|
||||
|
||||
|
||||
|
||||
|
||||
# Register accounts
|
||||
set account_command = '/nix/store/00000000000000000000000000000000-account-command.sh/bin/account-command.sh'
|
||||
# register account hm@example.com
|
||||
named-mailboxes "someCustomName" "/home/hm-user/Mail/hm@example.com/Inbox"
|
||||
mailboxes "/home/hm-user/Mail/hm@example.com/Sent"
|
||||
named-mailboxes "Spam" "imaps://home.manager@imap.example.com:993/Junk Email"
|
||||
mailboxes "/home/hm-user/Mail/hm@example.com/Trash"
|
||||
folder-hook /home/hm-user/Mail/hm@example.com/ " \
|
||||
source /home/hm-user/.config/neomutt/hm@example.com "
|
||||
|
||||
|
||||
# Source primary account
|
||||
source /home/hm-user/.config/neomutt/hm@example.com
|
||||
|
||||
# Extra configuration
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
{
|
||||
imports = [ ../../accounts/email-test-accounts.nix ];
|
||||
|
||||
config = {
|
||||
accounts.email.accounts = {
|
||||
"hm@example.com" = {
|
||||
notmuch.enable = true;
|
||||
neomutt = {
|
||||
enable = true;
|
||||
extraConfig = ''
|
||||
color status cyan default
|
||||
'';
|
||||
mailboxName = "someCustomName";
|
||||
extraMailboxes = [
|
||||
"Sent"
|
||||
{
|
||||
mailbox = "Junk Email";
|
||||
name = "Spam";
|
||||
type = "imap";
|
||||
}
|
||||
{ mailbox = "Trash"; }
|
||||
];
|
||||
};
|
||||
imap.port = 993;
|
||||
};
|
||||
};
|
||||
|
||||
programs.neomutt = {
|
||||
enable = true;
|
||||
vimKeys = false;
|
||||
};
|
||||
|
||||
test.stubs.neomutt = { };
|
||||
|
||||
nmt.script = ''
|
||||
assertFileExists home-files/.config/neomutt/neomuttrc
|
||||
assertFileExists home-files/.config/neomutt/hm@example.com
|
||||
assertFileContent $(normalizeStorePaths home-files/.config/neomutt/neomuttrc) ${
|
||||
./neomutt-with-imap-type-mailboxes-expected.conf
|
||||
}
|
||||
assertFileContent home-files/.config/neomutt/hm@example.com ${
|
||||
./hm-example.com-expected
|
||||
}
|
||||
|
||||
confFile=$(grep -o \
|
||||
'/nix/store/.*-account-command.sh/bin/account-command.sh' \
|
||||
$TESTED/home-files/.config/neomutt/neomuttrc)
|
||||
assertFileContent "$(normalizeStorePaths "$confFile")" ${
|
||||
./account-command.sh-expected
|
||||
}
|
||||
'';
|
||||
};
|
||||
}
|
44
tests/modules/programs/neomutt/neomutt-with-imap.nix
Normal file
44
tests/modules/programs/neomutt/neomutt-with-imap.nix
Normal file
|
@ -0,0 +1,44 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
{
|
||||
imports = [ ../../accounts/email-test-accounts.nix ];
|
||||
|
||||
config = {
|
||||
accounts.email.accounts = {
|
||||
"hm@example.com" = {
|
||||
neomutt = {
|
||||
enable = true;
|
||||
mailboxType = "imap";
|
||||
extraConfig = ''
|
||||
color status cyan default
|
||||
'';
|
||||
};
|
||||
imap.port = 993;
|
||||
};
|
||||
};
|
||||
|
||||
programs.neomutt.enable = true;
|
||||
|
||||
test.stubs.neomutt = { };
|
||||
|
||||
nmt.script = ''
|
||||
assertFileExists home-files/.config/neomutt/neomuttrc
|
||||
assertFileExists home-files/.config/neomutt/hm@example.com
|
||||
assertFileContent $(normalizeStorePaths home-files/.config/neomutt/neomuttrc) ${
|
||||
./neomutt-with-imap-expected.conf
|
||||
}
|
||||
assertFileContent home-files/.config/neomutt/hm@example.com ${
|
||||
./hm-example.com-imap-expected.conf
|
||||
}
|
||||
|
||||
confFile=$(grep -o \
|
||||
'/nix/store/.*-account-command.sh/bin/account-command.sh' \
|
||||
$TESTED/home-files/.config/neomutt/neomuttrc)
|
||||
assertFileContent "$(normalizeStorePaths "$confFile")" ${
|
||||
./account-command.sh-expected
|
||||
}
|
||||
'';
|
||||
};
|
||||
}
|
Loading…
Reference in a new issue