Learn how you can use the Raspberry Pi camera module and a motion sensor to email pictures to a Gmail account.

In this article, I'll show you how to send emails containing pictures using a Raspberry Pi and a motion detector and the Python programming language. We will use a motion detection sensor and whenever motion is detected, the Raspberry Pi Camera will take a picture and send an email with the picture attached. 

This tutorial only works with Gmail accounts, so before going any further, make sure you have a Gmail account. I recommended you create a brand-new Gmail account to avoid any possible security concerns.

Adjust Default Settings in Your Gmail

By default, Google does not allow you to send emails containing Python code. To update this default setting, turn on “Allow less secure apps” in your account settings with the following steps:

  1. Login to your Gmail account by entering your login credentials.
  2. Click on your profile picture and then click on “Google account”.
  3. Under “Sign-in and Security” click “Connected apps and sites”.
  4. Click “Allow less secure apps” to turn it on.

Now you can use your Gmail login info to receive emails containing Python code!

Connect the Motion Sensor to the Raspberry Pi

Connect the VCC and GND pins of the motion sensor to the 5V and GND of the Raspberry Pi, then connect the OUT pin of the motion sensor to GPIO17. Make sure that you connected the camera to the Raspberry Pi and have turned on on the camera from the interfacing options.

Raspberry Pi motion sensor circuit diagram

The Python Code to Send Emails

Before running the code, make sure the sender and receiver email addresses and the password of the email sender are all entered.

The code will read the output from the sensor and, upon detecting motion, will capture an image and save it on the database folder.

When you run the code for the first time, it will automatically create the folder. Once the camera captures an image, the image will be attached in the email and sent to the sender’s address.

Copy and paste the below code into a new file with a filename extension .py and run the code with the command: python “filename” (e.g. python motionTest.py).

        import os
import glob
import picamera
import RPi.GPIO as GPIO
import smtplib
from time import sleep

# Importing modules for sending mail
from email.MIMEMultipart import MIMEMultipart
from email.MIMEText import MIMEText
from email.MIMEBase import MIMEBase
from email import encoders

sender = '[email protected]'
password = 'abcd1234'
receiver = '[email protected]'

DIR = './Database/'
FILE_PREFIX = 'image'
            
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BOARD)
GPIO.setup(11, GPIO.IN)  # Read output from PIR motion sensor

def send_mail():
    print 'Sending E-Mail'
    # Create the directory if not exists
    if not os.path.exists(DIR):
        os.makedirs(DIR)
    # Find the largest ID of existing images.
    # Start new images after this ID value.
    files = sorted(glob.glob(os.path.join(DIR, FILE_PREFIX + '[0-9][0-9][0-9].jpg')))
    count = 0
    
    if len(files) > 0:
        # Grab the count from the last filename.
        count = int(files[-1][-7:-4])+1

    # Save image to file
    filename = os.path.join(DIR, FILE_PREFIX + '%03d.jpg' % count)
    # Capture the face
    with picamera.PiCamera() as camera:
        pic = camera.capture(filename)
    # Sending mail
    msg = MIMEMultipart()
    msg['From'] = sender
    msg['To'] = receiver
    msg['Subject'] = 'Movement Detected'
    
    body = 'Picture is Attached.'
    msg.attach(MIMEText(body, 'plain'))
    attachment = open(filename, 'rb')
    part = MIMEBase('application', 'octet-stream')
    part.set_payload((attachment).read())
    encoders.encode_base64(part)
    part.add_header('Content-Disposition', 'attachment; filename= %s' % filename)
    msg.attach(part)
    server = smtplib.SMTP('smtp.gmail.com', 587)
    server.starttls()
    server.login(sender, password)
    text = msg.as_string()
    server.sendmail(sender, receiver, text)
    server.quit()

while True:
    i = GPIO.input(11)
    if i == 0:  # When output from motion sensor is LOW
        print "No intruders", i
        sleep(0.3)
    elif i == 1:  # When output from motion sensor is HIGH
        print "Intruder detected", i
        send_mail()
    

After executing the code, here is what happens each time the Pi detects movement:

Code Explanation

Once you've uploaded the full code, let's take a look at what each section of code is doing in your project.

First, we add the packages and modules required for this project. The GPIO package helps up to control the GPIO pins of our Raspberry Pi. The Picamera package is used for the Raspberry Pi camera, while the Smtplib package allows us to set up the Gmail server.

        import os
import glob
import picamera
import RPi.GPIO as GPIO
import smtplib
from time import sleep
    

We need the four modules below to send emails from a Raspberry Pi:

        from email.MIMEMultipart import MIMEMultipart
from email.MIMEText import MIMEText
from email.MIMEBase import MIMEBase
from email import encoders
    

We need to add the receiver's email and sender's email address and password, as shown below:

        sender = '[email protected]'
password = 'abcd1234'
receiver = '[email protected]'
    

We can then set the directory path and the file prefix for where the images will be saved:

        DIR = './Database/'
FILE_PREFIX = 'image'
    

Then, because we are going to receive the output of the sensor, we declare pin 11 as input. Any GPIO warnings should be ignored.

        GPIO.setwarnings(False)
GPIO.setmode(GPIO.BOARD)
GPIO.setup(11, GPIO.IN)  # Read output from PIR motion sensor
    

In the send_mail() function, the system will check whether the database directory has already been created or not. If it is not created, one will be created. It will then look for the ID of the images and save the new image with a new ID. Then the most recent image will be attached to the email and sent to the receiver’s address.

        def send_mail():
    print 'Sending E-Mail'
    # Create the directory if not exists
    if not os.path.exists(DIR):
        os.makedirs(DIR)
    # Find the largest ID of existing images.
    # Start new images after this ID value.
    files = sorted(glob.glob(os.path.join(DIR, FILE_PREFIX + '[0-9][0-9][0-9].jpg')))
    count = 0
    
    if len(files) > 0:
        # Grab the count from the last filename.
        count = int(files[-1][-7:-4])+1

    # Save image to file
    filename = os.path.join(DIR, FILE_PREFIX + '%03d.jpg' % count)
    # Capture the face
    with picamera.PiCamera() as camera:
        pic = camera.capture(filename)
    # Sending mail
    msg = MIMEMultipart()
    msg['From'] = sender
    msg['To'] = receiver
    msg['Subject'] = 'Movement Detected'
    
    body = 'Picture is Attached.'
    msg.attach(MIMEText(body, 'plain'))
    attachment = open(filename, 'rb')
    part = MIMEBase('application', 'octet-stream')
    part.set_payload((attachment).read())
    encoders.encode_base64(part)
    part.add_header('Content-Disposition', 'attachment; filename= %s' % filename)
    msg.attach(part)
    server = smtplib.SMTP('smtp.gmail.com', 587)
    server.starttls()
    server.login(sender, password)
    text = msg.as_string()
    server.sendmail(sender, receiver, text)
    server.quit()

In the while loop, it will read the input from pin 11 and, if the input is equal to 1, the send_mail() function will be called to send an email.
while True:
    i = GPIO.input(11)
    if i == 0:  # When output from motion sensor is LOW
        print "No intruders", i
        sleep(0.3)
    elif i == 1:  # When output from motion sensor is HIGH
        print "Intruder detected", i
        send_mail()
    

Cover image courtesy of the Raspberry Pi Foundation.

Related Articles

Muhammad Aqib