Seite 1 von 1

[bottle] Formular (mailform)?

Verfasst: Dienstag 15. Mai 2012, 14:10
von lackschuh
Hallo

Brauch mal einen Gedankenanstoss für ein einfaches Kontaktformular, welches die Eingaben an eine bestimmte Mailadresse versenden soll. Ich möchte das ganze aber nicht über cgi-bin bzw Perl laufen lassen.

Mittels get-Methode kann ich mir zumindest schon mal die Eingabe auf der Konsole anzeigen lassen:

Code: Alles auswählen

get('/kontakt')
def kontakt():
    if request.GET.get('save','').strip():
        name = request.GET.get('name', '').strip()
        email = request.GET.get('email', '').strip()
        text = request.GET.get('text', '').strip()
    else:
        pass
    print 'Neuer Kontakt: Email', email, name, text
Bin halt noch ein blutiger Anfänger :wink:

Re: [bottle] Formular (mailform)?

Verfasst: Dienstag 15. Mai 2012, 14:54
von deets
dann google doch mal "python send mail" und schau, was bei rumkommt.

Re: [bottle] Formular (mailform)?

Verfasst: Dienstag 15. Mai 2012, 15:08
von jens
Wichtig ist, das alle reinkommenden Daten validiert werden! Nicht einfach nehmen und an sendmail übergeben, ansonsten hat man schnell eine SPAM Schleuder aufgebaut ;)

Mit Django hat man alles dabei:
* die Daten validieren mit den 'forms': https://docs.djangoproject.com/en/1.4/topics/forms/
* mails verschicken: https://docs.djangoproject.com/en/1.4/topics/email/

Sicherlich kann man auch auf andere Libs zurück greifen...

Re: [bottle] Formular (mailform)?

Verfasst: Dienstag 15. Mai 2012, 15:32
von lackschuh
Hallo

So was in der Art bräuchte ich:

Code: Alles auswählen

from django.core.mail import send_mail, BadHeaderError

def send_email(request):
    subject = request.POST.get('subject', '')
    message = request.POST.get('message', '')
    from_email = request.POST.get('from_email', '')
    if subject and message and from_email:
        try:
            send_mail(subject, message, from_email, ['admin@example.com'])
        except BadHeaderError:
            return HttpResponse('Invalid header found.')
        return HttpResponseRedirect('/contact/thanks/')
    else:
        # In reality we'd use a form class
        # to get proper validation errors.
        return HttpResponse('Make sure all fields are entered and valid.')
Aber das wird mir wohl bottle nicht bieten (diese Module). Werde mich mal in das Thema einlesen.

Re: [bottle] Formular (mailform)?

Verfasst: Dienstag 15. Mai 2012, 18:25
von BlackJack
@lackschuh: Für die Forms kann man zum Beispiel `wtforms` verwenden. Für's versenden gäbe es `turbomail`.

Re: [bottle] Formular (mailform)?

Verfasst: Mittwoch 16. Mai 2012, 07:36
von jens

Re: [bottle] Formular (mailform)?

Verfasst: Mittwoch 16. Mai 2012, 07:49
von lackschuh
jens hat geschrieben:@lackschuh: Bitte mal das lesen: http://wiki.python.de/Web-Frameworks#We ... w-r_wen.3F
Moin,

das habe ich mir als erstes durchgelesen und mich dann für bottle entschieden. Die Homepage ist soweit ja schon fertig (ca. 15 Seiten mit Sub-Sites). Nur fehlt mir eben noch die Idee, wie ich ein Kontaktformular mit Spamschutz (zB Berechnen Sie 3+5...) erstelle, welches mir die Eingabe an eine bestimmte Mailadresse schickt.

Re: [bottle] Formular (mailform)?

