Seite 1 von 1

email Modul: zwei Fragen

Verfasst: Samstag 15. November 2003, 11:49
von fs111
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

Umlaute

Verfasst: Mittwoch 19. November 2003, 14:04
von strogon14
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

Verfasst: Mittwoch 19. November 2003, 19:33
von 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()  

Verfasst: Mittwoch 19. November 2003, 19:37
von fs111
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

Verfasst: Mittwoch 19. November 2003, 20:44
von strogon14
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.

Verfasst: Mittwoch 19. November 2003, 21:26
von fs111
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

Verfasst: Donnerstag 20. November 2003, 01:58
von strogon14
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

Verfasst: Donnerstag 20. November 2003, 08:50
von fs111
hmmm, das hat bei mir keinerlei Effekt, das Subject sieht immer noch genauso aus.

Verfasst: Donnerstag 20. November 2003, 13:54
von 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'

Verfasst: Donnerstag 20. November 2003, 15:01
von strogon14
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.

Verfasst: Donnerstag 20. November 2003, 21:30
von fs111
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?

Verfasst: Freitag 28. November 2003, 18:38
von fs111
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

Geht erst ab Python 2.3

Verfasst: Samstag 29. November 2003, 01:14
von strogon14

Code: Alles auswählen

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