email Modul: zwei Fragen

Sockets, TCP/IP, (XML-)RPC und ähnliche Themen gehören in dieses Forum
Antworten
fs111
User
Beiträge: 170
Registriert: Samstag 15. November 2003, 11:42
Kontaktdaten:

Hallo Forengemeinde, dies ist mein erster Post, und ich hoffe es werden noch mehr werden.

Ich bin seit einem Praktikum bei einer Firma ein echter Python-Fan und bin begeistert von der Einfachheit und Mächtigkeit dieser Sprache. Im Moment schreibe ich gerade ein kleines Skript, welches Emails automatisch in einem Forum postet, also den Text und das Subject extrahiert, und per http-post versendet. Dabei treten zwei Probleme auf.

1. Bekomme ich es nicht hin das "Subject" der Email in den richtigen Zeichensatz zu formatieren, so dass auch Umlaute etc. dargestellt werden können. Ich habe mich schon in der Doku umgesehen, aber so ganz das richtige, scheine ich nicht zu finden. Wie kann man da vorgehen?

2. Schlägt mein Skript momenta fehl, wenn die Email aus mehreren Teilen besteht, deshalb suche ich nach einer eleganten Methode die Anhänge abzuschneiden. Leider stehe ich auch hierbei etwas auf dem Schlauch.

Über Anregungen und Tipps würde ich mich freuen.

Danke und Grüße

fs111
Benutzeravatar
strogon14
User
Beiträge: 58
Registriert: Sonntag 23. Februar 2003, 19:34
Wohnort: Köln
Kontaktdaten:

Hallo fs111,

das mit den Umlauten kann mehrere Ursachen haben. Da Du keinen Beispielcode von Dir postest, kann ich nur Vermutungen anstellen.

Hast Du:

- die Formularwerte im HTTP-POST mit urllib.quote_plus() behandelt?
- den Subject-Header der Mail mit der email.Header()-Klasse erzeugt?

siehe dazu Kapitel 12.2.5 "Internationalized headers" in der Standard Library Reference


Was das Abschneiden der Attachments angeht, auch hier wäre ein Code-Schnipsel hilfreich, um zu zeigen, was Du versuchst.

Hast Du Kapitel 12.2.13 "Examples" gelesen, insbesondere das letze Beispiel?

Hier ein Vorschlag für ein grundsätzliche Struktur:

Code: Alles auswählen

import email

e = email.message_from_file(file('message.eml'))
for part in e.walk():
    # Picke dir hier den Teil der Email raus, den du brauchst
    if part.get_content_type() == 'text/plain':
        process_email(part.get_payload())
Die Funktion process_email(text) wird dann mit dem Text des Body der Mail aufgerufen.

BTW: Allle Beispiel und Dokumentationsverweise beziehen sich auf Python 2.3

HTH, Chris
Gast

Danke erstmal für Deine Antwort. ich poste hier mal ein wenig Beispielcode, zmindest die Klasse, die das wichtigste erledig:

Code: Alles auswählen

class emailposter:
        FORUM_ID = 20
        CAT_ID = 4



        def __init__(self, message ):
            self.msg = message
            self.subject=self.createSubject()
#            print self.subject
            self.message=self.createMessage()
#            print self.message
        def postMessage(self):
                params = urllib.urlencode({'ARCHIVE': '', 'Method_Type': 'Topic',
                        'Type': '', 'REPLY_ID': '', 'TOPIC_ID': '',
                        'FORUM_ID': self.FORUM_ID, 'CAT_ID': self.CAT_ID, 'Refer': 'http://www.imit.uni-hildesheim.de/fachschaft/forum2/forum.asp?FORUM_ID=38',
                        'cookies': 'yes', 'UserName':'nutzer',
                        'Password':'geheim',
                        'Subject':self.subject, 'Message': self.message})

                headers = {"Content-type": "application/x-www-form-urlencoded",
                    "Accept": "text/plain"}

                conn = httplib.HTTPConnection("www.imit.uni-hildesheim.de:80")
                print 'connecting server...'
                conn.request("POST", "/fachschaft/forum2/post_info.asp", params, headers)
                response = conn.getresponse()
                code = response.status, response.reason