Verfasst: Mittwoch 16. Mai 2012, 09:07
von deets
BlackJack sagte es ja schon - benutz turbomail (haette ich selbst auch drauf kommen muessen, hab's schliesslich hier schon oefter erwaehnt...)

Re: [bottle] Formular (mailform)?

Verfasst: Dienstag 5. Juni 2012, 12:27
von lackschuh
Hallo

Ich hab mich ein wenig mit den obgenannten Bibliotheken beschäftigt. Nun bin ich aber an dem Pukt angekommen, wo ich wieder ein wenig Hilfe brauche (weil die Dokumentationen sehr spärlich sind).

Mit dem Marrow Mailer (ehemals Turbomail) kann ich schon einmal Mails verschicken:

maildelivery.py

Code: Alles auswählen

#!/usr/bin/python
# -*- coding: utf -8 -*-
from marrow.mailer import Mailer, Message
import forms


mailer = Mailer(dict(
        transport = dict(
                use = 'smtp',
                host = 'mail.meineDomain.com',
                port = '587',
                username = 'xxxx',
                password = 'xxxx',
                tls = 'required',
                debug = True),
        manager = dict()))
mailer.start()

message = Message(author="", to=u"Mich <info@meineDomain.com>")
message.subject = ""
message.plain = u""
filname = ""
message.attach(filname) 

mailer.send(message)
mailer.stop()
Des Weiteren habe ich mittels WTForms meine Eingabefelder fürs Formular deffiniert
forms.py:

Code: Alles auswählen

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

from wtforms import Form, FileField, TextField, TextAreaField, SubmitField, validators

class AttachmentForm(Form):
    name = TextField(u'Name',
            [validators.Required(
             message=u'Bitte geben Sie einen Namen ein!'),
             validators.Length(max=50,
             message=u'Der Text darf nicht länger als 50 Zeichen\
             sein.')])   

    email = TextField(u'E-Mail',
            [validators.Email(
             message=u'Keine oder falsche E-Mailadresse eingegeben!'),
             validators.Length(max=50,
             message=u'Der Text darf nicht länger als 50 Zeichen\
             sein.')])
    
    betreff = TextField(u'Betreff',
            [validators.Required(
             message=u'Bitte geben Sie einen Betreff an!'),
             validators.Length(max=50,
             message=u'Der Text darf nicht länger als 50 Zeichen\
             sein.')])

    kommentar = TextAreaField(u'Kommentar',
            [validators.Required(
             message=u'Bitte geben Sie Ihre Nachricht ein'),
             validators.Length(max=50,
             message=u'Der Text darf nicht länger als 50 Zeichen\
             sein.')])
         
    attachment = FileField(u'Datei',
        [validators.regexp(r'.+\.(jpg|pdf|png|docx|doc|txt)$',
        flags=2,
        message=u'Es sind nur Dateien mit der Endung jpg, pdf,\
        png, docx, doc und txt erlaubt!')])
    
    send = SubmitField(u'Senden')
Das formular.tpl:

Code: Alles auswählen

<html>
<head>
<title>Kontaktformular</title>
</head>
<body>
<h2>Datei-Upload</h2>
%if errors:
<p class="fehler">Die Eingabe enthält <a href="#fehler">Fehler</a></p>
%end
<p></p>
%if errors:
<p style="color: #ff0000;">Fehler:</p>
%for k,v in errors.iteritems():
<p><b>{{!form[k].label}}</b>: {{!v[0]}}</p>
%end
%end
<form action="/kontakt" method="post" enctype="multipart/form-data">
<ul>
<li>{{!form.name.label()}}<br/> {{!form.name(size=75)}}</li>
<br/>
<li>{{!form.email.label()}}<br/> {{!form.email(size=75)}}</li>
<br/>
<li>{{!form.betreff.label()}}<br/> {{!form.betreff(size=75)}}</li>
<br/>
<li>{{!form.kommentar.label()}}<br/> {{!form.kommentar(size=75)}}</li>
<br/>
<li>{{!form.attachment.label()}}<br/> {{!form.attachment(size=75)}}</li>
</ul>
<p>{{!form.send()}}</p>
</form>
</body>
</html>
Und dann noch die Bottle App
home.py

Code: Alles auswählen

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

import os
from bottle import route, template, request, run, debug, error
import forms
import maildelivery

# Linux Pfad
# static_folder = '/var/www/meineDomain.com/htdocs/attachment'
PATH = 'C:\\Projekte\\Upload\\attachment'

@route('/kontakt')
@route('/kontakt', method='POST')
def kontakt():
    req = request.forms
    data = request.files.get('attachment')
    form = forms.AttachmentForm(req)
    try:
        form.attachment.data = data.filename
    except:
        form.attachment.data = None
    if not req or not form.validate():
        return template('formular.tpl',
            form=form,errors=form.errors)
    else:
        raw = data.file.read()
        with open(os.path.join(PATH, data.filename),'wb') as f:
            f.write(raw)
        return u'Datei {0} erfolgreich verschickt'.format(
            data.filename, form.name.data)




debug(True)
run(reloader=True, host='10.0.2.110', port=8081)
Alle Skripte funktionieren so weit. Meine Frage ist aber nun, wie ich diese miteinander verbinden kann? Das maildelivery.py Skript soll die ausgefüllten Felder des formular.tpl/forms.py an meine E-Mail Adresse senden. An diesem Punkt bin ich momentan mit meinem Latein wieder am Ende.

mfg

Re: [bottle] Formular (mailform)?

Verfasst: Mittwoch 6. Juni 2012, 14:32
von noisefloor
Hallo,

die Textdaten aus dem Formular musst du halt als Inhalt in deine E-Mail schreiben und die Datei als Anhang anhängen. Wie das geht findest du ziemlich sicher in der Doku von Marrow Mailer.

Gruß, noisefloor

Re: [bottle] Formular (mailform)?

Verfasst: Montag 11. Juni 2012, 10:29
von lackschuh
noisefloor hat geschrieben:Hallo,

die Textdaten aus dem Formular musst du halt als Inhalt in deine E-Mail schreiben und die Datei als Anhang anhängen. Wie das geht findest du ziemlich sicher in der Doku von Marrow Mailer.

Gruß, noisefloor
Hallo

Also in der Doku - wenn man das überhaupt als Doku bezeichnen kann - hab ich nichts gefunden. Aber auch egal. Ich bin nun ein ganzes Stück weiter gekommen.

Ein paar Fragen hätte ich dennoch:

1: habe ich noch ein ascii Problem mit Umlauten etc:

Code: Alles auswählen

Error 500: Internal Server Error

Sorry, the requested URL 'http://localhost:8081/kontakt' caused an error:

Internal Server Error

Exception:

UnicodeDecodeError('ascii', '\xc3\xbc', 0, 1, 'ordinal not in range(128)')

Traceback:

Traceback (most recent call last):
  File "C:\Projekte\Kontaktformular\bottle.py", line 651, in _handle
    return callback(**args)
  File "C:\Projekte\Kontaktformular\bottle.py", line 1145, in wrapper
    rv = callback(*a, **ka)
  File "home.py", line 31, in kontakt
    form=form,errors=form.errors)
  File "C:\Projekte\Kontaktformular\bottle.py", line 2419, in template
    return TEMPLATES[tpl].render(kwargs)
  File "C:\Projekte\Kontaktformular\bottle.py", line 2393, in render
    self.execute(stdout, kwargs)
  File "C:\Projekte\Kontaktformular\bottle.py", line 2380, in execute
    eval(self.co, env)
  File "kontakt2.tpl", line 37, in <module>
    {{!form.kommentar(class_="imp")}} <br /></td>
  File "C:\Python27\lib\site-packages\wtforms\fields\core.py", line 136, in __call__
    return self.widget(self, **kwargs)
  File "C:\Python27\lib\site-packages\wtforms\widgets\core.py", line 221, in __call__
    return HTMLString(u'<textarea %s>%s</textarea>' % (html_params(name=field.name, **kwargs), escape(unicode(field._value()))))
  File "C:\Python27\lib\site-packages\wtforms\fields\core.py", line 477, in _value
    return unicode(self.data) if self.data is not None else u''
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 0: ordinal not in range(128)
Wo könnte der Fehler hier liegen?

