os not letting me save email attachment using pywin32 - python

import win32com.client
import pythoncom
import time
import os
class Handler_Class(object):
def OnNewMailEx(self, receivedItemsIDs):
# RecrivedItemIDs is a collection of mail IDs separated by a ",".
# You know, sometimes more than 1 mail is received at the same moment.
for ID in receivedItemsIDs.split(","):
print('Running scan...')
mail = outlook.Session.GetItemFromID(ID)
email_date = mail.SentOn.strftime("%m-%d-%y" + " at " + "%I:%M:%S %p")
email_date_stamp = mail.SentOn.strftime('%m-%d-%y_%I:%M:%S-%p')
email_message = mail.Body
email_subject = mail.Subject
email_sender = mail.SenderEmailAddress
email_attachments = mail.Attachments
try:
if check_correct_subject(email_subject) == True:
print('From: ' + email_sender)
print('Subject: ' + email_subject)
print('Date: ' + email_date)
if email_attachments.Count > 0:
print(str(email_attachments.Count) + ' attachments found.')
for i in range(email_attachments.Count):
email_attachment = email_attachments.Item(i + 1)
report_name = email_date_stamp + '_' + email_attachment.FileName
print(report_name)
email_attachment.SaveASFile(os.getcwd() + '\\Reports\\Broker_Risk_LDW\\' + report_name)
print('Pushing attachment - ' + report_name + ' - to check_correct_email() function.')
if check_correct_attachment(email_attachment) == True:
save_incoming_report(email_attachment, report_name, get_report_directory(email_subject))
else:
print('Not the attachment we are looking for.')
# add error logging here
break
else: # ***********add error logging here**************
print('No attachment found.')
except:
pass
I am calling the class like this.
if __name__ == '__main__':
outlook = win32com.client.DispatchWithEvents("Outlook.Application", Handler_Class)
#and then an infinit loop that waits from events.
pythoncom.PumpMessages()
The problem here is this line: email_attachment.SaveASFile(os.getcwd() + '\\Reports\\Broker_Risk_LDW\\' + report_name)
That folder is already created and it was working before I switched this to a class, in order to work with an Outlook event listener. I am not getting an error message, however the attachment is not saving.
Any tips?

Related

Python - using smtplib to send to multiple recipients

I'm finding it very difficult to modify this code to send to send to multiple recipients, I have tried many variations of the examples already out there. I'm very new to python so any help would be much appreciated.
It is as part of safety system I am designing to alert parents and carers of potential elopement risk for children and adults with ASD.
'''
import time
import serial
import smtplib
TO = 'email#mail.org'
GMAIL_USER = 'email#gmail.com'
GMAIL_PASS = 'passowrd'
SUBJECT = 'Security Alert'
TEXT = 'Movement detected!'
ser = serial.Serial('COM6', 9600)
def send_email():
print("Sending Email")
smtpserver = smtplib.SMTP("smtp.gmail.com",587)
smtpserver.ehlo()
smtpserver.starttls()
smtpserver.ehlo
smtpserver.login(GMAIL_USER, GMAIL_PASS)
header = 'To:' + TO + '\n' + 'From: ' + GMAIL_USER
header = header + '\n' + 'Subject:' + SUBJECT + '\n'
print header
msg = header + '\n' + TEXT + ' \n\n'
smtpserver.sendmail(GMAIL_USER, TO, msg)
smtpserver.close()
while True:
message = ser.readline()
print(message)
if message[0] == 'M' :
send_email()
time.sleep(0.5)
'''
Send the alert to multiple people.
Have you had a look at this yet? How to send email to multiple recipients using python smtplib?
It looks like you might be dropping some of the pieces of your header too by overwriting them:
header = 'From: ' + GMAIL_USER
Instead of:
header = header + 'From: ' + GMAIL_USER
You might also want to consider using format instead, but I'm already out of my depth on Python :-)

Identify sending user, Python IRC

