Programm aufrufen

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Nobuddy
User
Beiträge: 994
Registriert: Montag 30. Januar 2012, 16:38

Hallo zusammen,

für meinen EMail-Versand, habe ich hier http://codecocktail.wordpress.com/2008/ ... versenden/ ein schönes Programm gefunden, das ich für meine Bedürfnisse angepasst habe.

Hier mal das Programm:

Code: Alles auswählen

#!/usr/bin/python3
# -*- coding: utf-8 -*-

# Sende alle Dateien per Mail
#Example usage: python sendMail.py file1.txt, file2.txt ...

import sys, smtplib, os
from email.MIMEMultipart import MIMEMultipart
from email.MIMEBase import MIMEBase
from email.MIMEText import MIMEText
from email.Utils import formatdate
from email import Encoders

class SendMail(object):
    mailadress = 'email@mail.de'
    smtpserver = 'mail.de'
    username = 'usernamen'
    password = 'password'
    empfaenger = 'empfaenger@gmx.de'

    def send(self, files):
        # Gather information, prepare mail
        to = self.empfaenger
        From = self.mailadress
        #Subject contains preview of filenames
        if len(files) <= 3: subjAdd = ','.join(files)
        if len(files) > 3: subjAdd = ','.join(files[:3]) + '...'
        subject = 'Bestellung: ' + subjAdd
        msg = self.prepareMail(From, to, subject, files)

        #Connect to server and send mail
        server = smtplib.SMTP(self.smtpserver)
        server.ehlo() #Has something to do with sending information
        server.starttls() # Use encrypted SSL mode
        server.ehlo() # To make starttls work
        server.login(self.username, self.password)
        failed = server.sendmail(From, to, msg.as_string())
        server.quit()

    def prepareMail(self, From, to, subject, attachments):
        msg = MIMEMultipart()
        msg['From'] = From
        msg['To'] = to
        msg['Date'] = formatdate(localtime=True)
        msg['Subject'] = subject

        # The Body message is empty
        msg.attach( MIMEText("") )

        for file in attachments:
            #We could check for mimetypes here, but I'm too lazy
            part = MIMEBase('application', "octet-stream")
            part.set_payload( open(file,"rb").read() )
            Encoders.encode_base64(part)
            part.add_header('Content-Disposition', 'attachment; filename="%s"' % os.path.basename(file))
            msg.attach(part)
        #Delete created Tar
        return msg

if __name__ == '__main__':
    mail = SendMail()
    # Send all files included in command line arguments
    mail.send(sys.argv[1:])
Wenn ich dieses Programm aus dem Terminal mit

Code: Alles auswählen

python __modul_email__.py '/home/user/a/999mail.txt'
aufrufe, so wird die Mail mit Anhang verschickt. Dies funktioniert auch soweit problemlos.

Nun möchte ich aber nicht vom Terminal aus EMails mit Anhang versenden, sondern über ein eigens erstelltes Python-Programm. Leider ist es mir bis jetzt nicht gelungen, dies umzusetzen. :K

Ich würde mich über Eure Hilfe hier sehr freuen!

Grüße Nobuddy
deets

Wie bist du denn auf diesen absurden Modulnamen gekommen?

Prinzipiell ist es ganz simpel:

Code: Alles auswählen

from besserer_modulname import SendMail


def meine_funktion():
      m = SendMail()
      m.send(filename)
Nobuddy
User
Beiträge: 994
Registriert: Montag 30. Januar 2012, 16:38

Hallo deets,

mit

Code: Alles auswählen

files = '/home/whtb/a/999officeplanet.txt'

from __modul_email__ import SendMail

def meine_funktion():
      m = SendMail()
      m.send(files)
tut sich nichts und mit

Code: Alles auswählen

files = '/home/whtb/a/999officeplanet.txt'

from __modul_email__ import SendMail

def meine_funktion():
      m = SendMail()
      m.send(files)

meine_funktion()
erhalte ich die Fehlermeldung

Code: Alles auswählen

