Getting 'UnicodeDecodeError' when trying to send mail with Python - python

I'm trying to send an email using python but everytime I try to send, I'm getting UnicodeDecodeError. Where am I doing wrong? I couldn't figure out by searching on web.
Here's my full code:
import smtplib
import random
import datetime
# Random name list
names = ['Jack', 'Kevin', 'Laura']
# Datetime get time
date = datetime.datetime.now().strftime('%a, %b %d')
# Random order id's
r0 = random.randint(702, 711)
r1 = random.randint(1111111, 9999999)
r2 = random.randint(1111111, 9999999)
r3 = round(random.uniform(13, 25), 4)
# Mail content
mailc = """Hi {}! You did it buddy: #{}
Service: Standard
*Profit: S$ {}
Send it no later than {}...
""".format(random.choice(names), {r0}-{r1}-{r2}, {r3}, date)
# Subject
sub = '(.LO) New toy: {}-{}-{}'.format({r0}, {r1}, {r2})
# Mail adreesses and password
senderAddress = 'xxx#gmail.com'
senderPass = 'xxyyww'
receiverAddress = 'yyy#gmail.com'
# Server
server = smtplib.SMTP('smtp.gmail.com', 587)
server.ehlo()
server.starttls()
server.login(senderAddress, senderPass)
# Message
message = 'Subject: {}\n\n{}'.format(sub, mailc)
server.sendmail(senderAddress, receiverAddress, message)
server.quit()
print("Mail sent.")
And this is the error:
Traceback (most recent call last):
File "C:\Users\WINDOWS 8.1\Desktop\automaticOrderEmailSender.py", line 35, in
<module>
server = smtplib.SMTP('smtp.gmail.com', 587)
File "C:\Users\WINDOWS\AppData\Local\Programs\Python\Python37-32\lib\smtpl
ib.py", line 261, in __init__
fqdn = socket.getfqdn()
File "C:\Users\WINDOWS\AppData\Local\Programs\Python\Python37-32\lib\socke
t.py", line 676, in getfqdn
hostname, aliases, ipaddrs = gethostbyaddr(name)
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xf0 in position 1: invalid
continuation byte
Hope you can help.

Related

How to deal with error when mails are read

The script is first doing it job
find the message with specific subject
send a message to the sender
copy the message to folder 'answered'
delete the message
sleep for 1min and repeat
mail.select()
status, messages = mail.select("INBOX")
n = int(str(messages[0], 'utf-8'))
messages = int(messages[0])
for i in range(messages, messages-n,-1):
res, msg = mail.fetch(str(i), "(RFC822)")
for response in msg:
if isinstance(response, tuple):
# parse a bytes email into a message object
msg = email.message_from_bytes(response[1])
Sub, encoding = decode_header(msg.get("Subject"))[0] # Error is about this line
Sub=Sub.decode((encoding))
if Sub == pat:
fro, encoding = decode_header(msg.get("From"))[0]
if isinstance(fro, bytes):
fro = fro.decode(encoding)
# if s == 0:
# time.sleep(60)
# mai_load(1)
print("From:", fro)
send_mail(fro)
mail.copy(str(i), 'praca')
mail.store(str(i), '+FLAGS', '\\Deleted')
print("=" * 100)
time.sleep(60)
mai_load(0)
And here is the problem, messages are mark as read and when the scripts connects again I'm receiving an error:
line 99, in mai_load
Sub, encoding = decode_header(msg.get("Subject"))[0]
File "/usr/lib/python3.8/email/header.py", line 80, in decode_header
if not ecre.search(header):
TypeError: expected string or bytes-like object
Try my lib: https://github.com/ikvk/imap_tools
from imap_tools import MailBox, AND, MailMessageFlags
with MailBox('imap.mail.com').login('test#mail.com', 'pwd', 'INBOX') as mailbox:
# get list of email senders from INBOX folder
senders = [msg.from_ for msg in mailbox.fetch()]
# FLAG unseen messages in current folder (INBOX) as Flagged
mailbox.flag(mailbox.fetch(AND(seen=False)), [MailMessageFlags.FLAGGED], True)

how to fix output error in emailcheck python script