Und die andere Frage ist, ob der Aufbau des Skrips überhaupt so richtig ist. Hier mal die Bottle-App:

Code: Alles auswählen

@route('/kontakt')
@route('/kontakt', method='POST')
def kontakt():

    req = request.forms
    form = forms.KontaktFormular(req)
    
    
    
    if not req or not form.validate():
        return template('auswahl2.tpl',
            form=form,errors=form.errors)
    else:
        maildelivery.mailer.start()
        message = Message(author="From: '{0}' <{1}>" .format(form.name.data, form.email.data), to=u"Mein Name<meine@domain.com>")
        message.subject = u'{0}'.format(form.betreff.data)
        message.plain = u'{0}'.format(form.kommentar.data)
        
    
        maildelivery.mailer.send(message)
        maildelivery.mailer.stop()
        return u'Hallo {0}, die Nachricht wurde erfolgreich übermittelt.'.format(form.name.data)
Und das marrow.mailer Skript namens maildelivery.py

Code: Alles auswählen

#!/usr/bin/python
# -*- coding: utf -8 -*-
from marrow.mailer import Mailer, Message
import forms


mailer = Mailer(dict(
        transport = dict(
                use = 'smtp',
                host = 'mail.meineDomain.com',
                port = '587',
                username = 'xxxxxx',
                password = 'xxxxxx',
               # tls = 'required',
                debug = True),
        manager = dict()))
Das Versenden der Daten geht relativ Lange im Vergleich zu meinem Contao CMS. Oder liegt es nur daran, dass ich Bottle z.Z noch lokal laufen habe und noch nicht auf dem Server?

EDIT:

Hier noch ein Auszug aus dem Template:

Code: Alles auswählen

<tr>
          <td><strong>{{!form.name.label()}}</strong><br />
            {{!form.name(class_="imp")}} <br /></td>
          
          <td><strong>{{!form.email.label()}}</strong><br />
            {{!form.email(class_="imp")}}</td>
        </tr>
mfg

Re: [bottle] Formular (mailform)?

Verfasst: Montag 11. Juni 2012, 11:29
von deets
Ich wuerde mal sagen du benutzt Marrow Mailer falsch - das permanente gestarte und gestoppe ist so bestimmt nicht gedacht, und verzoegert im Zweifel sehr. Starte einmal bei Start der Applikation, und das mit dem Stop... ka ob bottle einen Mechanismus kennt das herunterfahren der Anwendung mit einem Event oder Callback oder so zu versehen.

Den UnicodeDecodeError finde ich komisch, haette gedacht, bottle liefert nur unicode und Marrow encodiert das proper. Aber wahrscheinlich benutzt du diese forms falsch.