So I made a Twitch.tv bot for my own channel, after having fun with it a little bit, I wanted to have some command restricted to some users, and some commands that can say the users name, for example:
Username reply example:
Person1: !tea
PythonBot: Would you like some tea, Person1?
Admin restriction example:
Person1: !ban Person2
PythonBot: I'm sorry, Person1, This command is restricted to admins only.
Ok, So here is the code I'm using (I will be modifying it soon to make it my own)
import socket
import threading
bot_owner = '~Not Today~'
nick = '~Not Today~'
channel = '~Not Today~'
server = 'irc.twitch.tv'
password = '~Not Today~'
queue = 13
irc = socket.socket()
irc.connect((server, 6667))
irc.send('PASS ' + password + '\r\n')
irc.send('USER ' + nick + ' 0 * :' + bot_owner + '\r\n')
irc.send('NICK ' + nick + '\r\n')
irc.send('JOIN ' + channel + '\r\n')
def message(msg):
global queue
queue = 5
if queue < 20:
irc.send('PRIVMSG' + channel + ' :' + msg + '\r\n')
else:
print 'Message Deleted'
def queuetimer():
global queue
queue = 0
threading.Timer(30,queuetimer).start()
queuetimer()
while True:
botdata = irc.recv(1204)
botuser = botdata.split(':')[1]
botuser = botuser.split('!')[0]
print botdata
if botdata.find('PING') != -1:
irc.send(botdata.replace('PING', 'PONG'))
if botdata.find('!res') != -1:
irc.send(botdata.replace('!res', '1600x900'))
The twitch IRC raw message is like
:jkm!jkm#jkm.tmi.twitch.tv PRIVMSG #trumpsc :needs Kappa
for above msg, it actually means userjkm at channel trumpsc saying needs Kappa
for your code, the method to get botuser is right, but you don't have the message the user sent, add following code should get the message
botmsg = botdata.split(':')[2]
so you get the message and username, the next step would be handling them.
Here would be some example for your need. For me, I will prepared a adminuserList and commmandList for other command, but I will simplify it here.
def commmanHandler(botuser, botmsg): # botmsg = '!ban user1'
command = botmsg.split(' ')[0] # command = '!ban'
command = command[1:] # command = 'ban'
argu = message.split(' ')[1] # argu = 'user1'
if command not in commmandList:
raise Exception("command not support")
if command == 'ban': # ban command, or using switch
# check if admin
if botuser not in adminList:
raise Exception("I'm sorry, " + botuser + ", This command is restricted to admins only.")
# admin, able to ban
irc.send('PRIVMSG' + channel + ' :' + '.ban ' + argu)
then call this function in your while loop to handle all message you get
try:
commmanHandler(botuser, botmsg)
except Exception, e:
print e
irc.send('PRIVMSG' + channel + ' :' + e)
here would be my solution, and also, don't forget to give the bot moderator privilege.

Type error: 'module' object has no attribute '_getitem_'

I am trying to fetch emails and then we need to write the mails in to different files according to the subject.
import email
import imaplib
from threading import Thread
from time import sleep
import time
def myThreadFun():
M = imaplib.IMAP4_SSL('imap.gmail.com')
M.login("noticeboard16#gmail.com", "embeddedSystems")
while (1):
M.select()
rv, data1 = M.search(None, 'UNSEEN')
for i in data1[0].split():
resp, data = M.FETCH(i, '(RFC822)')
mail = email.message_from_string(data[0][1])
for part in mail.walk():
# multipart are just containers, so we skip them
if part.get_content_maintype() == 'multipart':
continue
# we are interested only in the simple text messages
if part.get_content_subtype() != 'plain':
continue
payload = part.get_payload()
print '\n'
print '[%s]' % (mail['Subject'])
print 'From: %s' % (mail['From'])
print 'Date:', mail['Date']
print '================================='
print payload
#time.sleep(10)
#save_string = str("/home/buddhi-xubuntu/Python/email_" + ".text")
#myfile = open(save_string, 'a')
#myfile.write(mail['Subject']+ "\nFrom: " + mail['From'] + "\nDate: " + mail['Date'] + "=============\n" + payload)
#myfile.close()
#time.sleep(10)
#with file('email_.txt', 'r') as original: data = original.read()
#with file('email_2.txt', 'w') as modified: modified.write(mail['Subject']+ "\nFrom: " + mail['From'] + "\nDate: " + mail['Date'] + "\n=============\n" + payload + "\n" + data)
#orig_string = str("/home/e11452/Downloads/email_" + ".text")
#f = open(orig_string,'r')
#temp = f.read()
#f.close()
if mail['Subject']=="E/11":
new_string = str("/home/e11452/Downloads/email_11" + ".text")
f = open(new_string, 'w')
f.write(mail['Subject']+ "\nFrom: " + mail['From'] + "\nDate: " + mail['Date'] + "\n=============\n" + payload + "\n")
elif mail['Subject']=="E/10":
new_string = str("/home/e11452/Downloads/email_12" + ".text")
-f = open(new_string, 'w')
f.write(mail['Subject']+ "\nFrom: " + mail['From'] + "\nDate: " + mail['Date'] + "\n=============\n" + payload + "\n")
f.write(temp)
f.close()
time.sleep(10)
M.LOGOUT()
thread = Thread(target = myThreadFun)
thread.start()
above is the code i tried and i get an error saying
Traceback (most recent call last): File "email14.py", line 58, in if email['Subject'] == 'E/11': TypeError: 'module' object has no attribute 'getitem'
Seems that you misspell mail as email. email is a module you imported. Then you got the error.

