pagina precedente

Script python

sendMailAttach.py - v. 1.0
Scritto da: Demaldè Gastone
Data: domenica 16 settembre 2007

Lo script permette di spedire una o più mail con uno o più attachment.
Sintassi: sendMailAttach.py  nomeFileMessaggi.xml

Il file contenente le informazioni relative ai messaggi da spedire è scritto in xml.
La sintassi del file è la seguente:

--- inizio file messaggi
<?xml version='1.0' encoding='iso-8859-15'?>
<msgs>
  <message>
    <from> ... </from>
    <!-- gli indirizzi multipli vanno separati con una virgola -->
    <to> ... </to>
    <cc> ... </cc>
    <bcc> ... </bcc>
    <subject> ... </subject>
    <body>
      ...
      ...
    </body>
    <!-- singolo nome di file per ogni tag <file> -->
    <file> ...</file>
    ...
    <file> ... </file>
  </message>

  <!-- eventuali altri messaggi da spedire -->
  <message>
    ...
  </message>
  ...
</msgs>

--- fine file messaggi-------

I tag del file xml devono essere scritti in minuscolo.
Per poter spedire i messaggi occorre cambiare la linea smtpHost = 'out.alice.it'
inserendo l'indirizzo IP o il nome del server SMTP che si util izza normalmente per spedire la posta.

Lo script fa del suo meglio per individuare dove si trovano il file dei messaggi e d i file da spedire in attach.
In particolare:
  &nb sp; - se non trova il file dei messaggi, prova a cercarlo nella
      directory dello script
    - se non trova i file da spedire, prova a cercarli nella directory
      del file dei messaggi e poi nella directory dello script.

Lo script può essere memorizzato in una posizione diversa rispetto al file xml dei messaggi.

Ad esempio:
    /usr/local/bin/sendMailAttach.py  /home/user/sendMailAttach/mail-1234.xml

Durante l'esecuzione viene generato un file di log contenente le operazioni eseguite e gli errori incontrati.
Il file di log si trova nella stessa cartella del file xml dei messaggi ed ha lo stesso nome del file dei messaggi seguito da una estensione .log
All'inizio dell'eleborazione, il file xml dei messaggi viene rinominato aggiungendo un .begin
Alla fine viene aggiunto un .end

In questo modo non è possibile lanciare per due volte lo stesso script, inoltre la presenza di un file senza .end indica una fine non prevista dell'esecuzione dello script.

Nel caso esistano già i file .begin e .begin.end, questi vengono sovrascritti.

Se si vuole utilizzare lo script in contemporanea da più applicazioni, bisogna assicurarsi di generare file xml con nomi diversi,
ad esempio inserendo nel nome del file xml:

    - data e ora di generazione,
    - nome utente,
    - numero casuale,
    - ecc.

I tag <file> sono opzionali e possono essere omessi.
Il loro numero non è limitato, quindi si possono spedire zero, uno o più attachment in ogni messaggio.

I vari tag possono essere omessi.
E' consigliato mettere sempre i tag <from>,<to>,<subject>,<body> per evitare rischi di filtraggio del messaggio da parte dei server.

E' consigliato anche mettere un indirizzo email valido nel campo <from>, in modo da ricevere le segnalazioni di errore dei server nel caso gli indirizzi di destinazione non fossero validi.

Nel caso di tag multipli, viene letto solo il primo. Sono gestite le ripetizioni solo del tag <file>.

Eventuali indirizzi multipli devono essere inseriti nei tag <to>, <cc>, <bcc> separandoli con le virgole.

Nel file xml è possibile inserire commenti:

<!-- inizio commento
fine commento -->

Nel file xml i caratteri speciali < e > possono essere utilizzati solo nei tag. Al di fuori dei tag, < e > devono essere sostituiti rispettivamente
con &lt; e &gt;

SCRIPT PYTHON  - send.py

#! /usr/bin/env python
# -*- coding: iso-8859-15 -*-
# name : ...path-sendmail/send.py
import email.MIMEMultipart
import email.MIMEText
import email.MIMEBase
import email.Encoders
import email.Utils
import smtplib
import time
import shutil
import sys
import os.path
import xml.dom.minidom

smtpHost = 'out.alice.it'

class Messaggio:
def __init__(self):
self.From=''
self.To=''
self.Cc=''
self.Bcc=''
self.Subject=''
self.Body=''
self.Files=[]
def __str__(self):
s = '--- inizio messaggio ---\n'
s += 'From: %s\n' % self.From
s += 'To: %s\n' % self.To
s += 'Cc: %s\n' % self.Cc
s += 'Bcc: %s\n' % self.Bcc
s += 'Subject: %s\n' % self.Subject
s += 'Body: %s\n' % self.Body
s += 'Files: %s\n' % self.Files
s += '--- fine messaggio ---'
return s.encode(charset)
def fromTo(self):
s = 'From: %s, To: %s' % (self.From,self.To)
return s.encode(charset)