#                print response.read()
                conn.close()
                return code
        def createSubject(self):
            subject = self.msg.get('Subject')
            subject = email.Utils.encode_rfc2231(subject)
            if len(subject)<49:
                return subject
            else: return subject[0:49]
        def createMessage(self):
            mymsg = self.msg
            for header in mymsg.keys():
                mymsg.__delitem__(header)
            return mymsg.as_string()  
fs111
User
Beiträge: 170
Registriert: Samstag 15. November 2003, 11:42
Kontaktdaten:

Mist, verklickt, und nicht eingeloggt. Auf jeden FAlls seiht man jetzt ja ungefähr was da passiert. Das eigentliche posten geht dann so vor sich, dass mein evolution(email-Programm unter Linux) die erhaltene Email über einen Filter in einer Pipe an mein Skript weitergericht wird. Dieses liest dei email ein, erzeugt ein nueses emailposter Objekt (hoffe die Begrifflichkeit stimmt unter Python) und schickt dei Nachricht dann los.

Danke für die Hilfe.

fs111
Benutzeravatar
strogon14
User
Beiträge: 58
Registriert: Sonntag 23. Februar 2003, 19:34
Wohnort: Köln
Kontaktdaten:

Versuche mal das:

Code: Alles auswählen

import urllib

class emailposter:
    FORUM_ID = 20
    CAT_ID = 4

    def __init__(self, message):
        self.msg = message
        # print self.getSubject()
        # print self.geteMessage()

    def postMessage(self):
        params = urllib.urlencode({
          'ARCHIVE': '',
          'Method_Type': 'Topic',
          'Type': '', 'REPLY_ID': '', 'TOPIC_ID': '',
          'FORUM_ID': self.FORUM_ID, 'CAT_ID': self.CAT_ID,
          'Refer': 'http://www.imit.uni-hildesheim.de/fachschaft/forum2/forum.asp?FORUM_ID=38',
          'cookies': 'yes', 'UserName':'nutzer',
          'Password': 'geheim',
          'Subject': self.getSubject(),
          'Message': self.getMessage()})

        headers = {"Content-type": "application/x-www-form-urlencoded",
            "Accept": "text/plain"}

        conn = httplib.HTTPConnection("www.imit.uni-hildesheim.de:80")
        print 'connecting server...'
        conn.request("POST", "/fachschaft/forum2/post_info.asp",
          params, headers)
        response = conn.getresponse()
        code = response.status, response.reason
        # print response.read()
        conn.close()
        return code

    def getSubject(self):
        subject = self.msg.get('Subject')
        if len(subject)<49:
            return subject
        else: return subject[0:49]

    def getMessage(self):
        if self.msg.is_multipart():
            for part in self.msg.walk():
                # Picke dir hier den Teil der Email raus, den du brauchst
                if part.get_content_type() == 'text/plain':
                    return part.get_payload()
        else:
            return self.msg.get_payload()

if __name__ == '__main__':
    import email, sys
    msg_string = sys.stdin.read()
    msg = email.message_from_string(msg_string)
    e = emailposter(msg)
    e.postMessage()
Die Decodierung des Subjects wird von der Message-Klasse übernommen,
die Codierung dann von urllib.urlencode. Wenn es dann mit den Umlauten nicht klappt, solltest Du vielleicht mal eine Beispiel-Mail (mit allen Header) posten.
fs111
User
Beiträge: 170
Registriert: Samstag 15. November 2003, 11:42
Kontaktdaten:

Ja Danke, das mit den Anhängen geht jetzt, nur die Umlaute sind immer noch kaputt.

Aus Existenzgründung wird dann "=?ISO-8859-1?Q?Existenzgr=FCndung?=" was sehr unschön ist. Di Subject Zeile, in dieser Email sieht so aus:
Subject: =?ISO-8859-1?Q?Existenzgr=FCndung?=
Ich will jetzt mal aus Datenschutzrechrlichen Gründen nicht alles posten, hoffe es geht auch so

fs111
Benutzeravatar
strogon14
User
Beiträge: 58
Registriert: Sonntag 23. Februar 2003, 19:34
Wohnort: Köln
Kontaktdaten:

