Hei. Olisin toivonut neuvoa. Olen pitkään yrittänyt tehdä sähköpostiohjelmaa Pythonilla(3), mutta en ole saanut sellaista toimimaan kunnolla. Lähettämispuoli onnistuu kyllä liitteineen oikein hyvin, mutta saapuvien puolella on ongelmia. Olen kokeillut monia valmisohjelmia ja tässä linkissä on yksi parhaista, mitä olen löytänyt:
https://www.thepythoncode.com/article/reading-emails-in-python
Tämä melkein näyttäisi toimivan, mutta sitten huomasin ongelman, mitä en saanut ratkaistuksi. account-security-noreply@accountprotection.microsoft.com lähetti minulle postia ja otsikossa(subject) oli seuraava viesti "Tarkista sähköpostiosoite" Tämä ohjelmani osasi avata kaikki muut sähköpostit, mutta ei tätä ja se johtuu otsikosta. Avasin hieman ohjelmaa ja tein tällaisen havainnon (b'Tarkista ' None)
# decode the email subject subject, encoding = decode_header(msg["Subject"])[0] if isinstance(subject, bytes): # if it's a bytes, decode to str subject = subject.decode(encoding)
Näyttäisi siltä, että otsikko koostuu kahdenlaisesta sisällöstä, mahdollisesti koodattu eri tavalla. Mieleeni tulee esimerkkinä tekstiä ja hymiö(kuva). Sitten keksin, että se varmaan johtuu ääkkösistä otsikossa?? Muissakin sähköposteissa oli otsikoissa ääkkösiä(toimi), mutta ehkä tämä on koodattu jotenkin toisin?
Jotenkin kun saisi tämän ratkaistuksi, niin se olisi iso apu.
Kiitos jos saan apua.
Keksin jotakin...
(b'Tarkista ' None)
Mikäli tässä olisi ollut jokin muu otsikko kuin edellä mainittu, niin se olisi näyttänyt tältä:
Osta keksejä
(b'Osta keksejä', 'utf-8')
tai
(b'Osta keksejä', 'iso-8859-1')
siis näyttää siltä, että tuo Microsoft käyttää jotain koodausta, mitä tämä ohjelma ei ymmärrä ja siksi tulee tuo None:
(b'Tarkista ', None)
Ensin en keksi mitään viikkoihin ja nyt kun kirjoitan, niin ideoita syntyy???
Taisin keksiä syyn:
subject, encoding = decode_header(msg["Subject"])[0]
Jos muokkaan tätä hieman:
xxxxx=decode_header(msg["Subject"]) print(xxxxx)
Nyt havaitsen seuraavaa:
[(b'Tarkista ', None), (b's\xe4hk\xf6postiosoite', 'iso-8859-1')]
Ohjelma ei siis näköjään vain ymmärrä, että otsikossa voi olla kahta erilaista muotoilua. Miten voisin korjata ohjelmaa, tämä ei varmaan enää ole kovin vaikea ongelma???
Voisit katsoa myös sitä alkuperäistä otsikkoa (ennen dekoodausta), niin ehkä siitä selviäisi. Itse veikkaan, että muut enkoodaavat koko otsikon kerralla mutta tuossa tapauksessa alun ASCII-osuus on sellaisenaan ja vasta toinen sana on koodattu.
Subject: =?iso-8859-1?Q?Kaikki_yhdess=E4?= Subject: Palat =?iso-8859-1?Q?yksitt=E4in?=
Ainakin osat voi yhdistää näin:
osat = [(b'Tarkista ', None), (b's\xe4hk\xf6postiosoite', 'iso-8859-1')] teksti = "".join(tavut.decode(koodaus or "ASCII") for tavut, koodaus in osat)
Toisaalta jos tuo lähtötieto on tyypiltään email.header.Header, sen voi suoraan muuttaa tekstiksi ja saada tuon saman lopputuloksen.
teksti = str(msg["Subject"])
Ja jos tuo pätee, niin silloin kannattaa varmaan myös päivittää koko koodia, koska yllä linkittämäni sivun mukaan kyseinen luokka on vanhentunut ja nykyaikaisempi tapa viestien käsittelyyn olisi email.message.EmailMessage. ;)
Ei voi olla totta, tämähän näyttäisi toimivan.
Kiitos:-)
Vielä...
Kysyn nyt vielä kuitenkin yhtä asiaa, kun olet noin osaava:
Joissain sähköposteissa on muotoilukoodeja, kuten <p><br> border="0"></div>, jne..
Onko jotakin helppoa konstia poistaa kaikista viesteistä nämä koodit, jotta näkisin vain puhtaan tekstin?
Use plain text instead of HTML
Lipton_green kirjoitti:
Onko jotakin helppoa konstia poistaa kaikista viesteistä nämä koodit, jotta näkisin vain puhtaan tekstin?
HTML-tagien poistaminen tuottaa visuaalisesti aivan eri lopputuloksen. Esimerkiksi taulukot ovat rikki, tekstin rivitys on rikki, tyhjiä rivejä ja sisennyksiä voi olla mielin määrin jne., ja lisäksi CSS:llä voi muuttaa tilannetta vielä vaikeammaksi.
Moniosaisessa viestissä (Content-Type: multipart/mixed) saattaa yhtenä osana olla tekstimuotoinen versio (text/plain), jolloin kannattaa ehkä käyttää sitä.
Varmaan netissä on erilaisia ratkaisuja, miten HTML tulisi kivaan tekstimuotoon. Koodailin nyt huvin vuoksi tällaisen Pythonin luokkaan html.parser.HTMLParser perustuvan viritelmän, joka käsittelee pari yleisintä tagia jotenkin ja tuottaa ehkä suunnilleen lukukelpoista tekstiä. Sisennykset ovat vähän päin mäntyä, kun en nyt jaksanut hienostella enempää muuttujia ja erikoistapauksia välilyöntien karsimiseen.
import html.parser, re class HTMLToTextParser(html.parser.HTMLParser): def __init__(self): super().__init__() self.data = "" self.whitespace = "" self.pre = False self.pause = False def __str__(self): return self.data def handle_starttag(self, tag, attrs): if tag in ["br"]: self.data += "\n" if tag in ["pre"]: self.pre = True if tag in ["script", "style"]: self.pause = True def handle_startendtag(self, tag, attrs): if tag in ["br"]: self.data += "\n" def handle_endtag(self, tag): if tag in ["script", "style"]: self.pause = False if tag in ["pre"]: self.pre = False self.whitespace = "\n\n" if tag in ["td", "th"]: self.whitespace = "\t" if tag in ["li", "caption", "tr", "dt", "dd"]: self.whitespace = "\n" if tag in ["title", "h1", "h2", "h3", "p", "table", "ul", "ol", "dl", "div", "blockquote"]: self.whitespace = "\n\n" def handle_data(self, data): if self.pause: return if not self.pre: data = re.sub(r'\s+', ' ', data) if self.whitespace: self.data += self.whitespace self.whitespace = "" if not self.pre: data = re.sub(r'^\s+', '', data) self.data += data def html_to_text(data): p = HTMLToTextParser() p.feed(data) return str(p) # Testiohjelma: python tämä.py sivu.html import sys print(html_to_text(open(sys.argv[1]).read()))
Kiitos, pohdin tuota ohjelmaasi.
Törmäsin muuten sittenkin pieneen ongelmaan varsinaisessa sähköpostiohjelmassa.
https://www.thepythoncode.com/article/reading-emails-in-python
Yksi sähköpostin lähettäjä ei laittanut ollenkaan tekstiä viestiin, vain kuvan. Nyt tämä ohjelma laittaa tähän viestiin sisällön edellisestä sähköpostista, missä oli html. tekstiä. Jotenkin pitäisi saada nollattua "body" jokaisen viestinluvun jälkeen.
if content_type == "text/plain" and "attachment" not in content_disposition: # print text/plain emails and skip attachments print(body)
PS. En vaivaa kauaa, kiitos.
Vielä edelliseen. Laitoin laskurin näihin viesteihin, niin tekstitön viesti antaa saman järjestysnumeron(N) kuin edellinen viesti.
status, messages = imap.select("INBOX") # number of top emails to fetch N = 3 # total number of emails messages = int(messages[0])
Keksin jo, kiitos kaikille:-)
Aihe on jo aika vanha, joten et voi enää vastata siihen.