def stampa(s):
print s
fLog.write(s + '\n')

def leggiTestoNodoXML(nodoXML):
t = ""
try:
for n in nodoXML.childNodes:
if n.nodeType == n.TEXT_NODE:
t = t + n.data
except: pass
return t

def leggiTags(nodo,tag):
testi = []
for n in nodo.getElementsByTagName(tag):
t = leggiTestoNodoXML(n)
testi.append(t)
if len(testi)==0 and tag!='file':
testi.append('')
return testi

def leggiMessaggi(nomeFile):
msgs = []
s = file(nomeFile).read()
s = unicode(s,charset)
doc = xml.dom.minidom.parseString(s.encode(charset))
nodiMess = doc.getElementsByTagName('message')
for m in nodiMess:
message = Messaggio()
message.From = leggiTags(m,'from')[0]
message.To = leggiTags(m,'to')[0]
message.Cc = leggiTags(m,'cc')[0]
message.Bcc = leggiTags(m,'bcc')[0]
message.Subject = leggiTags(m,'subject')[0]
message.Body = leggiTags(m,'body')[0]
message.Files = leggiTags(m,'file')
msgs.append(message)
return msgs

def controllaFile(f):
if os.path.exists(f): return f
n = os.path.join(dirConf,f)
if os.path.exists(n): return n
n = os.path.join(dirScript,f)
if os.path.exists(n): return n
s = 'Errore: non trovo il file %s' % f
stampa(s)
raise Exception(s)

def sendMailAttach(m):
Date = email.Utils.formatdate(time.time(),True)
outer = email.MIMEMultipart.MIMEMultipart()
outer['Subject'] = m.Subject.strip()
if m.To: outer['To'] = m.To.strip()
outer['From'] = m.From.strip()
outer['Date'] = Date
if m.Cc: outer['Cc'] = m.Cc.strip()
outer['X-mailer'] = 'ADS Python script'
outer.preamble = 'ADS Python script\n'
outer.epilogue = ''
msg = email.MIMEText.MIMEText(m.Body,_charset=charset)
outer.attach(msg)
for f in m.Files:
maintype = 'application'
subtype = 'octet-stream'
nomeFile = controllaFile(f)
buff = file(nomeFile).read()
msg = email.MIMEBase.MIMEBase(maintype, subtype)
msg.set_payload(buff)
email.Encoders.encode_base64(msg)
nomeFile = os.path.basename(nomeFile)
msg.add_header('Content-Disposition','attachment',filename=nomeFile)
outer.attach(msg)
s = smtplib.SMTP()
# s.set_debuglevel(1)
s.connect(smtpHost)
destinatari = m.To.split(',') + m.Cc.split(',') + m.Bcc.split(',')
for i in range(len(destinatari)):
destinatari[i] = destinatari[i].strip()
s.sendmail(m.From, destinatari, outer.as_string())
s.close()

if len(sys.argv)!=2:
print 'Numero argomenti errato.'
print 'Esempio: %s messaggi.xml' % sys.argv[0]
print
sys.exit(1)

dirScript = os.path.dirname(sys.argv[0])
nomeFileMessaggi = sys.argv[1]
if not os.path.exists(nomeFileMessaggi):
nomeFileMessaggi = os.path.join(dirScript,nomeFileMessaggi)
if not os.path.exists(nomeFileMessaggi):
print 'File di configurazione mancante: %s' % sys.argv[1]
sys.exit(2)
dirConf = os.path.dirname(nomeFileMessaggi)

charset = 'iso-8859-15'
nomeFileLog = nomeFileMessaggi + '.log'
shutil.move(nomeFileMessaggi,nomeFileMessaggi+'.begin')
nomeFileMessaggi += '.begin'

fLog = file(nomeFileLog,'at')
fLog.write('''---
--- %s
---
''' % time.asctime())

messaggi = leggiMessaggi(nomeFileMessaggi)
stampa ('Letto %d messaggi' % len(messaggi))

for m in messaggi:
# stampa(str(m))
stampa(m.fromTo())
try:
sendMailAttach(m)
stampa('messaggio spedito')
except:
stampa('Errore: non riesco a spedire il messaggio')
stampa('-')

fLog.close()
shutil.move(nomeFileMessaggi,nomeFileMessaggi+'.end')