-3

I need to figure out how to make a script that scans for new files in a directory, and when there is a new one, sends the file via email.

Someone keeps stealing bikes in my apartment building! First it was my fault (I for got to lock it), now the crook upgraded by cutting chains. I had it after the crook stole my second bike by cutting 1/2 inch airplane wire.

Anyway, using a raspberry pi as a motion activated security camera, I want it to send me a video file as soon as the video program finishes recording it. This is incase they steal the pi.

I am looking at these examples, but I can't figure how to make the script run continuously (every minute) or how to make it scan a folder for a new file.

How do I send attachments using SMTP?

OK I got it down to scanning and then trying to email. It fails when trying to attach the video file. Can you help? Here is the revised code:

The failure is:
msg = MIMEMultipart() TypeError: 'LazyImporter' object is not callable, line 38

import time, glob
import smtplib
import email.MIMEMultipart  
from email.MIMEBase import MIMEBase
from email.MIMEText import MIMEText
from email.Utils import COMMASPACE, formatdate
from email import Encoders, MIMEMultipart
import os

#Settings:
fromemail= "Jose Garcia <somerandomemail@gmail.com>"
loginname="somerandomemail@gmail.com"
loginpassword="somerandomepassword"
toemail= "Jose Garcia <somerandomemail@gmail.com>"
SMTPserver='smtp.gmail.com'
SMTPort=587
fileslocation="/Users/someone/Desktop/Test/*.mp4"
subject="Security Notification"

def mainloop():   
        files=glob.glob(fileslocation) #Put whatever path and file format you're using in there.
        while 1:
            new_files=glob.glob(fileslocation)
            if len(new_files)>len(files):
                for x in new_files:
                    if x in files:
                        print("New file detected "+x)
                        print("about to call send email")
                        sendMail(loginname, loginpassword, toemail, fromemail, subject, gethtmlcode(), x, SMTPserver, SMTPort)

            files=new_files
            time.sleep(1)

def sendMail(login, password, to, frome, subject, text, filee, server, port):
#    assert type(to)==list
#    assert type(filee)==list

    msg = MIMEMultipart()
    msg['From'] = frome
    msg['To'] = COMMASPACE.join(to)
    msg['Date'] = formatdate(localtime=True)
    msg['Subject'] = subject

    msg.attach( MIMEText(text) )

#    #for filee in files:
    part = MIMEBase('application', "octet-stream")
    part.set_payload( open(filee,"rb").read() )
    Encoders.encode_base64(part)
    part.add_header('Content-Disposition', 'attachment; filename="%s"'
                       % os.path.basename(filee))
    msg.attach(part)

    smtp = smtplib.SMTP(SMTPserver, SMTPort)
    smtp.sendmail(frome, to, msg.as_string() )
    server.set_debuglevel(1) 
    server.starttls() 
    server.ehlo() 
    server.login(login, password) 
    server.sendmail(frome, to, msg) 
    server.quit()

def gethtmlcode():
    print("about to assemble html")
    html = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" '
    html +='"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml">'
    html +='<body style="font-size:12px;font-family:Verdana"><p>A new video file has been recorded </p>'
    html += "</body></html>"
    return(html)

#Execute loop
mainloop()
Community
  • 1
  • 1
