Skip to content

Commit

Permalink
Lähetä luettelot sähköpostilla
Browse files Browse the repository at this point in the history
  • Loading branch information
ohylli committed Sep 24, 2017
1 parent 3056b99 commit cc2bac1
Show file tree
Hide file tree
Showing 4 changed files with 136 additions and 19 deletions.
8 changes: 8 additions & 0 deletions posti.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"lähettäjä": "[email protected]",
"vastaanottajat": [ "[email protected]" ],
"palvelin": "smtp.example.com",
"portti": 465,
"käyttäjä": "käyttäjä",
"salasana": "salasana123"
}
46 changes: 46 additions & 0 deletions posti.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# -*- coding: utf-8 -*-

from email.mime.text import MIMEText
import smtplib
import json

class Postittaja():
"""Luokka uutuusluetteloiden lähettämiseen sähköpostilla."""

def __init__( self ):
'''Luo Postittaja posti.json konfiguraatio tiedoston määräämillä asetuksilla.'''
# lue konfiguraatio tiedostosta ja muunna json python sanakirjaksi
with open( 'posti.json', 'r', encoding = 'utf-8' ) as tiedosto:
konfiguraatio = json.load( tiedosto )

# tallenna konfiguraation sisältö muuttujiin
self.lähettäjä = konfiguraatio[ 'lähettäjä' ]
self.vastaanottajat = konfiguraatio[ 'vastaanottajat' ]
palvelinNimi = konfiguraatio['palvelin']
portti = konfiguraatio[ 'portti' ]
käyttäjä = konfiguraatio[ 'käyttäjä' ]
salasana = konfiguraatio[ 'salasana' ]

# Luo asiakas sähköpostipalvelimelle, joka on määritelty konfiguraatiotiedostossa
# käytetään heti SSL salattua yhteyttä
# ainakin soneran palvelin mail.inet.fi vaatii heti salatun yhteyden eli ei voida luoda salaamatonta asiakasta ja sitten käynnistää salattua yhteyttä
self.palvelin = smtplib.SMTP_SSL( palvelinNimi, portti )
# kirjaudutaan palvelimelle konfiguraatiossa olleilla käyttäjätunnuksella ja salasanalla
self.palvelin.login( käyttäjä, salasana )

def postita( self, luettelo ):
'''Postittaa parametrina saadun luettelo sanakirjan määrittämän uutuusluettelon.'''
# luetaan uutuusluettelon sisältö tiedostosta
tiedosto = open( luettelo['tiedosto'], 'r' )
runko = tiedosto.read()
tiedosto.close()
# luodaan tekstimuotoinen lähetettävä viesti, jonka rungoksi asetetaan luettelon sisältö
viesti = MIMEText( runko, 'plain' )
# asetetaan viestin lähettäjä
viesti['From'] = self.lähettäjä
# asetetaan vastaanottajat. Yhdistetään vastaanottaja listan osoitteet yhdeksi merkkijonoksi pilkulla eroteltuna
viesti['To'] = ','.join( self.vastaanottajat )
# asetetaan viestin otsikoksi luettelon otsikko
viesti['Subject'] = luettelo['otsikko']
# lähetetään viesti
self.palvelin.send_message( viesti )
25 changes: 22 additions & 3 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

