add email

This commit is contained in:
Ray Andrew 2024-11-04 00:24:43 -06:00
parent 1a4f484b1d
commit 676d39d61f
13 changed files with 810 additions and 20 deletions

1
.envrc Normal file
View file

@ -0,0 +1 @@
use flake

1
.gitignore vendored
View file

@ -1,4 +1,5 @@
*.swp *.swp
.direnv
# Generated by nix-pre-commit-hooks # Generated by nix-pre-commit-hooks
/.pre-commit-config.yaml /.pre-commit-config.yaml

View file

@ -1,7 +1,7 @@
keys: keys:
- &rayandrew age10jr6vyrtppdtjzfudw36j22lf9pl2lu8rgekrr6t4egruz7dcsvqrhd4u3 - &rayandrew age10jr6vyrtppdtjzfudw36j22lf9pl2lu8rgekrr6t4egruz7dcsvqrhd4u3
creation_rules: creation_rules:
- path_regex: src/hosts/secrets.json$ - path_regex: src/home/email/secrets.yaml$
key_groups: key_groups:
- age: - age:
- *rayandrew - *rayandrew

View file

@ -8,6 +8,7 @@
{ {
imports = [ imports = [
./emacs.nix ./emacs.nix
./email
./impermanence.nix ./impermanence.nix
./gui ./gui
./shell ./shell

123
src/home/email/davmail.nix Normal file
View file

@ -0,0 +1,123 @@
{
config,
lib,
pkgs,
...
}:
let
home = config.home.homeDirectory;
cfg = config.services.davmail;
configType =
with lib.types;
oneOf [
(attrsOf configType)
str
int
bool
]
// {
description = "davmail config type (str, int, bool or attribute set thereof)";
};
toStr = val: if lib.isBool val then lib.boolToString val else toString val;
linesForAttrs =
attrs:
lib.concatMap (
name:
let
value = attrs.${name};
in
if lib.isAttrs value then
map (line: name + "." + line) (linesForAttrs value)
else
[ "${name}=${toStr value}" ]
) (lib.attrNames attrs);
configFile = pkgs.writeText "davmail.properties" (
lib.concatStringsSep "\n" (linesForAttrs cfg.config)
);
in
{
options.services.davmail = {
enable = lib.mkEnableOption "davmail, an MS Exchange gateway";
url = lib.mkOption {
type = lib.types.str;
description = "Outlook Web Access URL to access the exchange server, i.e. the base webmail URL.";
example = "https://outlook.office365.com/EWS/Exchange.asmx";
};
config = lib.mkOption {
type = configType;
default = { };
description = ''
Davmail configuration. Refer to
<http://davmail.sourceforge.net/serversetup.html>
and <http://davmail.sourceforge.net/advanced.html>
for details on supported values.
'';
example = lib.literalExpression ''
{
davmail.allowRemote = true;
davmail.imapPort = 55555;
davmail.bindAddress = "10.0.1.2";
davmail.smtpSaveInSent = true;
davmail.folderSizeLimit = 10;
davmail.caldavAutoSchedule = false;
log4j.logger.rootLogger = "DEBUG";
}
'';
};
};
config = lib.mkIf cfg.enable {
services.davmail.config = {
davmail = lib.mapAttrs (name: lib.mkDefault) {
server = true;
disableUpdateCheck = true;
logFilePath = "/tmp/davmail.log";
logFileSize = "1MB";
mode = "auto";
url = cfg.url;
caldavPort = 1080;
imapPort = 1143;
ldapPort = 1389;
popPort = 1110;
smtpPort = 1025;
oauth.tokenFilePath = "${home}/.config/davmail/token";
};
log4j = {
logger.davmail = lib.mkDefault "WARN";
logger.httpclient.wire = lib.mkDefault "WARN";
logger.org.apache.commons.httpclient = lib.mkDefault "WARN";
rootLogger = lib.mkDefault "WARN";
};
};
systemd.user.services.davmail = {
Unit = {
Description = "DavMail POP/IMAP/SMTP Exchange Gateway";
};
Install = {
WantedBy = [ "default.target" ];
};
Service = {
Type = "simple";
ExecStart = "${pkgs.davmail}/bin/davmail ${configFile}";
Restart = "on-failure";
};
};
home.packages = [ pkgs.davmail ];
custom.persist = {
home.directories = [
".config/davmail"
];
};
};
}

211
src/home/email/default.nix Normal file
View file

@ -0,0 +1,211 @@
{
pkgs,
lib,
config,
user,
...
}:
let
home = config.home.homeDirectory;
cat = lib.getExe' pkgs.coreutils "cat";
in
{
imports = [
./davmail.nix
./neomutt
];
options.custom = with lib; {
email = {
enable = mkEnableOption "Enable email";
exchange = mkEnableOption "Enable Microsoft Exchange";
};
};
config = lib.mkIf config.custom.email.enable {
services.davmail = {
enable = config.custom.email.exchange;
url = "https://outlook.office365.com/EWS/Exchange.asmx";
config = {
davmail.mode = "O365Manual";
davmail.keepDelay = 30;
# log4j.logger.davmail = "DEBUG";
};
};
programs = {
neomutt = {
enable = true;
macros = [
{
map = [
"index"
"pager"
];
key = "<f2>";
action = "<sync-mailbox><enter-command>source ~/.config/neomutt/uchicago<enter><change-folder>!<enter>";
}
{
map = [
"index"
"pager"
];
key = "<f3>";
action = "<sync-mailbox><enter-command>source ~/.config/neomutt/personal<enter><change-folder>!<enter>";
}
];
};
mbsync.enable = true;
msmtp = {
enable = true;
};
};
services = {
mbsync = {
enable = true;
frequency = "*:0/1";
};
};
accounts.email = rec {
maildirBasePath = "${config.home.homeDirectory}/mail";
accounts = lib.mkMerge ([
{
"personal" = {
userName = "raydreww@gmail.com";
address = "raydreww@gmail.com";
realName = "Ray Andrew";
primary = !config.custom.email.exchange;
signature = {
text = ''
-- Ray Andrew
'';
showSignature = "append";
};
passwordCommand = "${cat} ${config.sops.secrets."personal/password".path}";
smtp = {
host = "smtp.gmail.com";
};
imap = {
host = "imap.gmail.com";
};
mbsync = {
enable = true;
create = "both";
expunge = "both";
patterns = [
"*"
"!\"[Airmail]/Done\""
"!\"[Airmail]/Snooze\""
"!\"[Airmail]/To Do\""
"!\"[Airmail]/Send Later\""
"!\"[Gmail]/All Mail\""
"!\"[Gmail]/Important\""
"!\"[Gmail]/Starred\""
"!\"[Gmail]/Bin\""
];
};
msmtp = {
enable = true;
};
neomutt = rec {
enable = true;
mailboxName = "p";
extraConfig = ''
set use_from = yes
named-mailboxes "${mailboxName}/inbox" =Inbox
named-mailboxes "${mailboxName}/drafts" =Drafts
named-mailboxes "${mailboxName}/sent" =Sent
named-mailboxes "${mailboxName}/important" =Important
named-mailboxes "${mailboxName}/trash" =Trash
named-mailboxes "${mailboxName}/archive" =Archive
'';
};
};
}
(lib.mkIf config.custom.email.exchange {
"uchicago" = {
userName = "rayandrew@uchicago.edu";
address = "rayandrew@uchicago.edu";
realName = "Ray Andrew";
primary = true;
signature = {
text = ''
-- Ray Andrew
'';
showSignature = "append";
};
passwordCommand = "${cat} ${config.sops.secrets."uchicago/password".path}";
smtp = {
host = "127.0.0.1";
port = 1025;
tls = {
enable = false;
certificatesFile = null;
};
};
imap = {
host = "127.0.0.1";
port = 1143;
tls.enable = false;
};
mbsync = {
enable = true;
create = "both";
expunge = "both";
patterns = [
"*"
"!\"[Airmail]/Done\""
"!\"[Airmail]/Snooze\""
"!\"[Airmail]/To Do\""
"!\"[Airmail]/Send Later\""
];
extraConfig.account = {
TLSType = "None";
AuthMechs = "LOGIN";
Timeout = 0;
};
};
msmtp = {
enable = true;
extraConfig = {
auth = "plain";
};
};
neomutt = rec {
enable = true;
mailboxName = "u";
extraConfig = ''
set use_from = yes
named-mailboxes "${mailboxName}/inbox" =Inbox
named-mailboxes "${mailboxName}/drafts" =Drafts
named-mailboxes "${mailboxName}/sent" =Sent
named-mailboxes "${mailboxName}/important" =Important
named-mailboxes "${mailboxName}/trash" =Trash
named-mailboxes "${mailboxName}/archive" =Archive
named-mailboxes "${mailboxName}/teaching" =Teaching
'';
};
};
})
]);
};
custom.persist = {
home.directories = [
"mail"
];
};
sops = {
age.keyFile = "${home}/.config/sops/age/keys.txt";
age.generateKey = true;
defaultSopsFile = ./secrets.yaml;
secrets = {
"personal/password" = { };
"uchicago/password" = { };
};
};
};
}

View file

@ -0,0 +1,72 @@
{ pkgs, ... }:
''
# Header colors:
color header blue default ".*"
color header brightmagenta default "^(From)"
color header brightcyan default "^(Subject)"
color header brightwhite default "^(CC|BCC)"
mono bold bold
mono underline underline
mono indicator reverse
mono error bold
color normal default default
color indicator brightyellow default # currently selected message. default makes bar clear, disabled arrow to save space.
color sidebar_highlight red default
color sidebar_divider brightblack black
color sidebar_flagged red black
color sidebar_new green black
color normal brightyellow default
color error red default
color tilde black default
color message cyan default
color markers red white
color attachment white default
color search brightmagenta default
color status brightyellow black
color hdrdefault brightgreen default
color quoted green default
color quoted1 blue default
color quoted2 cyan default
color quoted3 yellow default
color quoted4 red default
color quoted5 brightred default
color signature brightgreen default
color bold black default
color underline black default
color normal default default
color body brightred default "[\-\.+_a-zA-Z0-9]+@[\-\.a-zA-Z0-9]+" # Email addresses
color body brightblue default "(https?|ftp)://[\-\.,/%~_:?&=\#a-zA-Z0-9]+" # URL
color body green default "\`[^\`]*\`" # Green text between ` and `
color body brightblue default "^# \.*" # Headings as bold blue
color body brightcyan default "^## \.*" # Subheadings as bold cyan
color body brightgreen default "^### \.*" # Subsubheadings as bold green
color body yellow default "^(\t| )*(-|\\*) \.*" # List items as yellow
color body brightcyan default "[;:][-o][)/(|]" # emoticons
color body brightcyan default "[;:][)(|]" # emoticons
color body brightcyan default "[ ][*][^*]*[*][ ]?" # more emoticon?
color body brightcyan default "[ ]?[*][^*]*[*][ ]" # more emoticon?
color body red default "(BAD signature)"
color body cyan default "(Good signature)"
color body brightblack default "^gpg: Good signature .*"
color body brightyellow default "^gpg: "
color body brightyellow red "^gpg: BAD signature from.*"
mono body bold "^gpg: Good signature"
# mohttps://neomutt.org/code/config_vars.htmlno body bold "^gpg: BAD signature from.*"
color body red default "([a-z][a-z0-9+-]*://(((([a-z0-9_.!~*'();:&=+$,-]|%[0-9a-f][0-9a-f])*@)?((([a-z0-9]([a-z0-9-]*[a-z0-9])?)\\.)*([a-z]([a-z0-9-]*[a-z0-9])?)\\.?|[0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+)(:[0-9]+)?)|([a-z0-9_.!~*'()$,;:@&=+-]|%[0-9a-f][0-9a-f])+)(/([a-z0-9_.!~*'():@&=+$,-]|%[0-9a-f][0-9a-f])*(;([a-z0-9_.!~*'():@&=+$,-]|%[0-9a-f][0-9a-f])*)*(/([a-z0-9_.!~*'():@&=+$,-]|%[0-9a-f][0-9a-f])*(;([a-z0-9_.!~*'():@&=+$,-]|%[0-9a-f][0-9a-f])*)*)*)?(\\?([a-z0-9_.!~*'();/?:@&=+$,-]|%[0-9a-f][0-9a-f])*)?(#([a-z0-9_.!~*'();/?:@&=+$,-]|%[0-9a-f][0-9a-f])*)?|(www|ftp)\\.(([a-z0-9]([a-z0-9-]*[a-z0-9])?)\\.)*([a-z]([a-z0-9-]*[a-z0-9])?)\\.?(:[0-9]+)?(/([-a-z0-9_.!~*'():@&=+$,]|%[0-9a-f][0-9a-f])*(;([-a-z0-9_.!~*'():@&=+$,]|%[0-9a-f][0-9a-f])*)*(/([-a-z0-9_.!~*'():@&=+$,]|%[0-9a-f][0-9a-f])*(;([-a-z0-9_.!~*'():@&=+$,]|%[0-9a-f][0-9a-f])*)*)*)?(\\?([-a-z0-9_.!~*'();/?:@&=+$,]|%[0-9a-f][0-9a-f])*)?(#([-a-z0-9_.!~*'();/?:@&=+$,]|%[0-9a-f][0-9a-f])*)?)[^].,:;!)? \t\r\n<>\"]"
# Default index colors:
color index yellow default '.*'
color index_author red default '.*'
color index_number blue default
color index_subject cyan default '.*'
# For new mail:
color index brightyellow black "~N"
color index_author brightred black "~N"
color index_subject brightcyan black "~N"
color progress black cyan
''

View file

@ -0,0 +1,62 @@
{
pkgs,
config,
lib,
...
}:
let
keybinds = import ./keybind.nix rec {
inherit config lib pkgs;
};
colors = import ./colors.nix rec {
inherit config lib pkgs;
};
in
{
programs.neomutt = {
vimKeys = false;
sort = "threads";
unmailboxes = true;
binds = keybinds.binds ++ [ ];
macros = keybinds.macros ++ [ ];
extraConfig = ''
set abort_key = "<Esc>"
set edit_headers = yes
set sidebar_visible
set sidebar_format = "%D%?F? [%F]?%* %?N?%N/?%S"
set mail_check_stats
# set new_mail_command="notify-send 'New Email' '%n new messages, %u unread.' &"
# status bar, date format, finding stuff etc.
set status_chars = " *%A"
# set status_format = "[ Folder: %f ] [%r%m messages%?n? (%n new)?%?d? (%d to delete)?%?t? (%t tagged)? ]%>─%?p?( %p postponed )?"
set status_format = "[ Folder: %D ] [%r%m messages%?n? (%n new)?%?d? (%d to delete)?%?t? (%t tagged)? ]%>%?p?( %p postponed )?"
set date_format = "%d.%m.%Y %H:%M"
set uncollapse_jump
set sort_re
set reply_regexp = "^(([Rr][Ee]?(\[[0-9]+\])?: *)?(\[[^]]+\] *)?)*"
set quote_regexp = "^( {0,4}[>|:#%]| {0,4}[a-z0-9]+[>|]+)+"
set send_charset = "utf-8:iso-8859-1:us-ascii"
set charset = "utf-8"
set arrow_cursor = "no" # Change `color indicator` depending
# Pager View Options
set pager_index_lines = 10 # Shows 10 lines of index when pager is active
set pager_context = 3
set pager_stop
set menu_scroll
set tilde
unset markers
${colors}
'';
};
custom.persist = {
home.cache.directories = [
".cache/neomutt"
];
};
}

View file

@ -0,0 +1,309 @@
{ pkgs, ... }:
{
binds = [
{
map = [ "attach" ];
key = "<return>";
action = "view-mailcap";
}
{
map = [ "attach" ];
key = "l";
action = "view-mailcap";
}
# {
# map = [ "attach" ];
# key = "O";
# action = "<enter-command>unset wait_key<enter><shell-escape>rm -f /tmp/mutt-attach<enter><save-entry><kill-line>/tmp/mutt-attach<enter>^A";
# }
{
map = [ "editor" ];
key = "<space>";
action = "noop";
}
{
map = [ "pager" ];
key = "c";
action = "imap-fetch-mail";
}
{
map = [ "index" ];
key = "G";
action = "last-entry";
}
{
map = [ "index" ];
key = "g";
action = "noop";
}
{
map = [ "index" ];
key = "gg";
action = "first-entry";
}
{
map = [
"pager"
"attach"
];
key = "h";
action = "exit";
}
{
map = [ "pager" ];
key = "j";
action = "next-line";
}
{
map = [ "pager" ];
key = "k";
action = "previous-line";
}
{
map = [ "pager" ];
key = "l";
action = "view-attachments";
}
{
map = [ "index" ];
key = "D";
action = "delete-message";
}
{
map = [ "index" ];
key = "U";
action = "undelete-message";
}
{
map = [ "index" ];
key = "L";
action = "limit";
}
{
map = [ "index" ];
key = "h";
action = "noop";
}
{
map = [
"browser"
"pager"
"index"
];
key = "n";
action = "search-next";
}
{
map = [
"browser"
"pager"
"index"
];
key = "N";
action = "search-opposite";
}
{
map = [ "index" ];
key = "l";
action = "display-message";
}
{
map = [ "browser" ];
key = "h";
action = "goto-parent";
}
{
map = [ "browser" ];
key = "l";
action = "select-entry";
}
{
map = [
"pager"
"browser"
];
key = "gg";
action = "top-page";
}
{
map = [
"pager"
"browser"
];
key = "G";
action = "bottom-page";
}
{
map = [
"index"
"pager"
"browser"
];
key = "d";
action = "half-down";
}
{
map = [
"index"
"pager"
"browser"
];
key = "u";
action = "half-up";
}
{
map = [ "index" ];
key = "R";
action = "group-reply";
}
{
map = [ "index" ];
key = "\\031";
action = "previous-undeleted";
}
{
map = [ "index" ];
key = "\\005";
action = "next-undeleted";
}
{
map = [ "pager" ];
key = "\\031";
action = "previous-line";
}
{
map = [ "pager" ];
key = "\\005";
action = "next-line";
}
{
map = [ "editor" ];
key = "<Tab>";
action = "complete-query";
}
{
map = [
"index"
"pager"
];
key = "\\Ck";
action = "sidebar-prev";
}
{
map = [
"index"
"pager"
];
key = "\\Cj";
action = "sidebar-next";
}
{
map = [
"index"
"pager"
];
key = "\\Co";
action = "sidebar-open";
}
{
map = [
"index"
"pager"
];
key = "\\Cp";
action = "sidebar-prev-new";
}
{
map = [
"index"
"pager"
];
key = "\\Cn";
action = "sidebar-next-new";
}
{
map = [
"index"
"pager"
];
key = "B";
action = "sidebar-toggle-visible";
}
{
map = [
"index"
"pager"
];
key = "@";
action = "compose-to-sender";
}
{
map = [
"index"
"pager"
];
key = "D";
action = "purge-message";
}
{
map = [ "index" ];
key = "<tab>";
action = "sync-mailbox";
}
{
map = [ "index" ];
key = "<space>";
action = "collapse-thread";
}
{
map = [ "editor" ];
key = "<Tab>";
action = "complete-query";
}
{
map = [ "editor" ];
key = "^T";
action = "complete";
}
# {
# map = [
# "index"
# "pager"
# ];
# key = "<f2>";
# action = "<sync-mailbox><enter-command>source ~/.config/neomutt/accounts/uchicago<enter><change-folder>!<enter>";
# }
# {
# map = [
# "index"
# "pager"
# ];
# key = "<f3>";
# action = "<sync-mailbox><enter-command>source ~/.config/neomutt/accounts/personal<enter><change-folder>!<enter>";
# }
# {
# map = [ "attach" ];
# key = "V";
# action = "<pipe-entry>iconv -c --to-code=UTF8 > ~/.cache/mutt-mail.html<enter><shell-escape>xdg-open ~/.cache/mutt-mail.html<enter>";
# }
];
macros = [
{
map = [
"index"
"pager"
];
key = "a";
action = ":set confirmappend=no delete=yes\\n<tag-prefix><save-message>=Archive\\n<sync-mailbox>:set confirmappend=yes delete=ask-yes\\n";
}
{
map = [
"index"
"pager"
];
key = "n";
action = "<tag-prefix><clear-flag>N<untag-pattern>.<enter>\\n";
}
];
}

View file

@ -0,0 +1,24 @@
personal:
password: ENC[AES256_GCM,data:2iqTneVxVY1mQzC6Pm6SSQ==,iv:vF5j/uEIsO9O0XEc9b66FudMm+BJEVreyhJFe4IsnY8=,tag:WYXxuaLvmlImy18XkMXwmQ==,type:str]
uchicago:
password: ENC[AES256_GCM,data:IV6XQvzwfNwJvY27Flo=,iv:fQhh8Sg1gb0NfxLmIQS0SrxGYvxhgw2Pz9vvmq69IFA=,tag:8nVH93QOS3mSgewmD2chCw==,type:str]
sops:
kms: []
gcp_kms: []
azure_kv: []
hc_vault: []
age:
- recipient: age10jr6vyrtppdtjzfudw36j22lf9pl2lu8rgekrr6t4egruz7dcsvqrhd4u3
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBQSTVsbVJGaW14ZGxiSXFG
SmJYTzN0ajZtQW9MZDFKUDZNekVwd1hST1hnCjRJN3dvOTVUWkdHZUNnNHZ5Nk1P
ZjNzQUtDejhTRStYTm5WeDBWaEc1cjQKLS0tIGM2aDg1WGx4NGJRU3p6Y2pWSTV4
Zy9rVi9zS3drVUVMNUxFWXN3YlBBRU0KGVk8WEJiAuSeWmkgsT/zvins13t9fC8e
G3be1Fc/NRW0st1hlGgrNzveu79LAikaprXPJXOpcfarXCAFUgU2mQ==
-----END AGE ENCRYPTED FILE-----
lastmodified: "2024-11-04T02:32:31Z"
mac: ENC[AES256_GCM,data:ZU6qsOgDSSX5lwb1aAv9SA+rPe6Jnzg7SjuOKLxNWnoDHP4okOtAHVYJKTglnSS46ng4Sy7gPQhvjhSs5Jt2Yk/Uexu9QdsfrPmSxKPvoFyd82jKKQAY39b0LRPevqlhMJ+8vzu6Fndd0BrrQ7lJ7do8cj3Ixmoq9qI/DpMfD7o=,iv:QvxZaXO8DsKEIkhYY5XtG0XoQjTZOMgb7Y3uhw7W3Us=,tag:CZqSIrlc9ILl/gamph2O/w==,type:str]
pgp: []
unencrypted_suffix: _unencrypted
version: 3.9.1

View file

@ -44,6 +44,7 @@ let
inputs.nix-index-database.hmModules.nix-index inputs.nix-index-database.hmModules.nix-index
inputs.impermanence.nixosModules.home-manager.impermanence inputs.impermanence.nixosModules.home-manager.impermanence
inputs.plasma-manager.homeManagerModules.plasma-manager inputs.plasma-manager.homeManagerModules.plasma-manager
inputs.sops-nix.homeManagerModules.sops
./${host}/home.nix ./${host}/home.nix
../home ../home
]; ];

View file

@ -9,4 +9,8 @@
home.packages = with pkgs; [ home.packages = with pkgs; [
fw-ectool fw-ectool
]; ];
custom.email = {
enable = true;
exchange = true;
};
} }

