Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: Python: Sähköposti

Sivun loppuun

Lipton_green [12.11.2021 15:32:18]

#

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.

Lipton_green [12.11.2021 15:57:12]

#

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)

Lipton_green [12.11.2021 16:17:58]

#

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???

Metabolix [12.11.2021 17:10:23]

#

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. ;)

Lipton_green [12.11.2021 17:56:50]

#

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?

neosofta [12.11.2021 18:10:48]

#

Use plain text instead of HTML

Metabolix [12.11.2021 18:44:15]

#

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()))

Lipton_green [12.11.2021 19:33:36]

#

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.

Lipton_green [12.11.2021 19:37:52]

#

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])

Lipton_green [12.11.2021 19:43:36]

#

Keksin jo, kiitos kaikille:-)


Sivun alkuun

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta