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)
Related
I am using azure communication services in my react app to send email.
But I want to send bulk messages via a text file or an excel file
import time
from azure.communication.email import EmailClient, EmailContent, EmailAddress, EmailMessage, EmailRecipients
def main():
try:
connection_string = "<ACS_CONNECTION_STRING>"
client = EmailClient.from_connection_string(connection_string)
sender = "<SENDER_EMAIL>"
content = EmailContent(
subject="Test email from Python",
plain_text="This is plaintext body of test email.",
html= "<html><h1>This is the html body of test email.</h1></html>",
)
recipient = EmailAddress(email="<RECIPIENT_EMAIL>", display_name="<RECIPIENT_DISPLAY_NAME>")
message = EmailMessage(
sender=sender,
content=content,
recipients=EmailRecipients(to=[recipient])
)
response = client.send(message)
if (not response or response.message_id=='undefined' or response.message_id==''):
print("Message Id not found.")
else:
print("Send email succeeded for message_id :"+ response.message_id)
message_id = response.message_id
counter = 0
while True:
counter+=1
send_status = client.get_send_status(message_id)
if (send_status):
print(f"Email status for message_id {message_id} is {send_status.status}.")
if (send_status.status.lower() == "queued" and counter < 12):
time.sleep(10) # wait for 10 seconds before checking next time.
counter +=1
else:
if(send_status.status.lower() == "outfordelivery"):
print(f"Email delivered for message_id {message_id}.")
break
else:
print("Looks like we timed out for checking email send status.")
break
except Exception as ex:
print(ex)
main()
How to solve this issue?
I tried to get emails from a text file, but it failed for me
I want the script response for email with specific Subject and then delete that email.
The script is doing one job which is responding to the email but I'm struggling with deleting that email, I'm not sure if I'm doing it even correctly: mail.store(response[1], '+FLAGS', '\Deleted') gives an error: imaplib.error: STORE command error: BAD [b'Could not parse command']
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]
if isinstance(Sub, bytes): # check the subject
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(180)
mai_load(1)
print("From:", fro)
send_mail(fro)
mail.store(response[1], '+FLAGS', '\\Deleted')
print("=" * 100)
Solution:
had to change one line:
mail.store(response[1], '+FLAGS', '\\Deleted')
to
mail.store(str(i), '+FLAGS', '\\Deleted')
I'm unable to find ANY code that will function to retrieve Gmail.
import poplib
from email import parser
SERVER = "pop.gmail.com"
USER = "user#gmail.com"
PASSWORD = "password"
pop_conn = poplib.POP3_SSL(SERVER)
pop_conn.user(USER)
pop_conn.pass_(PASSWORD)
#Get messages from server:
messages = [pop_conn.retr(i) for i in range(1, len(pop_conn.list()[1]) + 1)]
# Concat message pieces:
messages = ["\n".join(mssg[1]) for mssg in messages]
#Parse message intom an email object:
messages = [parser.Parser().parsestr(mssg) for mssg in messages]
for message in messages:
print(message['subject'])
print(message['body'])
This produces only:
TypeError Traceback (most recent call last)
<ipython-input-8-e557fa99ae8d> in ()
12 messages = [pop_conn.retr(i) for i in range(1, len(pop_conn.list()[1]) + 1)]
13 # Concat message pieces:
---> 14 messages = ["\n".join(mssg[1]) for mssg in messages]
15 #Parse message intom an email object:
16 messages = [parser.Parser().parsestr(mssg) for mssg in messages]
<ipython-input-8-e557fa99ae8d> in (.0)
12 messages = [pop_conn.retr(i) for i in range(1, len(pop_conn.list()[1]) + 1)]
13 # Concat message pieces:
---> 14 messages = ["\n".join(mssg[1]) for mssg in messages]
15 #Parse message intom an email object:
16 messages = [parser.Parser().parsestr(mssg) for mssg in messages]
TypeError: sequence item 0: expected str instance, bytes found
I'VE SPENT DAYS trying to do a "simple" e-mail retrieve, and EVERY scrap of code I've found is totally non-functional.
Can anyone actually get Gmail, with subjects, etc?
This code is incomplete but may help you.
source: https://www.code-learner.com/python-use-pop3-to-read-email-example/
import poplib
import smtplib, ssl
# input email address, password and pop3 server domain or ip address
email = 'yourgmail#gmail.com'
password = 'password'
# connect to pop3 server:
server = poplib.POP3_SSL('pop.gmail.com')
# open debug switch to print debug information between client and pop3 server.
server.set_debuglevel(1)
# get pop3 server welcome message.
pop3_server_welcome_msg = server.getwelcome().decode('utf-8')
# print out the pop3 server welcome message.
print(server.getwelcome().decode('utf-8'))
# user account authentication
server.user(email)
server.pass_(password)
# stat() function return email count and occupied disk size
print('Messages: %s. Size: %s' % server.stat())
# list() function return all email list
resp, mails, octets = server.list()
print(mails)
# retrieve the newest email index number
index = len(mails)
# server.retr function can get the contents of the email with index variable value index number.
resp, lines, octets = server.retr(index)
# lines stores each line of the original text of the message
# so that you can get the original text of the entire message use the join function and lines variable.
msg_content = b'\r\n'.join(lines).decode('utf-8')
# now parse out the email object.
from email.parser import Parser
from email.header import decode_header
from email.utils import parseaddr
import poplib
# parse the email content to a message object.
msg = Parser().parsestr(msg_content)
# get email from, to, subject attribute value.
email_from = msg.get('From')
email_to = msg.get('To')
email_subject = msg.get('Subject')
print('From ' + email_from)
print('To ' + email_to)
print('Subject ' + email_subject)
# delete the email from pop3 server directly by email index.
# server.dele(index)
# close pop3 server connection.
server.quit()
My email program is emailing each line of the message as a separate email, i would like to know how to send all of the message in one email, when the email is sent the program will return to the beginning.
import smtplib
from email.mime.text import MIMEText
a = 1
while a == 1:
print " "
To = raw_input("To: ")
subject = raw_input("subject: ")
input_list = []
print "message: "
while True:
input_str = raw_input(">")
if input_str == "." and input_list[-1] == "":
break
else:
input_list.append(input_str)
for line in input_list:
# Create a MIME text message and populate its values
msg = MIMEText(line)
msg['Subject'] = subject
msg['From'] = '123#example.com'
msg['To'] = To
server = smtplib.SMTP_SSL('server', 465)
server.ehlo()
server.set_debuglevel(1)
server.ehlo()
server.login('username', 'password')
# Send a properly formatted MIME message, rather than a raw string
server.sendmail('user#example.net', To, msg.as_string())
server.close()
(the part that takes multiple lines was made with the help Paul Griffiths, Multiline user input python)
for line in input_list:
# Create a MIME text message and populate its values
msg = MIMEText(line)
You are calling server.sendmail in this loop.
Build your entire msg first (in a loop), THEN add all of your headers and send your message.
I'm trying to save email attachment from Google mail account.
AFAIK, it can be done 'walking' the message and getting its payload,
for part in message.walk():
# getting payload, saving attach etc.
but it does not work.
See the whole example below:
def test_save_attach(self):
self.connection = poplib.POP3_SSL('pop.gmail.com', 995)
self.connection.set_debuglevel(1)
self.connection.user(USERNAME)
self.connection.pass_(PASS)
emails, total_bytes = self.connection.stat()
print("{0} emails in the inbox, {1} bytes total".format(emails, total_bytes))
# return in format: (response, ['mesg_num octets', ...], octets)
msg_list = self.connection.list()
print(msg_list)
# messages processing
for i in range(emails):
response = self.connection.retr(i+1)
# return in format: (response, ['line', ...], octets)
lines = response[1]
str_message = email.message_from_bytes(b''.join(lines))
print(str_message)
# save attach
for part in str_message.walk():
print(part.get_content_type())
if part.get_content_maintype() == 'multipart':
continue
if part.get('Content-Disposition') is None:
continue
filename = part.get_filename()
if not(filename): continue
fp = open(os.path.join(self.savedir, filename), 'wb')
fp.write(part.get_payload(decode=1))
fp.close
self.connection.quit()
Script output is:
*cmd* 'USER **********'
*cmd* 'PASS **********'
*cmd* 'STAT'
*stat* [b'+OK', b'1', b'5301']
1 emails in the inbox, 5301 bytes total
*cmd* 'LIST'
(b'+OK 1 messages (5301 bytes)', [b'1 5301'], 8)
*cmd* 'RETR 1'
[<message headers and body>]
text/plain
*cmd* 'QUIT'
As we can see, the only part of the message has 'text/plain' format and does not contain any attach information, although the message body defenitely contains it and it can be seen while debug output.
response = self.connection.retr(i+1)
raw_message = response[1]
raw_message is not a string. retr returns the message as a list of single lines. you are trying to convert the list into a string with str(raw_message) - that doesn't work.
instead, join these lines together, eg, replace
str_message = email.message_from_string(str(raw_message))
with:
python2:
str_message = email.message_from_string("\n".join(raw_message))
python3:
str_message = email.message_from_bytes(b'\n'.join(raw_message))
edit:// adding my full working source and output to help debug the problem
import poplib
import email
import os
class GmailTest(object):
def __init__(self):
self.savedir="/tmp"
def test_save_attach(self):
self.connection = poplib.POP3_SSL('pop.gmail.com', 995)
self.connection.set_debuglevel(1)
self.connection.user("<munged>")
self.connection.pass_("<munged>")
emails, total_bytes = self.connection.stat()
print("{0} emails in the inbox, {1} bytes total".format(emails, total_bytes))
# return in format: (response, ['mesg_num octets', ...], octets)
msg_list = self.connection.list()
print(msg_list)
# messages processing
for i in range(emails):
# return in format: (response, ['line', ...], octets)
response = self.connection.retr(i+1)
raw_message = response[1]
str_message = email.message_from_bytes(b'\n'.join(raw_message))
# save attach
for part in str_message.walk():
print(part.get_content_type())
if part.get_content_maintype() == 'multipart':
continue
if part.get('Content-Disposition') is None:
print("no content dispo")
continue
filename = part.get_filename()
if not(filename): filename = "test.txt"
print(filename)
fp = open(os.path.join(self.savedir, filename), 'wb')
fp.write(part.get_payload(decode=1))
fp.close
#I exit here instead of pop3lib quit to make sure the message doesn't get removed in gmail
import sys
sys.exit(0)
d=GmailTest()
d.test_save_attach()
output:
python3 thetest.py
*cmd* 'USER <munged>'
*cmd* 'PASS <munged>'
*cmd* 'STAT'
*stat* [b'+OK', b'2', b'152928']
2 emails in the inbox, 152928 bytes total
*cmd* 'LIST'
(b'+OK 2 messages (152928 bytes)', [b'1 76469', b'2 76459'], 18)
*cmd* 'RETR 1'
multipart/mixed
text/plain
test.txt
application/pdf
ADDFILE_0.pdf
*cmd* 'RETR 2'
multipart/mixed
text/plain
test.txt
application/pdf
ADDFILE_0.pdf