View file

@ -1,19 +0,0 @@
{
"sops": {
"kms": null,
"gcp_kms": null,
"azure_kv": null,
"hc_vault": null,
"age": [
{
"recipient": "age10jr6vyrtppdtjzfudw36j22lf9pl2lu8rgekrr6t4egruz7dcsvqrhd4u3",
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBMZkczUjQ3b2NEV29WRTNZ\nSnlLdUlsUFdsWmZmU2gxVEgzWFlqNzlBNDE4CnlWazBQSFRReHZWT1lDYm0yWng2\nUEtjcDlvcS9QWEFDYU4yWkxOTmttMmsKLS0tIDVmcUV3ejg2MktWMFNBR25EdHVU\ndXdNMHBEYURNbFBHeDhVY2h2MnVTVk0KEg0MtRZR2dyb/4yuOC09DwxuVu1nca9H\naO8ZILRosqAkWL6qyuxnvlZHFOmLVibwMUnpAtesBHMXhxBiFyslMw==\n-----END AGE ENCRYPTED FILE-----\n"
}
],
"lastmodified": "2024-11-04T00:18:04Z",
"mac": "ENC[AES256_GCM,data:f6JwS7xYvqLMHd+mjuYpK2k+WMtXXK5ePuKrsjsMtjLpHR4YnQm4tFmhlvGtVHXkgn9WT7+qq8HUfMaDKvU3AZ9fkio3DCAPQFQZpIUHApvTTb8MgS4XBl2ST1/HPBnGS40IRL3Nx0NvUtxCUadv1+sE+9fz0repcQ4OkGpcvno=,iv:bfFCUlkY9oOaIueZLA8llmp6U3NUdRGsVqwNSmjM36g=,tag:ShzJ79NtDo14dh5TygYQsw==,type:str]",
"pgp": null,
"unencrypted_suffix": "_unencrypted",
"version": "3.9.1"
}
}