emailresponding / Email_Reader /email_reader.py
khalidsabri's picture
first changes
c10dac6
import imaplib
import email
import pandas as pd
from email.header import decode_header
import smtplib
import logging
class EmailReader:
"""
Class to read and process emails using IMAP.
"""
def __init__(self, imap_url, email_user, email_pass):
"""
Initialize the EmailReader object.
Args:
imap_url (str): IMAP server URL.
email_user (str): Email username.
email_pass (str): Email password.
"""
self.imap_url = 'imap.mail.yahoo.com'
self.email_user = email_user
self.email_pass = email_pass
self.mail = None
self.df = pd.DataFrame(columns=['Email ID', 'Message ID', 'From', 'Subject', 'Body'])
def connect(self):
"""
Connect to the IMAP server.
"""
try:
self.mail = imaplib.IMAP4_SSL(self.imap_url,port=993)
except imaplib.IMAP4.error as e:
logging.error(f"Failed to connect to IMAP server: {e}")
raise ConnectionError(f"Failed to connect to IMAP server: {e}")
def login(self):
"""
Login to the email account.
"""
try:
self.mail.login(self.email_user, self.email_pass)
except imaplib.IMAP4.error as e:
logging.error(f"Login failed: {e}")
raise ConnectionError(f"Login failed: {e}")
def fetch_unseen_emails(self):
"""
Fetch unseen emails and process them.
"""
try:
self.mail.select('inbox')
status, messages = self.mail.search(None, 'ALL')
if status == 'OK':
for num in messages[0].split():
status, data = self.mail.fetch(num, '(RFC822)')
if status == 'OK':
msg = email.message_from_bytes(data[0][1])
self.process_email(msg, num)
except Exception as e:
logging.error(f"Error fetching emails: {e}")
raise Exception(f"Error fetching emails: {e}")
def process_email(self, msg, email_id):
"""
Process the email and add it to the DataFrame.
Args:
msg (email.message.Message): Email message.
email_id (bytes): Email ID.
"""
try:
message_id = msg.get('Message-ID')
subject = decode_header(msg['subject'])[0][0]
if isinstance(subject, bytes):
subject = subject.decode()
from_ = msg.get('from')
body = self.get_email_body(msg)
self.df = self.df._append({'Email ID': email_id.decode(), 'Message ID': message_id, 'From': from_, 'Subject': subject, 'Body': body}, ignore_index=True)
except Exception as e:
logging.error(f"Error processing email: {e}")
raise Exception(f"Error processing email: {e}")
def get_email_body(self, msg):
"""
Get the body of the email.
Args:
msg (email.message.Message): Email message.
Returns:
str: Email body.
"""
body = ""
try:
if msg.is_multipart():
for part in msg.walk():
if part.get_content_maintype() == 'text':
body = part.get_payload(decode=True)
if body is not None:
body = body.decode()
break
else:
body = msg.get_payload(decode=True)
if body is not None:
body = body.decode()
except Exception as e:
logging.error(f"Error getting email body: {e}")
return body
def save_emails_to_excel(self, filename):
"""
Save emails to an Excel file.
Args:
filename (str): Name of the Excel file.
"""
try:
self.df.to_excel(filename, index=False)
except Exception as e:
logging.error(f"Error saving emails to Excel: {e}")
raise Exception(f"Error saving emails to Excel: {e}")
def close_connection(self):
"""
Close the IMAP connection.
"""
try:
self.mail.close()
self.mail.logout()
except Exception as e:
logging.error(f"Error closing connection: {e}")
print(f"Error closing connection: {e}")
def reply_to_email(self, msg_id, reply_body):
"""
Reply to an email.
Args:
msg_id (str): Message ID of the email to reply to.
reply_body (str): Body of the reply.
Returns:
str: Status message.
"""
try:
self.mail.select('inbox')
result, data = self.mail.search(None, f'(HEADER Message-ID "{msg_id}")')
if result == 'OK':
email_ids = data[0].split()
latest_email_id = email_ids[-1]
result, data = self.mail.fetch(latest_email_id, '(RFC822)')
if result == 'OK':
raw_email = data[0][1]
email_message = email.message_from_bytes(raw_email)
reply = email.message.EmailMessage()
reply['Subject'] = 'Re: ' + email_message['Subject']
reply['To'] = email_message['Reply-To'] or email_message['From']
reply['From'] = self.email_user
reply.set_content(reply_body)
with smtplib.SMTP('smtp-mail.outlook.com', 587) as smtp:
smtp.ehlo()
smtp.starttls()
smtp.ehlo()
smtp.login(self.email_user, self.email_pass)
smtp.send_message(reply)
return "Reply sent successfully."
else:
return "Failed to fetch the email."
else:
return "Email not found."
except Exception as e:
logging.error(f"Error in sending email: {e}")
raise Exception(f"Error in sending email: {e}")