home-manager/modules/programs/mbsync.nix
Robert Helgesson 4b32f16747
Use submodules for program email accounts
This reworks the way program specific email account options are
specified. In particular, we no longer use the deprecated `options`
field of `mkOption`. Instead submodules are used.
2018-08-16 21:37:42 +02:00

185 lines
4.7 KiB
Nix

{ config, lib, pkgs, ... }:
with lib;
let
dag = config.lib.dag;
cfg = config.programs.mbsync;
# Accounts for which mbsync is enabled.
mbsyncAccounts =
filter (a: a.mbsync.enable) (attrValues config.accounts.email.accounts);
genTlsConfig = tls: {
SSLType =
if !tls.enable then "None"
else if tls.useStartTls then "STARTTLS"
else "IMAPS";
}
//
optionalAttrs (tls.enable && tls.certificatesFile != null) {
CertificateFile = tls.certificatesFile;
};
masterSlaveMapping = {
none = "None";
imap = "Master";
maildir = "Slave";
both = "Both";
};
genSection = header: entries:
let
escapeValue = escape [ "\"" ];
genValue = v:
if isList v
then concatMapStringsSep " " genValue v
else "\"${escapeValue v}\"";
in
''
${header}
${concatStringsSep "\n"
(mapAttrsToList (n: v: "${n} ${genValue v}") entries)}
'';
genAccountConfig = account: with account;
if (imap == null || maildir == null)
then ""
else
genSection "IMAPAccount ${name}" (
{
Host = imap.host;
User = userName;
PassCmd = toString passwordCommand;
}
//
genTlsConfig imap.tls
//
optionalAttrs (imap.port != null) { Port = toString imap.port; }
)
+ "\n"
+ genSection "IMAPStore ${name}-remote" {
Account = name;
}
+ "\n"
+ genSection "MaildirStore ${name}-local" (
{
Path = "${maildir.absPath}/";
Inbox = "${maildir.absPath}/${folders.inbox}";
SubFolders = "Verbatim";
}
//
optionalAttrs (mbsync.flatten != null) { Flatten = mbsync.flatten; }
)
+ "\n"
+ genSection "Channel ${name}" {
Master = ":${name}-remote:";
Slave = ":${name}-local:";
Patterns = mbsync.patterns;
Create = masterSlaveMapping.${mbsync.create};
Remove = masterSlaveMapping.${mbsync.remove};
Expunge = masterSlaveMapping.${mbsync.expunge};
SyncState = "*";
}
+ "\n";
genGroupConfig = name: channels:
let
genGroupChannel = n: boxes: "Channel ${n}:${concatStringsSep "," boxes}";
in
concatStringsSep "\n" (
[ "Group ${name}" ] ++ mapAttrsToList genGroupChannel channels
);
in
{
options = {
programs.mbsync = {
enable = mkEnableOption "mbsync IMAP4 and Maildir mailbox synchronizer";
package = mkOption {
type = types.package;
default = pkgs.isync;
defaultText = "pkgs.isync";
example = literalExample "pkgs.isync";
description = "The package to use for the mbsync binary.";
};
groups = mkOption {
type = types.attrsOf (types.attrsOf (types.listOf types.str));
default = {};
example = literalExample ''
{
inboxes = {
account1 = [ "Inbox" ];
account2 = [ "Inbox" ];
};
}
'';
description = ''
Definition of groups.
'';
};
extraConfig = mkOption {
type = types.lines;
default = "";
description = ''
Extra configuration lines to add to the mbsync configuration.
'';
};
};
};
config = mkIf cfg.enable {
assertions = [
(
let
badAccounts = filter (a: a.maildir == null) mbsyncAccounts;
in
{
assertion = badAccounts == [];
message = "mbsync: Missing maildir configuration for accounts: "
+ concatMapStringsSep ", " (a: a.name) badAccounts;
}
)
(
let
badAccounts = filter (a: a.imap == null) mbsyncAccounts;
in
{
assertion = badAccounts == [];
message = "mbsync: Missing IMAP configuration for accounts: "
+ concatMapStringsSep ", " (a: a.name) badAccounts;
}
)
];
home.packages = [ cfg.package ];
programs.notmuch.new.ignore = [ ".uidvalidity" ".mbsyncstate" ];
home.file.".mbsyncrc".text =
let
accountsConfig = map genAccountConfig mbsyncAccounts;
groupsConfig = mapAttrsToList genGroupConfig cfg.groups;
in
concatStringsSep "\n" (
[ "# Generated by Home Manager.\n" ]
++ accountsConfig
++ groupsConfig
++ optional (cfg.extraConfig != "") cfg.extraConfig
);
home.activation.createMaildir =
dag.entryBetween [ "linkGeneration" ] [ "writeBoundary" ] ''
$DRY_RUN_CMD mkdir -m700 -p $VERBOSE_ARG ${
concatMapStringsSep " " (a: a.maildir.absPath) mbsyncAccounts
}
'';
};
}