Traceback (most recent call last):
  File "a.py", line 32, in <module>
    meine_funktion()
  File "a.py", line 30, in meine_funktion
    m.send(files)
  File "/media/daten/Scripte/officeplanet/lieferantenbestellung/__modul_email__.py", line 29, in send
    msg = self.prepareMail(From, to, subject, files)
  File "/media/daten/Scripte/officeplanet/lieferantenbestellung/__modul_email__.py", line 53, in prepareMail
    part.set_payload( open(file,"rb").read() )
IOError: [Errno 21] Is a directory: '/'
Während der Befehl im Terminal

Code: Alles auswählen

python __modul_email__.py '/home/user/a/999mail.txt'
funktioniert.

Was mache ich da falsch?
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Nobuddy hat geschrieben:Was mache ich da falsch?
Schau mal ganz genau hin, was die `send` Methode erwartet und womit du sie aufrufst. Alternativ kannst du dir auch anschauen, was `attachements` in `prepareMail` sein sollte.

Code: Alles auswählen

In [1]: list('kleiner tipp')
Out[1]: ['k', 'l', 'e', 'i', 'n', 'e', 'r', ' ', 't', 'i', 'p', 'p']
Nobuddy
User
Beiträge: 994
Registriert: Montag 30. Januar 2012, 16:38

An Deinem Beispielcode, sehe ich was Du mir mitteilen willst.
Leider ist mir nicht klar, wie ich bei `attachements` in `prepareMail` ansetzen soll?
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Code: Alles auswählen

def prepareMail(self, From, to, subject, attachments):
    ...
    for file in attachments:
Da du hier _einen_ Pfad uebergibst, ist `file` das erste Mal eben das erste Zeichen des Strings: '/'.

Mit anderen Worten: Nutze eine Liste von Strings, wie der Original Code das auch tut.
Nobuddy
User
Beiträge: 994
Registriert: Montag 30. Januar 2012, 16:38

Ich habe dies so geändert:

Code: Alles auswählen

#!/usr/bin/python3
# -*- coding: utf-8 -*-

# Sende alle Dateien per Mail
#Example usage: python sendMail.py file1.txt, file2.txt ...

import sys, smtplib, os
from email.MIMEMultipart import MIMEMultipart
from email.MIMEBase import MIMEBase
from email.MIMEText import MIMEText
from email.Utils import formatdate
from email import Encoders

class SendMail(object):
    mailadress = 'email@mail.de'
    smtpserver = 'mail.de'
    username = 'usernamen'
    password = 'password'
    empfaenger = 'empfaenger@gmx.de'

    def send(self, files):
        # Gather information, prepare mail
        to = self.empfaenger
        From = self.mailadress
        attachment = files
        # Subject contains preview of filenames
        # if len(files) <= 3: subjAdd = ','.join(files)
        # if len(files) > 3: subjAdd = ','.join(files[:3]) + '...'
        # subject = 'Bestellung: ' + subjAdd
        subject = 'Bestellung'
        msg = self.prepareMail(From, to, subject, attachment)

        #Connect to server and send mail
        server = smtplib.SMTP(self.smtpserver)
        server.ehlo() #Has something to do with sending information
        server.starttls() # Use encrypted SSL mode
        server.ehlo() # To make starttls work
        server.login(self.username, self.password)
        failed = server.sendmail(From, to, msg.as_string())
        server.quit()

    def prepareMail(self, From, to, subject, attachment):
        msg = MIMEMultipart()
        msg['From'] = From
        msg['To'] = to
        msg['Date'] = formatdate(localtime=True)
        msg['Subject'] = subject

        # The Body message is empty
        msg.attach( MIMEText("") )
        print(attachment)

        #We could check for mimetypes here, but I'm too lazy
        part = MIMEBase('application', "octet-stream")
        part.set_payload( open(attachment,"rb").read() )
        Encoders.encode_base64(part)
        part.add_header('Content-Disposition', 'attachment; filename="%s"' % os.path.basename(attachment))
        msg.attach(part)
        #Delete created Tar
        return msg

if __name__ == '__main__':
    mail = SendMail()
    # Send all files included in command line arguments
    mail.send(sys.argv[1:])
