Let my HOME alone 1/2
This commit is contained in:
parent
2ae37e902e
commit
a83e45df5e
94 changed files with 328 additions and 58 deletions
336
config/scripts/melConf
Executable file
336
config/scripts/melConf
Executable file
|
@ -0,0 +1,336 @@
|
|||
#!/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?
|
||||
# TODO Write in .config or .cache /mel
|
||||
# TODO Fix IMAPS with mbsync
|
||||
|
||||
configPath = os.path.join(os.path.expanduser('~'), '.config', 'mel', 'accounts.conf')
|
||||
|
||||
config = configparser.ConfigParser()
|
||||
config.read(configPath)
|
||||
|
||||
storageFull = os.path.realpath(os.path.expanduser(config["GENERAL"]["storage"]))
|
||||
config["GENERAL"]["storage"] = storageFull
|
||||
|
||||
SERVER_DEFAULTS = {
|
||||
"imap": {"port": 143, "starttls": True},
|
||||
"smtp": {"port": 587, "starttls": True},
|
||||
}
|
||||
SERVER_ITEMS = {"host", "port", "user", "pass", "starttls"}
|
||||
ACCOUNT_DEFAULTS = {
|
||||
"color": "#FFFFFF",
|
||||
"color16": "0",
|
||||
# "colormutt": "white",
|
||||
"inboxfolder": "INBOX",
|
||||
"archivefolder": "Archive",
|
||||
"draftsfolder": "Drafts",
|
||||
"sentfolder": "Sent",
|
||||
"spamfolder": "Spam",
|
||||
"trashfolder": "Trash",
|
||||
}
|
||||
|
||||
# Reading sections
|
||||
accounts = dict()
|
||||
mails = set()
|
||||
|
||||
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:
|
||||
val = section.get(key) or section.get(item) or SERVER_DEFAULTS[server][item]
|
||||
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]
|
||||
|
||||
for k, v in config['DEFAULT'].items():
|
||||
if k not in data:
|
||||
data[k] = v
|
||||
|
||||
for k, v in ACCOUNT_DEFAULTS.items():
|
||||
if k not in data:
|
||||
data[k] = v
|
||||
|
||||
mails.add(section["from"])
|
||||
if "alternatives" in section:
|
||||
for alt in section["alternatives"].split(";"):
|
||||
mails.add(alt)
|
||||
|
||||
data["account"] = name
|
||||
data["storage"] = os.path.join(config['GENERAL']['storage'], name)
|
||||
data["storageInbox"] = os.path.join(data["storage"], "INBOX")
|
||||
accounts[name] = data
|
||||
|
||||
general = dict()
|
||||
section = config["GENERAL"]
|
||||
for key in section.keys():
|
||||
general[key] = section[key]
|
||||
general["main"] = accounts[general["main"]]
|
||||
|
||||
|
||||
# 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"
|
||||
|
||||
"""
|
||||
|
||||
OFFLINEIMAP_ACCOUNT = """[Account {account}]
|
||||
localrepository = {account}-local
|
||||
remoterepository = {account}-remote
|
||||
autorefresh = 0.5
|
||||
quick = 10
|
||||
utf8foldernames = yes
|
||||
postsynchook = ~/.mutt/postsync
|
||||
|
||||
[Repository {account}-local]
|
||||
type = Maildir
|
||||
localfolders = {storage}
|
||||
|
||||
[Repository {account}-remote]
|
||||
type = IMAP
|
||||
{secconf}
|
||||
keepalive = 60
|
||||
holdconnectionopen = yes
|
||||
remotehost = {imaphost}
|
||||
remoteport = {imapport}
|
||||
remoteuser = {imapuser}
|
||||
remotepass = {imappass}
|
||||
|
||||
"""
|
||||
|
||||
offlineIMAPstr = OFFLINEIMAP_BEGIN.format(','.join(accounts), len(accounts))
|
||||
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
|
||||
MBSYNC_ACCOUNT = """IMAPAccount {account}
|
||||
Host {imaphost}
|
||||
Port {imapport}
|
||||
User {imapuser}
|
||||
Pass "{imappassEscaped}"
|
||||
{secconf}
|
||||
|
||||
IMAPStore {account}-remote
|
||||
Account {account}
|
||||
|
||||
MaildirStore {account}-local
|
||||
Subfolders Verbatim
|
||||
Path {storage}/
|
||||
Inbox {storageInbox}/
|
||||
|
||||
Channel {account}
|
||||
Master :{account}-remote:
|
||||
Slave :{account}-local:
|
||||
Patterns *
|
||||
Create Both
|
||||
SyncState *
|
||||
|
||||
"""
|
||||
|
||||
mbsyncStr = ""
|
||||
for name, account in accounts.items():
|
||||
if account["imapstarttls"]:
|
||||
secconf = "SSLType STARTTLS"
|
||||
else:
|
||||
secconf = "SSLType IMAPS"
|
||||
if "certificate" in account:
|
||||
secconf += "\nCertificateFile {certificate}".format(**account)
|
||||
imappassEscaped = account["imappass"].replace("\\", "\\\\")
|
||||
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:
|
||||
f.write(mbsyncStr)
|
||||
|
||||
# msmtp
|
||||
MSMTP_BEGIN = """defaults
|
||||
protocol smtp
|
||||
auth on
|
||||
tls_trust_file /etc/ssl/certs/ca-certificates.crt
|
||||
|
||||
"""
|
||||
|
||||
MSMTP_ACCOUNT = """account {account}
|
||||
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)
|
||||
mbsyncFilepath = os.path.join(os.path.expanduser('~'), '.config/msmtp/config')
|
||||
with open(mbsyncFilepath, 'w') as f:
|
||||
f.write(msmtpStr)
|
||||
|
||||
|
||||
# notmuch
|
||||
NOTMUCH_BEGIN = """[database]
|
||||
path={storage}
|
||||
|
||||
[user]
|
||||
name={main[name]}
|
||||
primary_email={main[from]}
|
||||
other_email={other_email}
|
||||
|
||||
[new]
|
||||
tags=unprocessed;unread;
|
||||
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)
|
||||
mbsyncFilepath = os.path.join(os.path.expanduser('~'), '.config/notmuch-config')
|
||||
with open(mbsyncFilepath, 'w') as f:
|
||||
f.write(notmuchStr)
|
||||
|
||||
# mutt (temp)
|
||||
|
||||
## mailboxes
|
||||
MAILBOXES_BEGIN = "mailboxes"
|
||||
|
||||
mailboxesStr = MAILBOXES_BEGIN
|
||||
for name, account in accounts.items():
|
||||
lines = "-" * (20 - len(name))
|
||||
mailboxesStr += f' "+{name}{lines}"'
|
||||
for root, dirs, files in os.walk(account['storage']):
|
||||
if "cur" not in dirs or "new" not in dirs or "tmp" not in dirs:
|
||||
continue
|
||||
assert root.startswith(storageFull)
|
||||
path = root[len(storageFull)+1:]
|
||||
mailboxesStr += f' "+{path}"'
|
||||
mailboxesStr += "\n"
|
||||
mailboxesFilepath = os.path.join(os.path.expanduser('~'), '.mutt/mailboxes')
|
||||
with open(mailboxesFilepath, 'w') as f:
|
||||
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
|
||||
muttFilepath = os.path.join(os.path.expanduser('~'), f'.mutt/accounts/{name}')
|
||||
with open(muttFilepath, 'w') as f:
|
||||
f.write(muttStr)
|
||||
|
||||
# Signature
|
||||
sigStr = account.get("sig", account.get("name", ""))
|
||||
sigFilepath = os.path.join(os.path.expanduser('~'), f'.mutt/accounts/{name}.sig')
|
||||
with open(sigFilepath, 'w') as f:
|
||||
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)
|
||||
selectFilepath = os.path.join(os.path.expanduser('~'), '.mutt/muttrc')
|
||||
with open(selectFilepath, 'w') as f:
|
||||
f.write(selectStr)
|
||||
|
||||
## Color
|
||||
for name, account in accounts.items():
|
||||
# Config
|
||||
colorFilepath = os.path.join(os.path.expanduser('~'), f'{general["storage"]}/{name}/color')
|
||||
with open(colorFilepath, 'w') as f:
|
||||
f.write(account['color'])
|
Loading…
Add table
Add a link
Reference in a new issue