iam trying to use a python script to do listener on gmail to get incoming emails with spicific criteria so far everything work well the script so listener and wait for the expected emai but when the email is recived i goten the following error any help will be welcome iam too beginer . already thanks.
the script used:
import time
from itertools import chain
import email
import imaplib
imap_ssl_host = 'imap.gmail.com' # imap.mail.yahoo.com
imap_ssl_port = 993
username = 'USERNAME or EMAIL ADDRESS'
password = 'PASSWORD'
# Restrict mail search. Be very specific.
# Machine should be very selective to receive messages.
criteria = {
'FROM': 'PRIVILEGED EMAIL ADDRESS',
'SUBJECT': 'SPECIAL SUBJECT LINE',
'BODY': 'SECRET SIGNATURE',
}
uid_max = 0
def search_string(uid_max, criteria):
c = list(map(lambda t: (t[0], '"'+str(t[1])+'"'), criteria.items())) + [('UID', '%d:*' % (uid_max+1))]
return '(%s)' % ' '.join(chain(*c))
# Produce search string in IMAP format:
# e.g. (FROM "me#gmail.com" SUBJECT "abcde" BODY "123456789" UID 9999:*)
def get_first_text_block(msg):
type = msg.get_content_maintype()
if type == 'multipart':
for part in msg.get_payload():
if part.get_content_maintype() == 'text':
return part.get_payload()
elif type == 'text':
return msg.get_payload()
server = imaplib.IMAP4_SSL(imap_ssl_host, imap_ssl_port)
server.login(username, password)
server.select('INBOX')
result, data = server.uid('search', None, search_string(uid_max, criteria))
uids = [int(s) for s in data[0].split()]
if uids:
uid_max = max(uids)
# Initialize `uid_max`. Any UID less than or equal to `uid_max` will be ignored subsequently.
server.logout()
# Keep checking messages ...
# I don't like using IDLE because Yahoo does not support it.
while 1:
# Have to login/logout each time because that's the only way to get fresh results.
server = imaplib.IMAP4_SSL(imap_ssl_host, imap_ssl_port)
server.login(username, password)
server.select('INBOX')
result, data = server.uid('search', None, search_string(uid_max, criteria))
uids = [int(s) for s in data[0].split()]
for uid in uids:
# Have to check again because Gmail sometimes does not obey UID criterion.
if uid > uid_max:
result, data = server.uid('fetch', uid, '(RFC822)') # fetch entire message
msg = email.message_from_string(data[0][1])
uid_max = uid
text = get_first_text_block(msg)
print 'New message :::::::::::::::::::::'
print text
server.logout()
time.sleep(1)
the result:
C:\Users\PC Sony>"C:/Users/PC Sony/AppData/Local/Programs/Python/Python38/python.exe" "c:/Users/PC Sony/Desktop/elzero/elzero/# import PySimpleGUI.py"
Traceback (most recent call last):
File "c:/Users/PC Sony/Desktop/elzero/elzero/# import PySimpleGUI.py", line 68, in <module>
result, data = server.uid('fetch', uid, '(RFC822)') # fetch entire message
File "C:\Users\PC Sony\AppData\Local\Programs\Python\Python38\lib\imaplib.py", line 881, in uid
typ, dat = self._simple_command(name, command, *args)
File "C:\Users\PC Sony\AppData\Local\Programs\Python\Python38\lib\imaplib.py", line 1205, in _simple_command
return self._command_complete(name, self._command(name, *args))
File "C:\Users\PC Sony\AppData\Local\Programs\Python\Python38\lib\imaplib.py", line 963, in _command
data = data + b' ' + arg
TypeError: can't concat int to bytes
result, data = server.uid('fetch', uid, '(RFC822)')
should be changed to
result, data = server.uid('fetch', str(uid), '(RFC822)')
arguments should be of type string or bytes.
source code in imaplib.py
for arg in args:
if arg is None: continue
if isinstance(arg, str):
arg = bytes(arg, "ASCII")
data = data + b' ' + arg

How can I make this python2 function that reads emails run in python3?

I've been following the guide here on how to read emails in python
https://codehandbook.org/how-to-read-email-from-gmail-using-python/
import smtplib
import time
import imaplib
import email
ORG_EMAIL = "#gmail.com"
FROM_EMAIL = "mygmail" + ORG_EMAIL
FROM_PWD = "mypassword"
SMTP_SERVER = "imap.gmail.com"
SMTP_PORT = 993
def read_email_from_gmail():
mail = imaplib.IMAP4_SSL(SMTP_SERVER)
mail.login(FROM_EMAIL,FROM_PWD)
mail.select('inbox')
type, data = mail.search(None, 'ALL')
mail_ids = data[0]
id_list = mail_ids.split()
first_email_id = int(id_list[0])
latest_email_id = int(id_list[-1])
for i in range(latest_email_id,first_email_id, -1):
typ, data = mail.fetch(i, '(RFC822)' )
for response_part in data:
if isinstance(response_part, tuple):
msg = email.message_from_string(response_part[1])
email_subject = msg['subject']
email_from = msg['from']
print('From : ' + email_from + '\n')
print('Subject : ' + email_subject + '\n')
This code was made for python2 and running it with python2 works perfectly, but I would like to work with python3 and so i tried to translate the code. Firstly, I changed all the instances of print foobar to print(foobar).
However Im getting the error 'TypeError: can't concat bytes to int'
Traceback (most recent call last):
File "mymail.py", line 37, in <module>
read_email_from_gmail()
File "mymail.py", line 26, in read_email_from_gmail
typ, data = mail.fetch(i, '(RFC822)' )
File "/usr/lib/python3.5/imaplib.py", line 518, in fetch
typ, dat = self._simple_command(name, message_set, message_parts)
File "/usr/lib/python3.5/imaplib.py", line 1180, in _simple_command
return self._command_complete(name, self._command(name, *args))
File "/usr/lib/python3.5/imaplib.py", line 945, in _command
data = data + b' ' + arg
TypeError: can't concat bytes to int
I'm not too familiar with this error. But using the original code from the text in python2 works perfectly with no issues. I kind of understand the error it's saying it can't concatenate bytes with numerics. However Im not sure why this error would occur going from python2 to python3.

