Encoded image gives different code when it was send wtih smtplib - python-3.x

I've tried to encode an image with this method :
def resim_ac(self):
dosya_ismi = QFileDialog.getOpenFileName(self, "Resim AƧ", os.getenv("HOME"))
with open(dosya_ismi[0], "rb") as file:
image = file.read()
encode_image = base64.encodestring(image)
if str(encode_image) != "":
return str(encode_image)
else:
return ""
encoded_image equals to image: b'iVBORw0KGgoAAAANSUhEUgAAAgAAAAI...BlLm9yZ5vuPBoAAAAASUVORK5CYII=\n'(It is encoded image)
Whenever I try to send this code with email with this method:
mesaj = MIMEMultipart()
mesaj_govdesi2 = MIMEText(str(self.resim_ac), "plain")
mesaj.attach(mesaj_govdesi2)
mesaj["Subject"] = self.subject_text.text() #LineEdit
mail = smtplib.SMTP("smtp.gmail.com", 587)
mail.ehlo()
mail.starttls()
mail.login(self.email, self.passw) # e-mail adress and it's password
mail.sendmail(self.email,self.email_to, mesaj.as_string())
print("Mail Sended....")
mail.close()
It gives me this
rather than b'iVBORw0KGgoAAAANSUhEUgAAAgAAAAI...BlLm9yZ5vuPBoAAAAASUVORK5CYII=\n'
My question is why these two are different? And how can I make them same

okay I solved it. The problem is that I should define encode_image with self. So it is easily called in another function in the class.
content = str(self.encryption())
mesaj = MIMEMultipart()
mesaj_govdesi = MIMEText(str(content), "plain")
mesaj_govdesi2 = MIMEText(str(self.encode_image), "plain")
mesaj.attach(mesaj_govdesi)
mesaj.attach(mesaj_govdesi2)
mesaj["Subject"] = self.subject_text.text() #LineEdit
try:
mail = smtplib.SMTP("smtp.gmail.com", 587)
mail.ehlo()
mail.starttls()
mail.login(self.email, self.passw) # e-mail adress and it's password
mail.sendmail(self.email,self.email_to, mesaj.as_string())

Related

smtplib sending duplicate emails

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!")

How do I download attachments from gmail?

I was able to locate the JSON file I want to download from attachment using :
part.get_content_type() == "application/json"
But have no idea on how to actually download and save it to local directory can someone pls help?
Here is the whole method:
#based on Python example from
#https://github.com/codingforentrepreneurs/30-Days-of-Python/blob/master/tutorial-reference/Day%209/inbox.py
import imaplib
host = 'imap.gmail.com' #inbox
def get_inbox(tempList):
mail = imaplib.IMAP4_SSL(host) #server
mail.login(tempList[0], tempList[2]) #login user name, user pass
mail.select("inbox") #defualt inbox
_, search_data = mail.search(None, 'UNSEEN')
my_message = []
for num in search_data[0].split():
email_data = {}
_, data = mail.fetch(num, '(RFC822)') #getting the msg data from gmail
_, b = data[0] #data in bytes
email_message = email.message_from_bytes(b)
for part in email_message.walk():
if part.get_content_type() == "application/json":
pass
my_message.append(email_data)
return my_message
if the attachment is in another file type
just change the json in
if part.get_content_type() == "application/json"
to the file type you want to downlaod

Why does the body part of email is not found Python imap?