Jose Garcia
  • 25
  • 1
  • 6
  • Better, but what does “It fails” mean? It sends a video of [Rick Astley](http://en.wikipedia.org/wiki/Rickrolling)? It throws an error? What's the error message? – Dour High Arch Sep 04 '14 at 17:00
  • I revised it again, less clutter. The code still fails with "The failure is: msg = MIMEMultipart() TypeError: 'LazyImporter' object is not callable, line 38" – Jose Garcia Sep 04 '14 at 17:44
  • Please show us what `LazyImporter` and “line 38” are. – Dour High Arch Sep 04 '14 at 20:53

4 Answers4

1

I finally got it working. I had to use python 2.5 to get rid of the LazyImporter error. Every time a new file is added to the security folder, it gets emailed to me. Logging is broken.

import time, glob
import smtplib
from email.MIMEMultipart import MIMEMultipart 
from email.MIMEMultipart import MIMEBase 
from email.MIMEText import MIMEText
from email.Utils import COMMASPACE, formatdate
import datetime 
from email import Encoders
import os
import sys


#Settings:
fromemail= 'RaspberryPI Security Camera <someone>'
loginname='someone@gmail.com'
loginpassword='something'
toemail= 'Jose Garcia < someone@gmail.com>'
SMTPserver='smtp.gmail.com'
SMTPort=587
fileslocation='/Users/someone/Desktop/Test/*.*'
subject="Security Notification"
log='logfile.txt'

def mainloop():   
        files=glob.glob(fileslocation) #Put whatever path and file format you're using in there.
        while 1:
            f = open(log, 'w')
            sys.stdout = Tee(sys.stdout, f)
            new_files=glob.glob(fileslocation)
            if len(new_files)>len(files):
                for x in new_files:
                    if x in files:
                        print(str(datetime.datetime.now()) + "New file detected "+x)
                        sendMail(loginname, loginpassword, toemail, fromemail, subject, gettext(), x, SMTPserver, SMTPort)
            files=new_files
            f.close()
            time.sleep(1)

def sendMail(login, password, send_to, send_from, subject, text, send_file, server, port):

    msg = MIMEMultipart()
    msg['From'] = send_from
    msg['To'] = COMMASPACE.join(send_to)
    msg['Date'] = formatdate(localtime=True)
    msg['Subject'] = subject

    msg.attach( MIMEText(text) )

    part = MIMEBase('application', "octet-stream")
    part.set_payload( open(send_file,"rb").read() )
    Encoders.encode_base64(part)
    part.add_header('Content-Disposition', 'attachment; filename="%s"' % os.path.basename(send_file))
    msg.attach(part)

    smtp = smtplib.SMTP(SMTPserver, SMTPort)
    smtp.set_debuglevel(1) 
    smtp.ehlo() 
    smtp.starttls() 
    smtp.login(login, password) 
    smtp.sendmail(send_from, send_to, msg.as_string() )
    smtp.close()


def gettext():
    text = "A new file has been added to the security footage folder. \nTime Stamp: "+ str(datetime.datetime.now())
    return(text)

class Tee(object):
    def __init__(self, *files):
        self.files = files
    def write(self, obj):
        for f in self.files:
            f.write(obj)


#Execute loop
mainloop()
Jose Garcia
  • 25
  • 1
  • 6
1

It looks like the email module has been refactored over time. This fixed the 'LazyImporter' object not callable error for me on Python 2.7:

from email.mime.text import MIMEText

Noteably it was not happy with (what I thought were) synonyms like import email; email.mime.text.MIMEText(...)

John Mee
  • 50,179
  • 34
  • 152
  • 186
1

I use python3 and I could not for the life of me get any of these examples to work, but I was able to come up with something that works and is a whole lot simpler.

import smtplib
from email.message import EmailMessage
from email.mime.base import MIMEBase
from email import encoders

# Defining Objects and Importing Files ------------------------------------

# Initializing video object
video_file = MIMEBase('application', "octet-stream")

# Importing video file
video_file.set_payload(open('video.mkv', "rb").read())

# Encoding video for attaching to the email
encoders.encode_base64(video_file)

# creating EmailMessage object
msg = EmailMessage()

# Loading message information ---------------------------------------------
msg['From'] = "person_sending@gmail.com"
msg['To'] = "person_receiving@gmail.com"
msg['Subject'] = 'text for the subject line'
msg.set_content('text that will be in the email body.')
msg.add_attachment(video_file, filename="video.mkv")

# Start SMTP Server and sending the email ---------------------------------
server=smtplib.SMTP_SSL('smtp.gmail.com',465)
server.login("person_sending@gmail.com", "some-clever-password")
server.send_message(msg)
server.quit()
Dewey Brooke
  • 407
  • 4
  • 10
0

Just put your script in a loop and have it sleep for 60 seconds. You can use glob to get a list of files in the directory. in is pretty useful for seeing what is in a list (i.e. the list of files in the directory).

import time, glob

files=glob.glob("/home/me/Desktop/*.mp4") #Put whatever path and file format you're using in there.

while 1:
    new_files=glob.glob("/home/me/Desktop/*.mp4")
    if len(new_files)>len(files):
        for x in new_files:
            if x not in files:
                print("New file: "+x) #This is where you would email it. Let me know if you need help figuring that out.
    files=new_files
    time.sleep(60)
Brōtsyorfuzthrāx
  • 4,387
  • 4
  • 34
  • 56
  • It wouldn't hurt to do more frequent intervals than 60 seconds. It shouldn't consume your processor significantly at all. Once a second would be more than okay. – Brōtsyorfuzthrāx Sep 04 '14 at 06:05
  • I got it down to scanning and executing the email sender, but it fails to load the payload. can you see what is missing? – Jose Garcia Sep 04 '14 at 16:02