Celia uutuudet on työkalu tekstimuotoisten uutuuskirjaluetteloiden luomiseen [Celia kirjaston](http://www.celia.fi) nettisivuilta löytyvistä uutuusluetteloista.
Sivustolla olevat uutuusluettelot eivät sisällä suoraan kirjojen kuvauksia, vaan ne joutuu katsomaan erikseen linkin takana olevalta sivulta. Jotkut käyttäjät kokevat tällaisen uutuusluettelon
hankalaksi. Tämä työkalu luo eri uutuusluettelosivuista uutuusluettelon tekstitiedostoon, joka sisältää kirjojen kuvaukset.
hankalaksi. Tämä työkalu luo eri uutuusluettelosivuista uutuusluettelon tekstitiedostoon, joka sisältää kirjojen kuvaukset. Luodut uutuusluettelot voi myös ohjelman avulla lähettää sähköpostilla haluamilleen vastaanottajille.

## Vaatimukset

Expand Down Expand Up @@ -31,6 +31,8 @@ Asenna ohjelman tarvitsemat kirjastot:

pip install -r requirements.txt

HUOM: riippuen Python asennuksestasi voivat komennot olla python3 ja pip3.

Luo uutuusluettelot:

python uutuushaku.py
Expand All @@ -39,15 +41,32 @@ Jokaisesta uutuudet sivusta aikuisten uutuudet, ja lasten ja nuorten uutuudet lu
luotuihin uutuusluetteloihin tulee vain ne kirjat, jotka on lisätty uutuudet sivuille edellisen luettelon luontikerran jälkeen. Tiedostossa vanhat.json pidetään kirjaa edellisen ajokerran uusimmista kirjoista eri kategorioissa.
Se ylikirjoitetaan ohjelman jokaisella ajokerralla, mutta siitä luodaan ennen ylikirjoitusta kopio tiedostoon edelliset_vanhat.json.

Ohjelma voi lähetää uutuusluettelot myös sähköpostitse haluamillesi vastaanottajille. Käyttääksesi ominaisuuta tulee ohjelma ensiksi konfiguroida sitä varten. Tiedostossa posti.json on sähköpostin lähetykseen tarvittavat asetukset:

- lähettäjä: oma sähköpostiosoitteesi
- vastaanottajat: lista vastaanottajien sähköpostiosoitteita
- palvelin: SMTP sähköpostipalvelimen osoite esim. Soneralla mail.inet.fi
- portti: TCP portti, johon palvelimella yhdistetään
- käyttäjä: Käyttäjätunnuksesi SMTP palvelimelle
- salasana: Salasanasi sähköpostipalvelimelle.

Sähköpostitusta hallitaan komentorivi parametrilla -p tai --posti, joka hyväksyy seuraavat arvot:

- ei: Luetteloita ei postiteta. Tämä on oletusarvo parametrille.
- kyllä: luettelot postitetaan heti kun ne on luotu
- kysy: Jokaisen luettelon kohdalla kysytään postitetaanko se.
- heti: Uusia luetteloita ei luoda, vaan ohjelma olettaa löytävänsä aikaisemmin luodut luettelot, jotka se postittaa heti.

## Ohjelman rakenne

Ohjelma koostuu neljästä lähdekooditiedostosta:
Ohjelma koostuu viidestä lähdekooditiedostosta:

- uutuushaku.py: pääohjelma, joka aloittaa uutuuksien haun
- uutuusluettelo.py: sisältää luokan uutuusluettelosivujen käsittelyyn
- kirja.py: sisältää luokan yksittäisen kirjan tiedot sisältävän sivun käsittelyyn
- kasitellyt.py: sisältää Käsitellyt luokan, jolla pidetään kirjaa edellisellä kerralla jo käsitellyistä kirjoista
- posti.py: Sisältää Postittaja luokan luetteloiden lähettämiseen sähköpostilla.

Pääohjelma luo eri uutuusluettelosivujen käsittelemiseen oman Uutuusluettelo tai sen aliluokan instanssin. Uutuusluettelo instanssi käy annetun uutuusluettelo sivun läpi kirjoittaen sen sisältöä annetun nimiseen tekstitiedostoon.
Uutuusluettelo käyttää KirjaSivu luokan instansseja yksittäisen kirjan tiedot sisältävien sivujen käsittelyyn eli kirjan tietojen hakemiseen sivulta.
Uuutuusluettelo käyttää Käsitellyt luokkaa kirjan pitämiseen siitä, mitkä kirjat eri kategorioista on käsitelty edellisellä kerralla. Luokan avulla myös tallennetaan tämän hetken uusimmat kirjat seuraavaa kertaa varten.
Uuutuusluettelo käyttää Käsitellyt luokkaa kirjan pitämiseen siitä, mitkä kirjat eri kategorioista on käsitelty edellisellä kerralla. Luokan avulla myös tallennetaan tämän hetken uusimmat kirjat seuraavaa kertaa varten. Pääohjelma käyttää Postittaja luokkaa luetteloiden lähettämiseen sähköpostilla.
76 changes: 60 additions & 16 deletions uutuushaku.py
Original file line number Diff line number Diff line change
@@ -1,37 +1,81 @@
# -*- coding: utf-8 -*-

# moduuli komentoriviparametrien käsittelyyn
import argparse

# luokka uutuusluetteloiden käsittelyyn
from uutuusluettelo import Uutuusluettelo
# luokka kirjanpitämiseen edellisen luettelon luonti kkerran kirjoista
# luokka kirjanpitämiseen edellisen luettelon luontikerran kirjoista
from kasitellyt import Käsitellyt

# luokka luetteloiden lähettämiseen sähköpostilla
from posti import Postittaja

def kysyPostitetaanko( luettelo ):
'''Postitus vaiheessa käytettävä funktio
Jos käyttäjä määrittää komentoriviparametrilla, että häneltä kysytään postitetaanko luettelot,
käytetään tätä funktiota käyttäjältä luvan kysymiseen jokaisen luettelon postituksesta.'''
# käyttäjän vastaus kysymykseen
vastaus = ''
# kysytään kunnes käyttäjä vastaa k tai e
while vastaus not in [ 'k', 'e' ]:
vastaus = input( 'Lähetetäänkö ' +luettelo['tiedosto'] + ' sähköpostilla. Vastaa k tai e: ' )

return vastaus == 'k'

# määritetään ohjelman komentorivi parametrit
komentorivi = argparse.ArgumentParser()
# määritetään -p valitsin, jolla valitaan miten luetteloiden sähköpostilla lähetyksen kanssa toimitaan
komentorivi.add_argument( '-p', '--posti',
choices = [ 'kyllä', 'ei', 'kysy', 'heti' ],
default = 'ei',
help = 'Määrittele miten luettelot postitetaan' )
# käsitellään komentoriviparametrit
parametrit = komentorivi.parse_args()

# määritetään mitä uutuusluetteloita käsitellään
# luettelosta määritetään osoite mistä uutuudet löytyvät
# tiedosto, johon ne tallennetaan ja luokka, jonka instanssilla luettelo käsitellään
# tiedosto, johon ne tallennetaan, luettelon nimi ja luokka, jonka instanssilla luettelo käsitellään
luettelot = [
{
'url': 'https://www.celianet.fi/kirjavinkit/uutuuskirjat-aikuisille/',
'otsikko': 'Aikuisten uutuudet',
'tiedosto': 'aikuisten_uutuudet.txt',
'luettelo': Uutuusluettelo
},
{
'url': 'https://www.celianet.fi/kirjavinkit/lasten-uutuuskirjat/',
'otsikko': 'Lasten ja nuorten uutuudet',
'tiedosto': 'lasten_ja_nuorten_uutuudet.txt',
'luettelo': Uutuusluettelo
}
]

# olio, josta luetaan edellisen luettelon luonti kerran uusimmat kirjat eri kategorioista, joita vanhempia
# kirjoja ei lisätä nyt luotaviin luetteloihin.
# tähän myös tallennetaan tällä hetkellä uusimmat kirjat eri kategorioista, jolloin niitä ei luetteloida ensi kerralla
# tiedot luetaan ja tallennetaan json muodossa vanhat.json tiedostoon
vanhat = Käsitellyt( "vanhat.json" )
# käsitellään jokainen luettelo
for luettelo in luettelot:
# luodaan luettelon käsittely luokasta instanssi, jolle annetaan osoite, josta luettelo löytyy, nimi tiedostolle, johon uutuudet tallennetaan, sekä tiedot käsitellyistä kirjoista
hakija = luettelo['luettelo']( luettelo['url'], luettelo['tiedosto'], vanhat )
# haetaan kirjat ja tallennetaan tiedostoon
hakija.haeKirjat()
# jos käyttäjä haluaa postittaa aikaisemmin luodut luettelot ei luoda niitä nyt
if parametrit.posti != 'heti':
# olio, josta luetaan edellisen luettelon luonti kerran uusimmat kirjat eri kategorioista, joita vanhempia
# kirjoja ei lisätä nyt luotaviin luetteloihin.
# tähän myös tallennetaan tällä hetkellä uusimmat kirjat eri kategorioista, jolloin niitä ei luetteloida ensi kerralla
# tiedot luetaan ja tallennetaan json muodossa vanhat.json tiedostoon
vanhat = Käsitellyt( "vanhat.json" )
# käsitellään jokainen luettelo
print( 'luodaan luetteloita.' )
for luettelo in luettelot:
# luodaan luettelon käsittely luokasta instanssi, jolle annetaan osoite, josta luettelo löytyy, nimi tiedostolle, johon uutuudet tallennetaan, sekä tiedot käsitellyistä kirjoista
hakija = luettelo['luettelo']( luettelo['url'], luettelo['tiedosto'], vanhat )
# haetaan kirjat ja tallennetaan tiedostoon
hakija.haeKirjat()

# tallennetaan tämän luettelon eri kategorioiden uusimmat seuraavaa kertaa varten
vanhat.tallenna()

# tallennetaan tämän luettelon eri kategorioiden uusimmat seuraavaa kertaa varten
vanhat.tallenna()
# postitetaan luettelot jos käyttäjä niin halusi
if parametrit.posti in [ 'kyllä', 'kysy', 'heti' ]:
# luodaan postin lähettäjä konfiguraation pohjalta
postittaja = Postittaja()
# käydään luettelot läpi
for luettelo in luettelot:
# postitetaan luettelo heti jos käyttäjä niin halusi muuten kysytään jokaisen luettelon kohdalla haluaako käyttäjä sen lähettää
if parametrit.posti in [ 'kyllä', 'heti' ] or kysyPostitetaanko( luettelo ):
print( 'Postitetaan {}'.format( luettelo['otsikko'] ))
postittaja.postita( luettelo )

0 comments on commit cc2bac1

Please sign in to comment.