Found an article about reading email with Python. The sender of the letter and the subject are found but there are problems with body of the mail - it is not found. Maybe there are some other ways to read body?
import imaplib
import email
from email.header import decode_header
import webbrowser
import os
# account credentials
username = "username#mail.ru"
password = "password"
def clean(text):
return "".join(c if c.isalnum() else "_" for c in text)
imap = imaplib.IMAP4_SSL("imap.mail.ru")
imap.login(username, password)
# it is spam folder id
status, messages = imap.select("&BCEEPwQwBDw-")
messages = int(messages[0])
for i in range(messages, 0, -1):
res, msg = imap.fetch(str(i), "(RFC822)")
for response in msg:
if isinstance(response, tuple):
msg = email.message_from_bytes(response[1])
subject, encoding = decode_header(msg["Subject"])[0]
if isinstance(subject, bytes):
subject = subject.decode(encoding)
From, encoding = decode_header(msg.get("From"))[0]
if isinstance(From, bytes):
From = From.decode(encoding)
print("Subject:", subject)
print("From:", From)
if msg.is_multipart():
for part in msg.walk():
# extract content type of email
content_type = part.get_content_type()
content_disposition = str(part.get("Content-Disposition"))
try:
body = part.get_payload(decode=True).decode()
except:
pass
if content_type == "text/plain" and "attachment" not in content_disposition:
print(body)
elif "attachment" in content_disposition:
filename = part.get_filename()
if filename:
folder_name = clean(subject)
if not os.path.isdir(folder_name):
os.mkdir(folder_name)
filepath = os.path.join(folder_name, filename)
open(filepath, "wb").write(part.get_payload(decode=True))
else:
content_type = msg.get_content_type()
body = msg.get_payload(decode=True).decode()
if content_type == "text/plain":
print(body)
if content_type == "text/html":
folder_name = clean(subject)
if not os.path.isdir(folder_name):
os.mkdir(folder_name)
filename = "index.html"
filepath = os.path.join(folder_name, filename)
open(filepath, "w").write(body)
webbrowser.open(filepath)
imap.close()
imap.logout()
For some reason, the body is not located and because of this, an error appears.
NameError: name 'body' is not defined
body is not defined because of this:
try:
body = part.get_payload(decode=True).decode()
except:
pass
You tried to define body, but failed due to some kind of error that you allowed to pass silently (hint: don't do that!). Then the next blocks of code assumed that body had already been assigned when it hadn't.
Solution: define body outside of the try/except clause:
body = None
try:
body = part.get_payload(decode=True).decode()
except:
# pass
import traceback
traceback.print_exception()
# this way you'll at least know what the error was

Scrape gmail for selected content and get attachments

I have a problem to scrape gmail.
Candidates should extract or pull information relating to financial transactions from Gmail. The information could be invoices, subscription alerts, bills, etc. We want you to connect with a Gmail account and scrape or pull data of invoices, subscriptions, upcoming bills. You can scrape the emails for words like upcoming invoice or subscription or invoice etc and pull the
amount, date, attachment if any all these details.
I have to collect information and also store all the attachments. Is there any specific simple way to do it?
my Code
import imaplib
import os
import email, getpass
import sys
import json
class GmailFinin():
def helloWorld(self):
print("\nHello I'm here to help you")
def initializeVariables(self):
self.usr = ""
self.pwd = ""
self.mail = object
self.mailbox = ""
self.mailCount = 0
self.destFolder = ""
self.data = []
self.ids = []
self.idsList = []
def getLogin(self):
print("\nPlease enter your Gmail login details below.")
self.usr = input("Email: ")
# self.pwd = input("Password: ")
self.pwd = getpass.getpass("Enter your password --> ")
def attemptLogin(self):
self.mail = imaplib.IMAP4_SSL("imap.gmail.com", 993)
if self.mail.login(self.usr, self.pwd):
print("\nLogon SUCCESSFUL")
self.destFolder = input("\nPlease choose a destination folder in the form of /Users/username/dest/ (do not forget trailing slash!): ")
if not self.destFolder.endswith("/"): self.destFolder+="/"
return True
else:
print("\nLogon FAILED")
return False
def checkIfUsersWantsToContinue(self):
print("\nWe have found "+str(self.mailCount)+" emails in the mailbox "+self.mailbox+".")
return True if input("Do you wish to continue extracting all the emails into "+self.destFolder+"? (y/N) ").lower().strip()[:1] == "y" else False
def selectMailbox(self):
# self.mailbox = input("\nPlease type the name of the mailbox you want to extract, e.g. Inbox: ")
self.mailbox = "Inbox"
bin_count = self.mail.select(self.mailbox)[1]
self.mailCount = int(bin_count[0].decode("utf-8"))
return True if self.mailCount > 0 else False
def searchThroughMailbox(self):
type, self.data = self.mail.search(None, "ALL")
self.ids = self.data[0]
self.idsList = self.ids.split()
def parseEmails(self):
jsonOutput = {}
for anEmail in self.data[0].split():
type, self.data = self.mail.fetch(anEmail, '(UID RFC822)')
raw = self.data[0][1]
try:
raw_str = raw.decode("utf-8")
except UnicodeDecodeError:
try:
raw_str = raw.decode("ISO-8859-1") # ANSI support
except UnicodeDecodeError:
try:
raw_str = raw.decode("ascii") # ASCII ?
except UnicodeDecodeError:
pass
msg = email.message_from_string(raw_str)
jsonOutput['subject'] = msg['subject']
jsonOutput['from'] = msg['from']
jsonOutput['date'] = msg['date']
raw = self.data[0][0]
raw_str = raw.decode("utf-8")
uid = raw_str.split()[2]
# Body #
if msg.is_multipart():
for part in msg.walk():
partType = part.get_content_type()
## Get Body ##
if partType == "text/plain" and "attachment" not in part:
jsonOutput['body'] = part.get_payload()
## Get Attachments ##
if part.get('Content-Disposition') is not None:
attchName = part.get_filename()
print(attchName)
if bool(attchName):
attchFilePath = str(self.destFolder)+str(uid)+str("/")+str(attchName)
print(attchFilePath)
os.makedirs(os.path.dirname(attchFilePath), exist_ok=True)
with open(attchFilePath, "wb") as f:
f.write(part.get_payload(decode=True))
else:
# jsonOutput['body'] = msg.get_payload(decode=True).decode("utf-8") # Non-multipart email, perhaps no attachments or just text.
jsonOutput['body'] = msg.get_payload()
outputDump = json.dumps(jsonOutput)
emailInfoFilePath = str(self.destFolder)+str(uid)+str("/")+str(uid)+str(".json")
os.makedirs(os.path.dirname(emailInfoFilePath), exist_ok=True)
print(emailInfoFilePath)
with open(emailInfoFilePath, "w") as f:
f.write(outputDump)
def __init__(self):
self.initializeVariables()
self.helloWorld()
self.getLogin()
if self.attemptLogin():
not self.selectMailbox() and sys.exit()
else:
sys.exit()
not self.checkIfUsersWantsToContinue() and sys.exit()
self.searchThroughMailbox()
self.parseEmails()
if __name__ == "__main__":
run = GmailFinin()
I have tried using below for search, but I don't think i.e optimal because it is searching only in subject and How to add multiple or condition for list of keywords.
type, self.data = self.mail.search(None, '(OR TEXT "bill" SUBJECT "bill")')

Problem with sendmail(email, send_to_email, msg.as_string())

I'm trying to attach and send multiple attachments to list of emails individually
import smtplib
import openpyxl
import os.path
from email import encoders
from openpyxl import load_workbook
from email.mime.text import MIMEText
from email.mime.base import MIMEBase
from email.mime.multipart import MIMEMultipart
email_source_workbook = load_workbook(filename=r'C:\Users\Name\Desktop\final mailer\mail list.xlsx')
curr_sheet = email_source_workbook['ml']
attachment_location = [r'C:\Users\Name\Desktop\final mailer\at1.txt']
row_len = curr_sheet.max_row
email = 'example#email.com'
password = 'pswrd'
subject = 'test subj' #Subject
message = '''this
is test
mail
ok?
'''
msg = MIMEMultipart()
with smtplib.SMTP('smtp-mail.outlook.com', 587) as svr:
print("Initializing the server")
svr.ehlo()
svr.starttls()
svr.ehlo()
svr.login(email, password)
print("login sucessful")
for curr_attachment in attachment_location:
name_of_attachment = os.path.basename(curr_attachment)
attachment_payload = MIMEBase('application' , "octet-stream")
attachment_payload.set_payload(open(curr_attachment, "rb").read())
encoders.encode_base64(attachment_payload)
attachment_payload.add_header('Content-Disposition', 'attachment' , filename=name_of_attachment)
for i in range(1 , row_len+1):
print("###################")
send_to_email = curr_sheet.cell(row = i, column = 1).value
msg['From'] = email
msg['To'] = send_to_email
msg['Subject'] = subject
msg.attach(MIMEText(message, 'plain'))
svr.sendmail(email, send_to_email, msg.as_string())
svr.quit()
i can send the mail but the problem is for example there are 3 email addresses in the excel file
it will send the first mail to the first recipient
perfectly fine
then in the second mail it'll send it to the second and first recipient with the attachment + the wole body of mail as one more attachment
and to the third it will send to the first two recipients with the third with the original attachment with two same attachments that are the body of the mail. it will go on so fourth with n number of email addresses. i.e. 10 mail id and on the 10th mail the 10th recipient with all the previous 9 and 10 attachments.
found the solution
msg = MIMEMultipart()
should be in
for i in range(1 , row_len+1):
print("###################")
send_to_email = curr_sheet.cell(row = i, column = 1).value
msg['From'] = email
msg['To'] = send_to_email
msg['Subject'] = subject
msg = MIMEMultipart()
msg.attach(MIMEText(message, 'plain'))
svr.sendmail(email, send_to_email, msg.as_string())

Resources