How can i download a gmail attachment based on subject? ERROR : "No route to host" when connecting to imap.gmail.com

This is my first python code, so please excuse me.
This is what i wrote.
import imaplib
import email
import os
import getpass
email = 'br******#******.com'
password = getpass.getpass('Enter your password: ')
mail = 'imap.gmail.com'
flag = '(RFC822)'
svdir = 'c:/Users/'
m = imaplib.IMAP4(mail)
m.login(email,password)
m.select('inbox')
typ, msgs = m.search(None, 'subject:resume has:attachment')
msgs = msgs[0].split()
for emailid in msgs:
resp, data = m.fetch(emailid, "(RFC822)")
email_body = data[0][1]
mail = email.message_from_string(email_body)
if mail.get_content_maintype() != 'multipart':
continue
for part in mail.walk():
if part.get_content_maintype() == 'multipart':
continue
if part.get('Content-Disposition') is None:
continue
filename=part.get_filename()
if filename is not None:
sv_path = os.path.join(svdir, filename)
if not os.path.isfile(sv_path):
print (sv_path)
fp = open(sv_path, 'wb')
fp.write(part.get_payload(decode=True))
fp.close()
But i'm getting this as error.
Traceback (most recent call last):
File "/Users/Documents/Fetch_Attchments.py", line 12, in <module>
m = imaplib.IMAP4(mail)
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/imaplib.py", line 197, in __init__
self.open(host, port)
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/imaplib.py", line 294, in open
self.sock = self._create_socket()
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/imaplib.py", line 284, in _create_socket
return socket.create_connection((self.host, self.port))
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/socket.py", line 711, in create_connection
raise err
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/socket.py", line 702, in create_connection
sock.connect(sa)
OSError: [Errno 65] No route to host
I filtering messages by subject and getting the attachment saved to particular location. Kindly note that the subject condition will filter only one message.
Gmail does not allow connecting on a plain text port. SSL/TLS is required.
You will need:
m = imaplib.IMAP4_SSL("imap.gmail.com", 993)

How to search specific e-mail using python imaplib.IMAP4.search()

import imaplib,time
T=time.time()
M=imaplib.IMAP4_SSL("imap.gmail.com")
M.login(user,psw)
M.select()
typ, data = M.search(None, 'UNSEEN SINCE T')
for num in string.split(data[0]):
try :
typ, data=M.fetch(num,'(RFC822)')
msg=email.message_from_string(data[0][1])
print msg["From"]
print msg["Subject"]
print msg["Date"]
except Exception,e:
print "hello world"
M.close()
M.logout()
ERROR:
Traceback (most recent call last):
File "mail.py", line 37, in <module>
typ, data = M.search(None, 'UNSEEN SINCE T')
File "/usr/lib/python2.7/imaplib.py", line 627, in search
typ, dat = self._simple_command(name, *criteria)
File "/usr/lib/python2.7/imaplib.py", line 1070, in _simple_command
return self._command_complete(name, self._command(name, *args))
File "/usr/lib/python2.7/imaplib.py", line 905, in _command_complete
raise self.error('%s command error: %s %s' % (name, typ, data))
imaplib.error: SEARCH command error: BAD ['Parse command error']
I want to search e-mail since a specific time . Here is my code .But it runs error.Can you give me some advice on how to solve it.thanks a lot!
import imaplib
mail = imaplib.IMAP4_SSL('imap.gmail.com')
mail.login('test#gmail.com', 'test')
mail.list()
# Out: list of "folders" aka labels in gmail.
mail.select("inbox") # connect to inbox.
result, data = mail.search(None, '(FROM "anjali sinha" SUBJECT "test")' )
ids = data[0] # data is a list.
id_list = ids.split() # ids is a space separated string
latest_email_id = id_list[-1] # get the latest
result, data = mail.fetch(latest_email_id, "(RFC822)") # fetch the email body (RFC822) for the given ID
raw_email = data[0][1] # here's the body, which is raw text of the whole email
# including headers and alternate payloads
print raw_email
this eventually worked for me
specyfing labels with conditions
UPDATE: OP has imported imaplib but it's still generating an error message which has not been put into the question.
--
This won't work because you have not imported imaplib.
Try
import smtplib, time, imaplib
instead of
import smtplib, time

Categories

Resources