dotfiles/config/scripts/melConf

345 lines
8.3 KiB
Plaintext
Raw Normal View History

2018-08-13 10:20:09 +00:00
#!/usr/bin/env python3
"""
Meh mail client conf generator for other things
"""
import configparser
import os
import sys
# TODO Find config file from XDG
# TODO Signature file
# TODO Write ~/.mail/[mailbox]/color file if required by sth?
2018-10-14 14:59:49 +00:00
# TODO Write in .config or .cache /mel
2018-08-13 15:59:40 +00:00
# TODO Fix IMAPS with mbsync
2018-08-13 10:20:09 +00:00
2021-06-13 09:49:21 +00:00
configPath = os.path.join(os.path.expanduser("~"), ".config", "mel", "accounts.conf")
2018-08-13 10:20:09 +00:00
config = configparser.ConfigParser()
config.read(configPath)
2018-08-13 15:59:40 +00:00
storageFull = os.path.realpath(os.path.expanduser(config["GENERAL"]["storage"]))
config["GENERAL"]["storage"] = storageFull
2018-08-13 10:20:09 +00:00
SERVER_DEFAULTS = {
2021-06-13 09:49:21 +00:00
"imap": {"port": 143, "starttls": True},
"smtp": {"port": 587, "starttls": True},
}
2018-08-13 10:20:09 +00:00
SERVER_ITEMS = {"host", "port", "user", "pass", "starttls"}
2018-10-14 14:59:49 +00:00
ACCOUNT_DEFAULTS = {
"color": "#FFFFFF",
"color16": "0",
# "colormutt": "white",
"inboxfolder": "INBOX",
"archivefolder": "Archive",
"draftsfolder": "Drafts",
"sentfolder": "Sent",
"spamfolder": "Spam",
"trashfolder": "Trash",
}
2018-08-13 10:20:09 +00:00
# Reading sections
accounts = dict()
2018-08-13 15:59:40 +00:00
mails = set()
2018-08-13 10:20:09 +00:00
for name in config.sections():
if not name.islower():
continue
section = config[name]
data = dict()
for server in SERVER_DEFAULTS.keys():
for item in SERVER_ITEMS:
key = server + item
try:
2021-06-13 09:49:21 +00:00
val = (
section.get(key)
or section.get(item)
or SERVER_DEFAULTS[server][item]
)
2018-08-13 10:20:09 +00:00
except KeyError:
raise KeyError("{}.{}".format(name, key))
if isinstance(val, str):
if val == "True":
val = True
elif val == "False":
val = False
elif val.isnumeric():
val = int(val)
data[key] = val
for key in section.keys():
if key in SERVER_ITEMS:
continue
data[key] = section[key]
2021-06-13 09:49:21 +00:00
for k, v in config["DEFAULT"].items():
2018-10-14 14:59:49 +00:00
if k not in data:
data[k] = v
for k, v in ACCOUNT_DEFAULTS.items():
if k not in data:
data[k] = v
2018-08-13 15:59:40 +00:00
mails.add(section["from"])
if "alternatives" in section:
for alt in section["alternatives"].split(";"):
mails.add(alt)
data["account"] = name
2021-06-13 09:49:21 +00:00
data["storage"] = os.path.join(config["GENERAL"]["storage"], name)
2018-08-13 10:20:09 +00:00
data["storageInbox"] = os.path.join(data["storage"], "INBOX")
accounts[name] = data
2018-08-13 15:59:40 +00:00
general = dict()
section = config["GENERAL"]
for key in section.keys():
general[key] = section[key]
general["main"] = accounts[general["main"]]
2018-08-13 10:20:09 +00:00
# OfflineIMAP
OFFLINEIMAP_BEGIN = """[general]
# List of accounts to be synced, separated by a comma.
accounts = {}
maxsyncaccounts = {}
stocktimeout = 60
pythonfile = ~/.config/offlineimap.py
[mbnames]
enabled = yes
filename = ~/.mutt/mailboxes
header = "mailboxes "
peritem = "+%(accountname)s/%(foldername)s"
sep = " "
footer = "\\n"
"""
2018-08-13 15:59:40 +00:00
OFFLINEIMAP_ACCOUNT = """[Account {account}]
localrepository = {account}-local
remoterepository = {account}-remote
2018-08-13 10:20:09 +00:00
autorefresh = 0.5
quick = 10
utf8foldernames = yes
postsynchook = ~/.mutt/postsync
2018-08-13 15:59:40 +00:00
[Repository {account}-local]
2018-08-13 10:20:09 +00:00
type = Maildir
localfolders = {storage}
2018-08-13 15:59:40 +00:00
[Repository {account}-remote]
2018-08-13 10:20:09 +00:00
type = IMAP
{secconf}
keepalive = 60
holdconnectionopen = yes
remotehost = {imaphost}
remoteport = {imapport}
remoteuser = {imapuser}
remotepass = {imappass}
"""
2021-06-13 09:49:21 +00:00
offlineIMAPstr = OFFLINEIMAP_BEGIN.format(",".join(accounts), len(accounts))
2018-08-13 10:20:09 +00:00
for name, account in accounts.items():
if account["imapstarttls"]:
secconf = "ssl = no"
else:
secconf = "sslcacertfile = /etc/ssl/certs/ca-certificates.crt"
offlineIMAPstr += OFFLINEIMAP_ACCOUNT.format(**account, secconf=secconf)
# TODO Write
# mbsync
2018-08-13 15:59:40 +00:00
MBSYNC_ACCOUNT = """IMAPAccount {account}
2018-08-13 10:20:09 +00:00
Host {imaphost}
2018-08-13 15:59:40 +00:00
Port {imapport}
2018-08-13 10:20:09 +00:00
User {imapuser}
2018-08-13 15:59:40 +00:00
Pass "{imappassEscaped}"
2018-08-13 10:20:09 +00:00
{secconf}
2018-08-13 15:59:40 +00:00
IMAPStore {account}-remote
Account {account}
2018-08-13 10:20:09 +00:00
2018-08-13 15:59:40 +00:00
MaildirStore {account}-local
2018-08-13 10:20:09 +00:00
Subfolders Verbatim
Path {storage}/
Inbox {storageInbox}/
2018-08-13 15:59:40 +00:00
Channel {account}
Master :{account}-remote:
Slave :{account}-local:
2018-08-13 10:20:09 +00:00
Patterns *
Create Both
SyncState *
"""
mbsyncStr = ""
for name, account in accounts.items():
if account["imapstarttls"]:
secconf = "SSLType STARTTLS"
else:
secconf = "SSLType IMAPS"
2018-08-13 15:59:40 +00:00
if "certificate" in account:
secconf += "\nCertificateFile {certificate}".format(**account)
imappassEscaped = account["imappass"].replace("\\", "\\\\")
2021-06-13 09:49:21 +00:00
mbsyncStr += MBSYNC_ACCOUNT.format(
**account, secconf=secconf, imappassEscaped=imappassEscaped
)
mbsyncFilepath = os.path.join(os.path.expanduser("~"), ".config/mel/mbsyncrc")
with open(mbsyncFilepath, "w") as f:
2018-08-13 10:20:09 +00:00
f.write(mbsyncStr)
# msmtp
MSMTP_BEGIN = """defaults
protocol smtp
auth on
tls_trust_file /etc/ssl/certs/ca-certificates.crt
"""
2018-08-13 15:59:40 +00:00
MSMTP_ACCOUNT = """account {account}
2018-08-13 10:20:09 +00:00
from {from}
user {smtpuser}
password {smtppass}
host {smtphost}
port {smtpport}
tls on
"""
msmtpStr = MSMTP_BEGIN
for name, account in accounts.items():
msmtpStr += MSMTP_ACCOUNT.format(**account)
2021-06-13 09:49:21 +00:00
mbsyncFilepath = os.path.join(os.path.expanduser("~"), ".config/msmtp/config")
with open(mbsyncFilepath, "w") as f:
2018-08-13 10:20:09 +00:00
f.write(msmtpStr)
2018-08-13 15:59:40 +00:00
# notmuch
NOTMUCH_BEGIN = """[database]
path={storage}
[user]
name={main[name]}
primary_email={main[from]}
other_email={other_email}
[new]
2018-08-14 15:23:57 +00:00
tags=unprocessed;unread;
2018-08-13 15:59:40 +00:00
ignore=
[search]
exclude_tags=deleted;spam;
[maildir]
synchronize_flags=true
[crypto]
gpg_path=gpg
"""
other_email = mails.copy()
other_email.remove(general["main"]["from"])
other_email = ";".join(other_email)
notmuchStr = NOTMUCH_BEGIN.format(**general, other_email=other_email)
2021-06-13 09:49:21 +00:00
mbsyncFilepath = os.path.join(os.path.expanduser("~"), ".config/notmuch-config")
with open(mbsyncFilepath, "w") as f:
2018-08-13 15:59:40 +00:00
f.write(notmuchStr)
2018-10-14 14:59:49 +00:00
# mutt (temp)
## mailboxes
MAILBOXES_BEGIN = "mailboxes"
mailboxesStr = MAILBOXES_BEGIN
for name, account in accounts.items():
lines = "-" * (20 - len(name))
mailboxesStr += f' "+{name}{lines}"'
2021-06-13 09:49:21 +00:00
for root, dirs, files in os.walk(account["storage"]):
2018-10-14 14:59:49 +00:00
if "cur" not in dirs or "new" not in dirs or "tmp" not in dirs:
continue
assert root.startswith(storageFull)
2021-06-13 09:49:21 +00:00
path = root[len(storageFull) + 1 :]
2018-10-14 14:59:49 +00:00
mailboxesStr += f' "+{path}"'
mailboxesStr += "\n"
2021-06-13 09:49:21 +00:00
mailboxesFilepath = os.path.join(os.path.expanduser("~"), ".mutt/mailboxes")
with open(mailboxesFilepath, "w") as f:
2018-10-14 14:59:49 +00:00
f.write(mailboxesStr)
## accounts
# TODO html mails
MUTT_ACCOUNT = """set from = "{from}"
set sendmail = "/usr/bin/msmtp -a {account}"
set realname = "{name}"
set spoolfile = "+{account}/{inboxfolder}"
set mbox = "+{account}/{archivefolder}"
set postponed = "+{account}/{draftsfolder}"
set record = "+{account}/{sentfolder}"
set trash = "+{account}/{trashfolder}"
set signature = "~/.mutt/accounts/{account}.sig"
set content_type = "text/plain"
set sig_dashes = yes
color status {colormutt} default
macro index D \\
"<clear-flag>N<save-message>+{account}/{trashfolder}<enter>" \\
"move message to the trash"
macro index S \\
"<clear-flag>N<save-message>+{account}/{spamfolder}<enter>" \\
"mark message as spam"
# vim: syntax=muttrc
"""
for name, account in accounts.items():
muttStr = MUTT_ACCOUNT.format(**account)
# Config
2021-06-13 09:49:21 +00:00
muttFilepath = os.path.join(os.path.expanduser("~"), f".mutt/accounts/{name}")
with open(muttFilepath, "w") as f:
2018-10-14 14:59:49 +00:00
f.write(muttStr)
# Signature
sigStr = account.get("sig", account.get("name", ""))
2021-06-13 09:49:21 +00:00
sigFilepath = os.path.join(os.path.expanduser("~"), f".mutt/accounts/{name}.sig")
with open(sigFilepath, "w") as f:
2018-10-14 14:59:49 +00:00
f.write(sigStr)
MUTT_SELECTOR = """
set folder = "{storage}"
source ~/.mutt/mailboxes
source ~/.mutt/accounts/{main[account]}
{hooks}
source ~/.mutt/custom
# vim: syntax=muttrc
"""
selectStr = ""
hooks = ""
for name, account in accounts.items():
hooks += f"folder-hook {name}/* source ~/.mutt/accounts/{name}\n"
selectStr += MUTT_SELECTOR.format(**general, hooks=hooks)
2021-06-13 09:49:21 +00:00
selectFilepath = os.path.join(os.path.expanduser("~"), ".mutt/muttrc")
with open(selectFilepath, "w") as f:
2018-10-14 14:59:49 +00:00
f.write(selectStr)
2018-10-18 19:14:11 +00:00
## Color
for name, account in accounts.items():
# Config
2021-06-13 09:49:21 +00:00
colorFilepath = os.path.join(
os.path.expanduser("~"), f'{general["storage"]}/{name}/color'
)
with open(colorFilepath, "w") as f:
f.write(account["color"])