Using python and elixir to send emails utilizing db tables with foreign keys

I have a python script that pulls information from a single database table and sends a weekly update email to users. I'd like to find a way to modify my code to allow for normalizing the structure and putting all of the investigator info (prefix, fname, lname, and email) into it's own table. However, I'm not sure how to do this within the structure of the elixir model and my python code.
Here is my current elixir model file:
from elixir import *
import auth as auth
au = auth.UserAuth()
metadata.bind = 'mysql://' + au.user + ':' + au.password + '#localhost/' + au.database
metadata.bind.echo = True
class Protocol(Entity):
id = Field(Integer, primary_key = True)
irb_no = Field(Text)
title = Field(Text)
prefix = Field(Text)
fname = Field(Text)
lname = Field(Text)
email = Field(Text)
action_date = Field(Date)
action = Field(Text)
approved = Field(Integer)
using_options(tablename = 'protocols')
def __repr__ (self):
return '%d' %(self.id)
And here is my python script:
import smtplib
import auth as auth
import ProtocolModel as PM
from elixir import *
from datetime import datetime
au = auth.UserAuth()
setup_all()
create_all()
table = PM.Protocol
records = table.query.all()
if len(records) == 0:
print 'No records in Table'
else:
for record in records:
setup_all()
if record.approved == 1:
print 'Completed'
else:
FROMADDR = au.google_user
LOGIN = FROMADDR
PASSWORD = au.google_password
TOADDRS = record.email
SUBJECT = "Weekly Research Update for " + record.irb_no + " - " + record.title
date1 = datetime.strptime(str(record.action_date), '%Y-%m-%d')
date2 = date1.strftime('%B %d, %Y')
msg = ("From: %s\r\nTo: %s\r\nSubject: %s\r\n\r\n" % (FROMADDR, ", ".join(TOADDRS), SUBJECT) )
msg += 'Dear' + ' ' + record.prefix + ' ' + record.fname + ' ' + record.lname + ',' + '\n' + '\n'
msg += 'Our records indicate that the most recent action on your research protocol titled ' + record.title + ' was taken on ' + str(date2) +'.' +'\n'
msg += 'This action was: ' + record.action
server = smtplib.SMTP('smtp.gmail.com', 587)
server.set_debuglevel(1)
server.ehlo()
server.starttls()
server.login(LOGIN, PASSWORD)
server.sendmail(FROMADDR, TOADDRS, msg)
server.quit()
This seems like it should be a relatively simple change, but I'm just not sure how to go about this. Any help is much appreciated, thanks!
I figured it out. Used ManyToOne in the new entity class in the model file and referenced that in the python code. It was a simple fix once I got back into it.
New elixir model:
from elixir import *
import auth as auth
au = auth.UserAuth()
metadata.bind = 'mysql://' + au.user + ':' + au.password + '#localhost/' + au.database
metadata.bind.echo = True
class Investigator(Entity):
id = Field(Integer, primary_key = True)
prefix = Field(Text)
fname = Field(Text)
lname = Field(Text)
email = Field(Text)
using_options(tablename = 'investigators')
def __repr__ (self):
return '%d' %(self.id)
class Protocol(Entity):
id = Field(Integer, primary_key = True)
irb_no = Field(Text)
title = Field(Text)
investigator = ManyToOne('Investigator', colname='investigator_id')
action_date = Field(Date)
action = Field(Text)
approved = Field(Integer)
using_options(tablename = 'protocols')
def __repr__ (self):
return '%d' %(self.id)
New python script:
import smtplib
import auth as auth
import ProtocolModel1 as PM
from elixir import *
from datetime import datetime
au = auth.UserAuth()
setup_all()
create_all()
table = PM.Protocol
records = table.query.all()
if len(records) == 0:
print 'No records in Table'
else:
for record in records:
setup_all()
if record.approved == 1:
print 'Completed'
else:
FROMADDR = au.google_user
LOGIN = FROMADDR
PASSWORD = au.google_password
TOADDRS = record.investigator.email
SUBJECT = "Weekly Research Update for " + record.irb_no + " - " + record.title
date1 = datetime.strptime(str(record.action_date), '%Y-%m-%d')
date2 = date1.strftime('%B %d, %Y')
msg = ("From: %s\r\nTo: %s\r\nSubject: %s\r\n\r\n" % (FROMADDR, ", ".join(TOADDRS), SUBJECT) )
msg += 'Dear' + ' ' + record.investigator.prefix + ' ' + record.investigator.fname + ' ' + record.investigator.lname + ',' + '\n' + '\n'
msg += 'Our records indicate that the most recent action on your research protocol titled ' + record.title + ' was taken on ' + str(date2) +'.' +'\n'
msg += 'This action was: ' + record.action
server = smtplib.SMTP('smtp.gmail.com', 587)
server.set_debuglevel(1)
server.ehlo()
server.starttls()
server.login(LOGIN, PASSWORD)
server.sendmail(FROMADDR, TOADDRS, msg)
server.quit()

Python smtplib sometimes fails sending

I wrote a simple "POP3S to Secure SMTP over TLS" MRA script in Python (see below).
It works fine, but sometimes it returns "Connection unexpectedly closed" while trying to send via SMTP. Running the script again will deliver that message successfully.
Please give me some suggestions why it would fail to deliver a message sometimes but at the next run it delivers exactly this message successfully!?
#! /usr/bin/env python
import poplib
import email
def forward_pop3_smtp( smtp_credentials, pop3_credentials, forward_address):
pop3_server = pop3_credentials[0]
pop3_port = pop3_credentials[1]
pop3_user = pop3_credentials[2]
pop3_password = pop3_credentials[3]
message_recipient = forward_address
server = poplib.POP3_SSL( pop3_server, pop3_port)
server.user( pop3_user)
server.pass_( pop3_password)
for messages_iterator in range( len( server.list()[1])):
message_list = server.retr( messages_iterator + 1)[1]
message_string = ''
for message_line in message_list:
message_string += message_line + '\n'
message_message = email.message_from_string( message_string)
message_message_as_string = message_message.as_string()
message_sender = message_message[ 'From']
print( 'message_sender = ' + message_sender)
smtp_return = send_smtp( smtp_credentials, message_sender, message_recipient, message_message_as_string)
print( 'smtp_return = ' + str(smtp_return))
if smtp_return == 0:
print( 'Deleting message ' + message_message[ 'Subject'] + ':\n')
return_delete = server.dele( messages_iterator + 1)
print( 'return_delete = \n' + str(return_delete))
print( '\n')
server.quit()
def send_smtp( smtp_credentials, message_sender, message_recipient, message_message_as_string):
smtp_server = smtp_credentials[0]
smtp_port = smtp_credentials[1]
smtp_user = smtp_credentials[2]
smtp_password = smtp_credentials[3]
import smtplib
exception = 0
try:
server = smtplib.SMTP( smtp_server)
server.starttls()
server.login( smtp_user, smtp_password)
smtp_sendmail_return = server.sendmail( message_sender, message_recipient, message_message_as_string)
server.quit()
except Exception, e:
exception = 'SMTP Exception:\n' + str( e) + '\n' + str( smtp_sendmail_return)
return exception
if __name__ == '__main_':
print( 'This module needs to be imported!\n')
quit()
Use Port 587 for TLS. I don't see the script use smtp_port
Use like,
server = smtplib.SMTP( smtp_server, int(smtp_port)
For Secure SMTP (SMTP + SSL), use smtplib.SMTP_SSL

Categories