web mail interface using pi and flask


raspberry pi

have you ever used gmail or hotmail on the web? it seems so natural that we take it for granted. in this post we’ll see how to build a basic web mail client to send mail … using flask and pi as server. this is content =======

flask intro : folder structure

flask intro : requests

flask : basic app

flask : post flask intro : folder structure ==============================

flask is a python web framework, it is recommended to learn it before django. a typical flask project structure is as follows:

let us say we name our project sendmail, the project structure is

sendmail [folder]
|_ _ app.py
|_ _ templates [folder]
|     |_ _ file.html
|_ _ static [folder]
      |_ _ style.css

to run a flask app you don’t need the templates and static folder but they are here for good reasons the templates folder


let us say you have a website and for each page there are some elements recurring like the header and footer. having a template allows you to specify only the changing data templating engine


flask uses the jinja templating engine for rendering variables etc

{{name}} will display the variable name on rendering. more on that later static folder


static means it won’t change, load your non-changing assets in there flask intro : requests ======================

for a webserver, whatever you type in the address bar after specifying the correct ip is a request

http://www.domain.com/water.html

requests the file water.html

in flask however (and python), you need not request for only files, you can pretty much mould the request pattern

http://www.domain.com/mult/5/by/2

http://www.domain.com/show/user54/sea

flask : basic app

a basic app in flask is as follows :

from flask import Flask

app = Flask(__name__)
@app.route('/')
def basic():
    return 'welcome to my site'
if __name__ == '__main__': # if file run
    app.run(debug=True, host='0.0.0.0')

explanations

@app.route('/')

means the first slash after the domain name if requested

you define the action in the subsequent function, which can be named as you want

let us say the domain is www.d.com, we are specifying what to do when www.d.com/ is requested

return 'welcome to my site'

displays a single string

app.run(debug=True, host='0.0.0.0')

host=‘0.0.0.0’ runs the app on 192.168. … flask : basic app : return page ===============================

from flask import Flask, render_tempplate

app = Flask(__name__)
@app.route('/')
def basic():
    return render_template('index.html')
if __name__ == '__main__':
    app.run(debug=True, host='0.0.0.0')

here

return render_template('index.html')

returns the file index.html in the templates folder flask : post ============

there are two request methods viz post and get, post is more secure than get

here is a post demo :

our html

<form method="POST">
<input type="text" name="xyz">
<br>
<input type="submit" value="Send">
</form>

our post handling method:

@app.route('/', methods=['GET', 'POST'])
def index():
    if request.method == 'POST': #this block is only entered when the form is submitted
        data = request.form['xyz']
        return 'data entered :{}'.format(data)

    return render_template('index.html')

our app

here is the code for our index.html file in our templates folder :

<!DOCTYPE html>
<html>
<head>
<title></title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<form method="POST">
to:<br>
<input type="text" name="to">
<br>
subject:<br>
<input type="text" name="subject">
<br>
body:<br>
<textarea rows="4" cols="50" type="text" name="body">

</textarea>
<br><br>
<input type="submit" value="Send">
</form> 
</body>
</html>

our app.py code :

from flask import Flask, render_template, request

# send mail function
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.header import Header

def send_mail(to_, subject_, body_):
    fromaddr='[address]'
    toaddr=to_
    thesub=subject_
    thebody=body_
    thepassword='[pass]'
    domsmtp='smtp.gmail.com'
    smtpport= 587 #needs integer not string


    msg = MIMEMultipart('alt text here')
    msg.set_charset('utf8')


    msg['From'] = fromaddr
    msg['To'] = toaddr
    msg['Subject'] = Header(thesub,'utf8')
    _attach = MIMEText(thebody.encode('utf8'),'html','UTF-8')
    msg.attach(_attach)

    server = smtplib.SMTP(domsmtp, smtpport)
    server.starttls()
    server.login(fromaddr, thepassword)
    text = msg.as_string()
    server.sendmail(fromaddr, toaddr, text)

    server.quit()
    print('mail sent')

app = Flask(__name__)

@app.route('/', methods=['GET', 'POST'])
def index():
    if request.method == 'POST': #this block is only entered when the form is submitted
        to = request.form['to']
        subject = request.form['subject']
        body = request.form['body']
        send_mail(to, subject, body)
        return 'mail sent to {}'.format(to)

    return render_template('index.html')

if __name__ == '__main__':
    app.run(debug=True, host='0.0.0.0')

just replace [address] and [pass] by your actual data now run app.py, and see the output

you can grab another device on the network, go to 192.168. … depending, and … you can send a mail from another device, from a web interface