I just finished a small scripting project for one of Blumetech’s clients. It was a small project but shows how simple scripts can be used to automate many tasks around the office.
The client wanted to
- Upload files to an FTP server via SFTP
- Wanted logging on all the uploads
- Wanted success and failure email alerts
The work was simple to do. In this particular case I did similar work for another client and it was easy to reuse the code that was previously written. Hence the learning curve needed to handle the SFTP connection was straightforward. The work was done and deployed in under 6 hours.
Of course I chose Python to do the work. One of the reasons I chose python over a bash script, Powershell, or even a simple Windows batch file is the readability of the code. The code excerpt below which represents the core module is readable even to people with little experience with Python. This is important as I am counting on other engineers with little Python experience to be the tier 1 support for these applications. Python’s simplicity allows even neophytes to get started with the language very quickly.
I expect more and more of these scripts and more office automation in the coming future. Many offices find themselves doing routine business tasks where parts of their workflow can be automated to increase both speed and accuracy.
'''
Uploads files to complysci FTP site.
Created on Feb 14, 2012
@author: mraposa
'''
import thread
import sys
import traceback
import smtplib
import os
from email.mime.text import MIMEText
import pysftp
from paramiko import SSHException
from LogFileHelper2x import getDefaultLogger
from GeneralUtilities import displayPID
from FileHelper2x import getFileList
LOG_FILENAME = "FtpUpload_log.txt"
LOG_NAME = "Main"
WORK_DIR = r"E:\Data\Shared\FTP Files"
EMAIL_TO_SUCCESS = ["",]
EMAIL_TO_FAIL = ["", ""]
FTP_UID = ""
FTP_PASS = ""
FTP_SERVER = ""
SMTP_SERVER = "10.0.1.6"
log = getDefaultLogger(LOG_FILENAME, 'Main', consoleLogging=False)
def send_simple_email(to, subject, message, fromAddr='[email protected]'):
"""
Function sends a simple plain text message to multiple recipients
to = string of recipients separated by a comma, e.g. '[email protected],[email protected]'
"""
# Create a text/plain message
msg = MIMEText(message)
msg['Subject'] = subject
msg['From'] = fromAddr
msg['To'] = to
# Send the message via our own SMTP server.
s = smtplib.SMTP(SMTP_SERVER)
s.sendmail(fromAddr, to.split(','), msg.as_string())
s.quit()
def sftpUpload(f):
try:
log.info("Connecting to %s" % FTP_SERVER)
srv = pysftp.Connection(FTP_SERVER, username=FTP_UID, password=FTP_PASS)
log.info("Uploading %s" % f)
srv.put(f)
log.info("Getting file list on FTP Server")
log.info(srv.listdir())
log.info("Disconnecting from ftp server")
srv.close()
return 0
except SSHException:
log.error("Unable to connect - login fail")
message = """
"Unable to connect - login fail"
Host: %s
UID: %s
""" % (FTP_SERVER, FTP_UID)
subject = "Ftp Upload Error: Unable to connect - login fail"
for to in EMAIL_TO_FAIL:
send_simple_email(to, subject, message)
return 1
except AttributeError:
log.error("Host unreachable:")
message = """
"Host unreachable:"
Host: %s
UID: %s
""" % (FTP_SERVER, FTP_UID)
subject = "Ftp Upload Error: Host unreachable:"
for to in EMAIL_TO_FAIL:
send_simple_email(to, subject, message)
return 1
def execute_task():
for f in getFileList(WORK_DIR):
log.info("Working on file: %s" % f)
if sftpUpload(f) == 0:
log.info("File upload successful")
log.info("Deleting file: %s" %f)
os.remove(f)
subject = "Ftp Upload Successful"
message = """
Successfully uploaded file
File: %s
Server: %s
""" % (os.path.basename(f), FTP_SERVER)
for to in EMAIL_TO_SUCCESS:
send_simple_email(to, subject, message)
if __name__ == '__main__':
try:
thread.start_new_thread(displayPID, ())
execute_task()
except Exception:
exc_type, exc_value, exc_traceback = sys.exc_info()
print >> sys.stderr, "Exception in user code:"
print >> sys.stderr, '-'*60
traceback.print_exc(file=sys.stderr)
print >> sys.stderr, '-'*60
print >> sys.stderr, "*** format_exception:"
errorText = ""
for tmp in traceback.format_exception(exc_type, exc_value, exc_traceback):
errorText = errorText + "%s" % tmp
print >> sys.stderr, errorText
log.exception("Exception in %s" % LOG_FILENAME)
msg = """
An exception occurred with an automated FTP client.
%s
""" % (errorText,)
log.info("Attempting to send email")
for to in EMAIL_TO_FAIL:
send_simple_email(to, "Automated FTP Client Exception", msg)
log.info("E-Mail sent")
sys.exit(1)
print("\nAll done!")
log.info("All done!")
sys.exit(0)