und funktioniert mit dem externen Aufruf

Code: Alles auswählen

files = '/home/user/a/999officeplanet.txt'

from __modul_email__ import SendMail

def meine_funktion():
      m = SendMail()
      m.send(files)

meine_funktion()
Allerdings funktionieren mehrere Anhänge pro Mail nicht.
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Nobuddy hat geschrieben:Allerdings funktionieren mehrere Anhänge pro Mail nicht.
Noch die eigenstaendige Verwendung des Programms.

Die naheliegende Veraenderung waere

Code: Alles auswählen

files = '/home/user/a/999officeplanet.txt'
zu

Code: Alles auswählen

files = ['/home/user/a/999officeplanet.txt']
gewesen .. dann wuerde auch der Plural Sinn machen.
Nobuddy
User
Beiträge: 994
Registriert: Montag 30. Januar 2012, 16:38

cofi, Danke für Deine Tipp, jetzt funktioniert dies auch mit mehreren Anhängen.

Hier nochmal das aktuelle Konstrukt:

Code: Alles auswählen

#!/usr/bin/python3
# -*- coding: utf-8 -*-


import sys, smtplib, os
from email.MIMEMultipart import MIMEMultipart
from email.MIMEBase import MIMEBase
from email.MIMEText import MIMEText
from email.Utils import formatdate
from email import Encoders


# EMail-Versand mit Anhang
class SendMail(object):
    def send(self, mailadress, smtpserver, username, password, files, empfaenger, subject):
        # EMail vorbereiten, Informationen sammeln
        to = empfaenger
        From = mailadress
        attachment = files
        msg = self.prepareMail(From, to, subject, attachment)

        # Verbinden zu einem Server und E-Mail senden
        server = smtplib.SMTP(smtpserver)
        server.ehlo() # Hat etwas mit Senden von Informationen zu tun
        server.starttls() # SSL-Modus verwenden
        server.ehlo() # TLS starten
        server.login(username, password)
        failed = server.sendmail(From, to, msg.as_string())
        server.quit()

    def prepareMail(self, From, to, subject, attachment):
        msg = MIMEMultipart()
        msg['From'] = From
        msg['To'] = to
        msg['Date'] = formatdate(localtime=True)
        msg['Subject'] = subject

        # Der Body-Nachricht ist leer
        msg.attach( MIMEText("") )

        for file in attachment:
            # Wir könnten hier für die MIME-Typen zu überprüfen, aber ich bin zu faul
            part = MIMEBase('application', "octet-stream")
            part.set_payload( open(file,"rb").read() )
            Encoders.encode_base64(part)
            part.add_header('Content-Disposition', 'attachment; filename="%s"' % os.path.basename(file))
            msg.attach(part)
        # Löschen erstellt Tar
        return msg

if __name__ == '__main__':
    mail = SendMail()
    # Datei senden, die im Kommandozeilen-Argument enthalten ist
    mail.send(sys.argv[1:])
Grüße Nobuddy
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Und dann solltest du deinem Modul noch einen Richtigen Namen geben ;-) "__modul_email__" ist gleich doppelt falsch: Zum einen die doppelten Unterstriche und zum anderen das überflüssige "modul" im Namen.

Sebastian
Das Leben ist wie ein Tennisball.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Und zur Vorwarnung: nenne es nicht "email.py"
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Nobuddy
User
Beiträge: 994
Registriert: Montag 30. Januar 2012, 16:38

Hallo zusammen,
meine Namensgebung mit den Unterstrichen und dem Anfangswort 'modul', dient bei mir zur Sortierung in dem betreffenden Ordner, da weitere Dateien dort sich befinden, die wieder eine andere Funktion haben.
lunar

@Nobuddy: Nicht Dein Ernst, oder? Nutze Pakete und verwende vernünftige Modulnamen, um Deinen Quelltext zu strukturieren.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Und nenne nichts `files`, was in Wirklichkeit `filenames` sind ;-) Und `file` sollte man auch aus dem Grund schon nicht nehmen - selbst wenn es sich um ein file-Objekt handelte - da es ein Built-in überschreibt.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Antworten