fs111 hat geschrieben:Subject: =?ISO-8859-1?Q?Existenzgr=FCndung?=
Das ist die RFC 2047 Kodierung. Du musst die getSubject-Methode noch so erweitern, dass Sie Unicode zurückgibt:

Code: Alles auswählen

def getSubject(self):
    subject = unicode(self.msg.get('Subject'))
    ...
Chris
fs111
User
Beiträge: 170
Registriert: Samstag 15. November 2003, 11:42
Kontaktdaten:

hmmm, das hat bei mir keinerlei Effekt, das Subject sieht immer noch genauso aus.
Gast

Code: Alles auswählen

>>> from email.Header import Header
>>> h = Header('Existenzgründung', 'iso-8859-1')
>>> h
<email.Header.Header instance at 0x00826358>

>>> str(h)
'=?iso-8859-1?q?Existenzgr=81ndung?='

>>> from email.Header import decode_header
>>> decode_header(h)
[('Existenzgr\x81ndung', 'iso-8859-1')]

>>> unicode(h)
u'Existenzgr\x81ndung'
Benutzeravatar
strogon14
User
Beiträge: 58
Registriert: Sonntag 23. Februar 2003, 19:34
Wohnort: Köln
Kontaktdaten:

Ups, das mit 'iso-8859-1' im vorherigen Bespiel aus dem interaktiven Modus ist natürlich Quatsch, da ich das unter Windows gemacht habe. Das 'ü' ist natürlich im Windows-Zeichensatz kodiert (wie auch immer der unter Python heißt), unter ISO-8859-1 wäre es =FC.

Das ändert aber nichts am grundsätzlichen Vorgehen.
fs111
User
Beiträge: 170
Registriert: Samstag 15. November 2003, 11:42
Kontaktdaten:

irgendwie hat das keinen Effekt:
Python 2.2.3 (#1, Oct 15 2003, 23:33:35)
[GCC 3.3.1 20030930 (Red Hat Linux 3.3.1-6)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from email.Header import Header, decode_header
>>> h = Header('http://www.w3schools.com/css/default.asp','iso-8859-1')
[1]+ Stopped python
[FS111@Hermes FS111]$ fg
python
>>> h = Header('=?ISO-8859-1?Q?Existenzgr=FCndung?=','iso-8859-1')
>>> h
<email.Header.Header instance at 0x8b5a334>
>>> str(h)
'=?iso-8859-1?q?=3D=3FISO-8859-1=3FQ=3FExistenzgr=3DFCndung=3F=3D?='
>>> decode_header(h)
[('=?ISO-8859-1?Q?Existenzgr=FCndung?=', 'iso-8859-1')]
>>> unicode(h)
u'=?ISO-8859-1?Q?Existenzgr=FCndung?='
noch eine Idee?
fs111
User
Beiträge: 170
Registriert: Samstag 15. November 2003, 11:42
Kontaktdaten:

Ok, ich habe es jetzt hinbekommen, wenn auch etwas und die Ecke, aber es funktioniert mit beliebig vielen Umlauten/Sonderzeichen im Subject.

Die Funktion sieht jetzt sieht jetzt folgendermaßen aus:

Code: Alles auswählen

def createSubject(self):
            subject = self.msg.get('Subject')
            array = subject.split()
            mysubject = ''
            for part in array:
                    if part.find('?=') != -1:
                        i = part.find('?Q?')
                        part = part[i+3:-2]
                        part = part.replace('=', '%')
                    part = urllib.unquote(part)
                    mysubject = mysubject+part+' '
            mysubject = mysubject.replace('_', '')        
            if len(mysubject)<50:
               return mysubject
            else: return mysubject[0:49]
Vielleicht hilft es ja dem einen oder anderen.

Grüße

fs111
Benutzeravatar
strogon14
User
Beiträge: 58
Registriert: Sonntag 23. Februar 2003, 19:34
Wohnort: Köln
Kontaktdaten:

Code: Alles auswählen

unicode(h)
funktioniert anscheinend erst ab Python 2.3 richtig :-(
Antworten