thunderbird: map account auth methods

Closes #5137
This commit is contained in:
Austin Horstman
2026-04-28 09:54:55 -05:00
parent 8ec5a714db
commit ae6aeb9dbc
4 changed files with 241 additions and 9 deletions

View File

@@ -87,6 +87,49 @@ let
if (builtins.isString address) then address else (address.address + address.realName)
));
thunderbirdAuthMethods = {
anonymous = 1;
clear = 3;
cram_md5 = 4;
digest_md5 = 4;
gssapi = 5;
login = 3;
ntlm = 6;
plain = 3;
xoauth2 = 10;
};
toThunderbirdAuthMethod =
authentication: if authentication == null then 3 else thunderbirdAuthMethods.${authentication} or 3;
authMethodWarning =
name: authentication:
lib.optional (authentication != null && !builtins.hasAttr authentication thunderbirdAuthMethods) ''
${moduleName}: accounts.email.accounts.${name} uses authentication method
'${authentication}', which Thunderbird does not support directly. Falling back
to password-based authentication.
'';
unsupportedAuthMethodWarnings =
account:
let
aliasWarnings =
alias:
lib.optionals (builtins.isAttrs alias && alias.smtp != null && alias.smtp != account.smtp) (
authMethodWarning "${account.name}.aliases.${alias.address}.smtp" alias.smtp.authentication
);
in
lib.optionals (account.imap != null) (
authMethodWarning "${account.name}.imap" account.imap.authentication
)
++ lib.optionals (account.smtp != null) (
authMethodWarning "${account.name}.smtp" account.smtp.authentication
)
++ lib.optionals (account.ews != null) (
authMethodWarning "${account.name}.ews" account.ews.authentication
)
++ lib.concatMap aliasWarnings account.aliases;
toThunderbirdIdentity =
account: address:
# For backwards compatibility, the primary address reuses the account ID.
@@ -128,7 +171,7 @@ let
addressIsString = builtins.isString address;
in
optionalAttrs (!addressIsString && address.smtp != null) {
"mail.smtpserver.smtp_${id}.authMethod" = 3;
"mail.smtpserver.smtp_${id}.authMethod" = toThunderbirdAuthMethod address.smtp.authentication;
"mail.smtpserver.smtp_${id}.hostname" = address.smtp.host;
"mail.smtpserver.smtp_${id}.port" = if (address.smtp.port != null) then address.smtp.port else 587;
"mail.smtpserver.smtp_${id}.try_ssl" =
@@ -173,8 +216,11 @@ let
"mail.server.server_${id}.type" = "imap";
"mail.server.server_${id}.userName" = account.userName;
}
// optionalAttrs (account.imap != null && account.imap.authentication != null) {
"mail.server.server_${id}.authMethod" = toThunderbirdAuthMethod account.imap.authentication;
}
// optionalAttrs (account.smtp != null) {
"mail.smtpserver.smtp_${id}.authMethod" = 3;
"mail.smtpserver.smtp_${id}.authMethod" = toThunderbirdAuthMethod account.smtp.authentication;
"mail.smtpserver.smtp_${id}.hostname" = account.smtp.host;
"mail.smtpserver.smtp_${id}.port" = if (account.smtp.port != null) then account.smtp.port else 587;
"mail.smtpserver.smtp_${id}.try_ssl" =
@@ -188,7 +234,7 @@ let
}
// optionalAttrs (account.ews != null) {
"mail.smtpserver.ews_${id}.type" = "ews";
"mail.outgoingserver.ews_${id}.auth_method" = 3;
"mail.outgoingserver.ews_${id}.auth_method" = toThunderbirdAuthMethod account.ews.authentication;
"mail.outgoingserver.ews_${id}.ews_url" = account.ews.serviceDescriptionURL;
"mail.outgoingserver.ews_${id}.key" = "ews_${id}";
"mail.outgoingserver.ews_${id}.username" = account.userName;
@@ -210,6 +256,9 @@ let
"mail.server.server_${id}.type" = "ews";
"mail.server.server_${id}.userName" = account.userName;
}
// optionalAttrs (account.ews != null && account.ews.authentication != null) {
"mail.server.server_${id}.authMethod" = toThunderbirdAuthMethod account.ews.authentication;
}
// builtins.foldl' (a: b: a // b) { } (map (address: toThunderbirdSMTP account address) addresses)
// optionalAttrs (account.smtp != null && account.primary) {
"mail.smtp.defaultserver" = "smtp_${id}";
@@ -951,12 +1000,14 @@ in
)
];
warnings = lib.optionals (!cfg.darwinSetupWarning) [
''
Using programs.thunderbird.darwinSetupWarning is deprecated and will be
removed in the future. Thunderbird is now supported on Darwin.
''
];
warnings =
lib.optionals (!cfg.darwinSetupWarning) [
''
Using programs.thunderbird.darwinSetupWarning is deprecated and will be
removed in the future. Thunderbird is now supported on Darwin.
''
]
++ lib.flatten (map unsupportedAuthMethodWarnings enabledEmailAccounts);
home.packages = [
cfg.package

View File

@@ -1,5 +1,7 @@
{
thunderbird = ./thunderbird.nix;
thunderbird-auth-methods = ./thunderbird-auth-methods.nix;
thunderbird-auth-warning = ./thunderbird-auth-warning.nix;
thunderbird-with-firefox = ./thunderbird-with-firefox.nix;
thunderbird-native-messaging-host = ./thunderbird-native-messaging-host.nix;
}

View File

@@ -0,0 +1,94 @@
{
config,
pkgs,
...
}:
let
anonymousAccountId = builtins.hashString "sha256" "anonymous@example.com";
digestAccountId = builtins.hashString "sha256" "digest@example.com";
gssapiAccountId = builtins.hashString "sha256" "gssapi@example.com";
mixedAccountId = builtins.hashString "sha256" "mixed@example.com";
aliasSmtpId = builtins.hashString "sha256" "alias@example.comAlias";
inherit (pkgs.stdenv.hostPlatform) isDarwin;
profilesDir = if isDarwin then "Library/Thunderbird/Profiles" else ".thunderbird";
userJs = "home-files/${profilesDir}/default/user.js";
in
{
accounts.email.accounts = {
"anonymous@example.com" = {
address = "anonymous@example.com";
imap = {
host = "imap-anonymous.example.com";
authentication = "anonymous";
};
primary = true;
realName = "Anonymous";
thunderbird.enable = true;
};
"digest@example.com" = {
address = "digest@example.com";
imap = {
host = "imap-digest.example.com";
authentication = "digest_md5";
};
realName = "Digest";
thunderbird.enable = true;
};
"gssapi@example.com" = {
address = "gssapi@example.com";
ews = {
host = "ews-gssapi.example.com";
serviceDescriptionURL = "https://ews-gssapi.example.com/EWS/Exchange.asmx";
authentication = "gssapi";
};
realName = "GSSAPI";
thunderbird.enable = true;
};
"mixed@example.com" = {
address = "mixed@example.com";
aliases = [
{
address = "alias@example.com";
realName = "Alias";
smtp = {
host = "smtp-alias.example.com";
authentication = "xoauth2";
};
}
];
imap = {
host = "imap-mixed.example.com";
authentication = "ntlm";
};
realName = "Mixed";
smtp = {
host = "smtp-mixed.example.com";
authentication = "clear";
};
thunderbird.enable = true;
};
};
programs.thunderbird = {
enable = true;
package = config.lib.test.mkStubPackage {
name = "thunderbird";
};
profiles.default.isDefault = true;
};
nmt.script = ''
assertFileContains ${userJs} 'user_pref("mail.server.server_${anonymousAccountId}.authMethod", 1);'
assertFileContains ${userJs} 'user_pref("mail.server.server_${digestAccountId}.authMethod", 4);'
assertFileContains ${userJs} 'user_pref("mail.server.server_${gssapiAccountId}.authMethod", 5);'
assertFileContains ${userJs} 'user_pref("mail.outgoingserver.ews_${gssapiAccountId}.auth_method", 5);'
assertFileContains ${userJs} 'user_pref("mail.server.server_${mixedAccountId}.authMethod", 6);'
assertFileContains ${userJs} 'user_pref("mail.smtpserver.smtp_${mixedAccountId}.authMethod", 3);'
assertFileContains ${userJs} 'user_pref("mail.smtpserver.smtp_${aliasSmtpId}.authMethod", 10);'
'';
}

View File

@@ -0,0 +1,85 @@
{
config,
...
}:
{
accounts.email.accounts."hm@example.com" = {
address = "hm@example.com";
imap = {
host = "imap.example.com";
authentication = "oauthbearer";
};
primary = true;
realName = "Home Manager";
thunderbird.enable = true;
};
accounts.email.accounts."exchange@example.com" = {
address = "exchange@example.com";
ews = {
host = "ews.example.com";
serviceDescriptionURL = "https://ews.example.com/EWS/Exchange.asmx";
authentication = "oauthbearer";
};
realName = "Exchange Account";
thunderbird.enable = true;
};
accounts.email.accounts."smtp@example.com" = {
address = "smtp@example.com";
aliases = [
{
address = "inherited-alias@example.com";
realName = "Inherited Alias";
}
{
address = "overridden-alias@example.com";
realName = "Overridden Alias";
smtp = {
host = "smtp-alias.example.com";
authentication = "oauthbearer";
};
}
];
imap.host = "imap-smtp.example.com";
realName = "SMTP Account";
smtp = {
host = "smtp.example.com";
authentication = "oauthbearer";
};
thunderbird.enable = true;
};
programs.thunderbird = {
enable = true;
package = config.lib.test.mkStubPackage {
name = "thunderbird";
};
profiles.default.isDefault = true;
};
test.asserts.warnings.expected = [
''
programs.thunderbird: accounts.email.accounts.exchange@example.com.ews uses authentication method
'oauthbearer', which Thunderbird does not support directly. Falling back
to password-based authentication.
''
''
programs.thunderbird: accounts.email.accounts.hm@example.com.imap uses authentication method
'oauthbearer', which Thunderbird does not support directly. Falling back
to password-based authentication.
''
''
programs.thunderbird: accounts.email.accounts.smtp@example.com.smtp uses authentication method
'oauthbearer', which Thunderbird does not support directly. Falling back
to password-based authentication.
''
''
programs.thunderbird: accounts.email.accounts.smtp@example.com.aliases.overridden-alias@example.com.smtp uses authentication method
'oauthbearer', which Thunderbird does not support directly. Falling back
to password-based authentication.
''
];
test.asserts.warnings.enable = true;
}