import os import sys from email.mime.text import MIMEText from email.header import Header from email.mime.multipart import MIMEMultipart from email.utils import formataddr # from email import policy # from lxml import etree import subprocess import filing from nitpo import Nitpo from sheets import Sheets import docing import re class Emailer(Nitpo): def __init__(self, do_verbose=False): """subscription profiles""" super().__init__() self.sheets = Sheets() self.repis_fufi = None self.do_verbose = do_verbose # # can be set in the headers self.params = {} # # debug if on local computer self.debug = os.path.isfile('/etc/wpa_supplicant.conf') # self.re_nama = re.compile(r"([^<]+)<([^@]+)@([^>]+)>\s*") self.re_nama = re.compile(r"([^<]+)<([^>]+)>\s*") def prepare(self, maix, empro='repis', in_what='empros', dont_send=False, base='base', only=None): """send the email via file, stores the file in base""" mail_fufi = self.conf['folders']['mail'] + '/' + base + '.mail' if os.path.isfile(mail_fufi) and not dont_send: print(f"emailer sees {mail_fufi}, skip") return None # # save xml, for debugging maix_fufi = self.conf['folders']['mail'] + '/' + base + '.xml' if self.debug and empro == 'repis': filing.prepare(maix_fufi) maix_file = open(maix_fufi, 'w') string = docing.show(maix) maix_file.write(string) maix_file.close() # head_doc = self.sheets.get_result(empro + '_head', maix) # sheet_fufi = self.sheets.get_sheet_fufi(empro + '_head') sheet_fufi = self.get_empro_part(empro, 'head', in_what=in_what) #print(sheet_fufi) #quit() head_doc = self.sheets.via_system(sheet_fufi, maix) msg = MIMEMultipart("alternative") xp = '/n:headers/n:header' header_eles = head_doc.xpath(xp, namespaces={'n': self.const['ns']}) for header_ele in header_eles: if 'name' not in header_ele.attrib: show_head_ele = docing.show(header_ele) print(f"email: no name in {show_head_ele}", file=sys.stderr) quit() continue name = header_ele.attrib['name'] if 'value' not in header_ele.attrib: show_head_ele = docing.show(header_ele) print(f"email: no value in {show_head_ele}", file=sys.stderr) quit() continue value = header_ele.attrib['value'] # # if all uppercase names, it's a parameter if name.upper() == name: self.params[name] = value continue if self.is_it_ascii(value): msg[name] = value continue if header_ele.get('type') == 'address': out = str(self.make_address(value)) if out is not None: msg[name] = out continue msg[name] = Header(value, 'utf-8') if only != 'html': # empro_text = empro + '_text' sheet_fufi = self.get_empro_part(empro, 'text', in_what=in_what) if sheet_fufi is not None: string = self.sheets.via_system(sheet_fufi, maix, is_text=True) # string = docing.show(html) if dont_send: print(string) part = MIMEText(str(string), "plain", _charset='utf-8') msg.attach(part) #if self.has_conf('sheets', empro_text): # # text = self.sheets.get_result(empro_text, maix) # # detour via sytem # sheet_fufi = self.sheets.get_sheet_fufi(empro + '_text') # text = self.sheets.via_system(sheet_fufi, maix, is_text=True) # part = MIMEText(str(text), "plain") # msg.attach(part) if only != 'text': # empro_html = empro + '_html' # if self.has_conf('sheets', empro_html): # # html = self.sheets.get_result(empro_html, maix) # # detour via sytem # sheet_fufi = self.sheets.get_sheet_fufi(empro + '_html') # html = self.sheets.via_system(sheet_fufi, maix) # string = docing.show(html) # part = MIMEText(str(string), "html", # _charset='utf-8') # msg.attach(part) # # print(html) sheet_fufi = self.get_empro_part(empro, 'html', in_what=in_what) if sheet_fufi is not None: html = self.sheets.via_system(sheet_fufi, maix) string = docing.show(html) part = MIMEText(str(string), "html", _charset='utf-8') msg.attach(part) mail_fufi = self.conf['folders']['mail'] + '/' + base + '.mail' filing.prepare(mail_fufi) mail_file = open(mail_fufi, 'w') mail_file.write(msg.as_string()) mail_file.close() if dont_send is True: print(f"emailer wrote {mail_fufi}, not sent") return None mail_command = f"cat {mail_fufi} | /usr/sbin/exim4 -t" envelope_address = self.get_envelope_address() if envelope_address is not None: mail_command += f" -f {envelope_address}" # # don't send on the test machine if not os.path.isfile('/etc/wpa_supplicant.conf'): out = subprocess.run(mail_command, shell=True, check=True) else: print(f"emailer wrote {mail_fufi}") out = None return out def get_envelope_address(self): if 'ENVELOPE_ADDRESS' in self.params: return self.params['ENVELOPE_ADDRESS'] if self.has_conf('addresses', 'envelope'): return self.conf['addresses']['envelope'] return def is_it_ascii(self, string): try: string.encode('ascii') except UnicodeEncodeError: return False return True def make_address(self, nama): out = self.re_nama.match(nama) if(out is None): print(f"emailer can't parse '{nama}'") return None name = out.group(1).strip() emad = out.group(2).strip() # # https://stackoverflow.com/questions/10551933/python-email-module-form-header-from-with-some-unicode-name-email address = formataddr((str(Header(name, 'utf-8')), emad)) return address def has_it_empro(self, empro, in_what='empros'): """is there is empro available""" if self.get_empro_part(empro, 'head', in_what=in_what) is None: return False if self.get_empro_part(empro, 'text', in_what=in_what) is not None: return True if self.get_empro_part(empro, 'html', in_what=in_what) is not None: return True return True def get_empro_part(self, empro, part, in_what='empros'): """empro part either by sheets conf or seen""" target = f"{empro}_{part}" ### check the configuration if self.has_conf('sheets', target): fufi = self.conf['sheets'][target] if not os.path.isfile(fufi): print(f"emailer does not see {fufi}", file=sys.stderr) return None return fufi if not self.has_conf('folders', in_what): print(f"emailer: not [folders][{in_what}] configured.", file=sys.stderr) what_fudi = self.conf['folders'][in_what] fufi = f"{what_fudi}/{target}.xslt.xml" if os.path.isfile(fufi): return fufi # # try empros what_fudi = self.conf['folders']['empros'] fufi = f"{what_fudi}/{target}.xslt.xml" if not os.path.isfile(fufi): print(f"emailer does not see {fufi}", file=sys.stderr) return None return fufi