#!/usr/bin/env python3 # SPDX-FileCopyrightText: Daniel Pätzold # SPDX-License-Identifier: AGPL-3.0-or-later # # Will prepare local mozilla and thunderbird folders with given tar.files # import re import sys import subprocess import certifi import tarfile import shutil import os from os import environ # See https://pypi.org/project/webdavclient3/ # needs pip install webdavclient3 from webdav3.client import Client #Variables thunderbird_tar = os.path.dirname(__file__) + '/thunderbird.tar.zst' firefox_tar = os.path.dirname(__file__) + '/firefox.tar.zst' firefoxhome_path = environ['HOME'] + "/.config/mozilla/firefox" firefoxhome_profile_src = os.path.dirname(__file__) + '/profiles_ff.ini' firefoxhome_profile_dst = firefoxhome_path + '/profiles.ini' #Check Env if not 'DAVTOKEN_USER' in environ: print("Error: Script cannot be executed standalone and needs a prereserved Environment. Quit.") sys.exit(1) options = { 'webdav_hostname': "https://" + environ['SERVERFQDN_NC'] + "/remote.php/dav/files/" + environ['DAVTOKEN_USER'], 'webdav_login': environ['DAVTOKEN_USER'], 'webdav_password': environ['DAVTOKEN_PASS'] } client = Client(options) #client.verify = False # To not check SSL certificates (Default = True) if 'PROFILE_FIREFOX_RESET_LOCAL' in environ: #Remove all files in ~/mozilla print("Removing " + firefoxhome_path) shutil.rmtree(firefoxhome_path) print("Extracting " + firefox_tar + " to " + firefoxhome_path) if not os.path.exists(firefoxhome_path): # Recreate os.makedirs(firefoxhome_path) tar = tarfile.open(firefox_tar) tar.extractall(path = firefoxhome_path, filter = 'data') tar.close() shutil.copyfile(firefoxhome_profile_src, firefoxhome_profile_dst) # Copy initial profiles.ini to dir print("Done.") #Firefox first profile setup if 'PROFILE_FIREFOX_SRC' in environ: # Check and setup mozilla pathstr = environ['PROFILE_FIREFOX_SRC'] + "/default" if not client.check(pathstr): print("Path " + pathstr + " was not found on Server. Creating it.") i = 0 while i >= 0: #Dive into subfolders of string i = pathstr.find("/", i + 1) if i >= 0: #print("/" + pathstr[:i]) if not client.check(pathstr[:i]): client.execute_request("mkdir", "/" + pathstr[:i]) #print("/" + pathstr) client.execute_request("mkdir", "/" + pathstr) print("Done.") #Check and create local Folder if not os.path.exists(environ['PROFILE_FIREFOX_DST'] + "/default"): os.makedirs(environ['PROFILE_FIREFOX_DST'] + "/default") #First sync to initialise sync-db print("Call " + environ['SYSCONFIGPATH'] + "/system_setup/mozilla_starter.sh firefox sync") retstr = subprocess.call(['sh', environ['SYSCONFIGPATH'] + '/system_setup/mozilla_starter.sh', 'firefox', 'sync']) #Extract empty firefox profile to Folder print("Extracting " + firefox_tar + " to " + environ['PROFILE_FIREFOX_DST']) tar = tarfile.open(firefox_tar) tar.extractall(path=environ['PROFILE_FIREFOX_DST'],filter='data') tar.close() print("Done.") #Next sync will be executed by logon script #Thunderbird first profile setup if 'PROFILE_TB_SRC' in environ: # Check and setup mozilla pathstr = environ['PROFILE_TB_SRC'] + "/default" if not client.check(pathstr): print("Path " + pathstr + " was not found on Server. Creating it.") i = 0 while i >= 0: #Dive into subfolders of string i = pathstr.find("/", i + 1) if i >= 0: #print("/" + pathstr[:i]) if not client.check(pathstr[:i]): client.execute_request("mkdir", "/" + pathstr[:i]) #print("/" + pathstr) client.execute_request("mkdir", "/" + pathstr) print("Done.") #Check and create local Folder if not os.path.exists(environ['PROFILE_TB_DST'] + "/default"): os.makedirs(environ['PROFILE_TB_DST'] + "/default") #First sync to initialise sync-db print("Call " + environ['SYSCONFIGPATH'] + "/system_setup/mozilla_starter.sh thunderbird sync") retstr = subprocess.call(['sh', environ['SYSCONFIGPATH'] + '/system_setup/mozilla_starter.sh', 'thunderbird', 'sync']) #Extract empty firefox profile to Folder print("Extracting " + thunderbird_tar + " to " + environ['PROFILE_TB_DST']) tar = tarfile.open(thunderbird_tar) tar.extractall(path=environ['PROFILE_TB_DST'],filter='data') tar.close() print("Done.") #Next sync will be executed by logon script # Check and auto-provision IMAP account for DAVTOKEN_USER@TLDOMAIN in Thunderbird if ('PROFILE_TB_DST' in environ and 'TLDOMAIN' in environ and 'SERVERFQDN_IMAP' in environ and 'DAVTOKEN_USER' in environ): prefs_path = environ['PROFILE_TB_DST'] + "/default/prefs.js" mail_user = environ['DAVTOKEN_USER'] + "@" + environ['TLDOMAIN'] mail_user_url = mail_user.replace('@', '%40') imap_host = environ['SERVERFQDN_IMAP'] full_name = environ.get('TB_MAIL_FULLNAME', environ['DAVTOKEN_USER']) profile_dir = environ['PROFILE_TB_DST'] + "/default" if not os.path.exists(prefs_path): print("Thunderbird prefs.js not found, skipping mail account setup.") else: with open(prefs_path, 'r') as f: prefs = f.read() account_exists = bool(re.search( r'mail\.server\.server\d+\.userName",\s*"' + re.escape(mail_user) + '"', prefs )) if account_exists: print(f"Thunderbird IMAP account for {mail_user} already configured.") else: print(f"Adding Thunderbird IMAP account for {mail_user} ...") server_nums = [int(x) for x in re.findall(r'mail\.server\.server(\d+)\.type', prefs)] account_nums = [int(x) for x in re.findall(r'mail\.account\.account(\d+)\.server', prefs)] id_nums = [int(x) for x in re.findall(r'mail\.identity\.id(\d+)\.useremail', prefs)] ns = (max(server_nums) + 1) if server_nums else 1 na = (max(account_nums) + 1) if account_nums else 1 ni = (max(id_nums) + 1) if id_nums else 1 sn, an, idn = f"server{ns}", f"account{na}", f"id{ni}" new_lines = [ f'user_pref("mail.server.{sn}.check_new_mail", true);', f'user_pref("mail.server.{sn}.cleanup_inbox_on_exit", true);', f'user_pref("mail.server.{sn}.directory", "{profile_dir}/ImapMail/{imap_host}");', f'user_pref("mail.server.{sn}.directory-rel", "[ProfD]ImapMail/{imap_host}");', f'user_pref("mail.server.{sn}.hostname", "{imap_host}");', f'user_pref("mail.server.{sn}.login_at_startup", true);', f'user_pref("mail.server.{sn}.max_cached_connections", 5);', f'user_pref("mail.server.{sn}.name", "{mail_user}");', f'user_pref("mail.server.{sn}.port", 993);', f'user_pref("mail.server.{sn}.socketType", 3);', f'user_pref("mail.server.{sn}.storeContractID", "@mozilla.org/msgstore/maildirstore;1");', f'user_pref("mail.server.{sn}.timeout", 29);', f'user_pref("mail.server.{sn}.trash_folder_name", "Trash");', f'user_pref("mail.server.{sn}.type", "imap");', f'user_pref("mail.server.{sn}.userName", "{mail_user}");', f'user_pref("mail.identity.{idn}.draft_folder", "imap://{mail_user_url}@{imap_host}/Drafts");', f'user_pref("mail.identity.{idn}.drafts_folder_picker_mode", "0");', f'user_pref("mail.identity.{idn}.fcc_folder", "imap://{mail_user_url}@{imap_host}/Sent");', f'user_pref("mail.identity.{idn}.fcc_folder_picker_mode", "0");', f'user_pref("mail.identity.{idn}.fullName", "{full_name}");', f'user_pref("mail.identity.{idn}.reply_on_top", 1);', f'user_pref("mail.identity.{idn}.stationery_folder", "imap://{mail_user_url}@{imap_host}/Templates");', f'user_pref("mail.identity.{idn}.tmpl_folder_picker_mode", "0");', f'user_pref("mail.identity.{idn}.useremail", "{mail_user}");', f'user_pref("mail.identity.{idn}.valid", true);', f'user_pref("mail.account.{an}.identities", "{idn}");', f'user_pref("mail.account.{an}.server", "{sn}");', ] # Append account to mail.accountmanager.accounts m = re.search(r'(mail\.accountmanager\.accounts",\s*")([^"]+)(")', prefs) if m: prefs = prefs[:m.start(2)] + m.group(2) + ',' + an + prefs[m.end(2):] else: new_lines.append(f'user_pref("mail.accountmanager.accounts", "{an}");') # Update mail.account.lastKey m = re.search(r'(mail\.account\.lastKey",\s*)(\d+)', prefs) if m: prefs = prefs[:m.start(2)] + str(max(int(m.group(2)), na)) + prefs[m.end(2):] prefs = prefs.rstrip('\n') + '\n' + '\n'.join(new_lines) + '\n' with open(prefs_path, 'w') as f: f.write(prefs) print(f"Thunderbird IMAP account for {mail_user} added successfully.") sys.exit(0)