AIEmailAutomationUtility 0.0.1__py3-none-any.whl → 0.0.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- AIEmailAutomationUtility/EmailReplyAssistant.py +67 -0
- AIEmailAutomationUtility/{Email_Drafter.py → Email_Draft.py} +1 -1
- AIEmailAutomationUtility/Email_Read.py +80 -50
- AIEmailAutomationUtility/__init__.py +3 -1
- {AIEmailAutomationUtility-0.0.1.dist-info → AIEmailAutomationUtility-0.0.3.dist-info}/METADATA +3 -3
- AIEmailAutomationUtility-0.0.3.dist-info/RECORD +11 -0
- AIEmailAutomationUtility-0.0.1.dist-info/RECORD +0 -10
- {AIEmailAutomationUtility-0.0.1.dist-info → AIEmailAutomationUtility-0.0.3.dist-info}/LICENCE.txt +0 -0
- {AIEmailAutomationUtility-0.0.1.dist-info → AIEmailAutomationUtility-0.0.3.dist-info}/WHEEL +0 -0
- {AIEmailAutomationUtility-0.0.1.dist-info → AIEmailAutomationUtility-0.0.3.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,67 @@
|
|
1
|
+
import traceback
|
2
|
+
from openai import OpenAI
|
3
|
+
from openai import OpenAI, AssistantEventHandler
|
4
|
+
|
5
|
+
class EmailReplyAssistant:
|
6
|
+
def __init__(self):
|
7
|
+
pass
|
8
|
+
|
9
|
+
def Reply_Email_Ai_Assistant(self, openAI_key, assistant_ID, email_content, subject, signature):
|
10
|
+
try:
|
11
|
+
class EventHandler(AssistantEventHandler):
|
12
|
+
def __init__(self):
|
13
|
+
super().__init__()
|
14
|
+
self.delta_values = []
|
15
|
+
|
16
|
+
def on_text_created(self, text):
|
17
|
+
if isinstance(text, str):
|
18
|
+
print(f"\nAssistant: {text}", end="", flush=True)
|
19
|
+
|
20
|
+
def on_text_delta(self, delta, snapshot):
|
21
|
+
self.delta_values.append(delta.value)
|
22
|
+
|
23
|
+
def on_tool_call_created(self, tool_call):
|
24
|
+
print(f"\nAssistant: {tool_call.type}\n", flush=True)
|
25
|
+
|
26
|
+
def on_tool_call_delta(self, delta, snapshot):
|
27
|
+
if delta.type == 'code_interpreter':
|
28
|
+
if delta.code_interpreter.input:
|
29
|
+
print(delta.code_interpreter.input, end="", flush=True)
|
30
|
+
if delta.code_interpreter.outputs:
|
31
|
+
print(f"\n\nOutput >", flush=True)
|
32
|
+
for output in delta.code_interpreter.outputs:
|
33
|
+
if output.type == "logs":
|
34
|
+
print(output.logs, flush=True)
|
35
|
+
|
36
|
+
openAI_response = ""
|
37
|
+
client = OpenAI(api_key=openAI_key)
|
38
|
+
thread = client.beta.threads.create()
|
39
|
+
|
40
|
+
client.beta.threads.messages.create(
|
41
|
+
thread_id=thread.id,
|
42
|
+
role="user",
|
43
|
+
content=f"subject:{subject}\nemail body:{email_content}",
|
44
|
+
)
|
45
|
+
|
46
|
+
event_handler = EventHandler()
|
47
|
+
|
48
|
+
with client.beta.threads.runs.stream(
|
49
|
+
thread_id=thread.id,
|
50
|
+
assistant_id=assistant_ID,
|
51
|
+
instructions=f"Create a reply for the email received from a customer. Include the email signature as {signature}\nDo not include any instruction as the output will be directly in a program.",
|
52
|
+
event_handler=event_handler,
|
53
|
+
) as stream:
|
54
|
+
stream.until_done()
|
55
|
+
|
56
|
+
delta_values = event_handler.delta_values
|
57
|
+
openAI_response = ''.join(delta_values)
|
58
|
+
return openAI_response
|
59
|
+
|
60
|
+
except Exception as error:
|
61
|
+
responseStr = "<br/><br/>" + str(error)
|
62
|
+
trace = traceback.format_exc()
|
63
|
+
print(f"Exception in process_Email: {responseStr} \n {trace} \n DataType ::: {type(responseStr)}")
|
64
|
+
self.send_response(200)
|
65
|
+
self.send_header('Content-type', 'text/html')
|
66
|
+
self.end_headers()
|
67
|
+
self.wfile.write(responseStr.encode('utf-8'))
|
@@ -6,7 +6,7 @@ import time
|
|
6
6
|
import loggerutility as logger
|
7
7
|
|
8
8
|
|
9
|
-
class
|
9
|
+
class Email_Draft:
|
10
10
|
def draft_email(self, email_config, email_details, response_content):
|
11
11
|
try:
|
12
12
|
with imaplib.IMAP4_SSL(host=email_config['host'], port=imaplib.IMAP4_SSL_PORT) as imap_ssl:
|
@@ -1,69 +1,61 @@
|
|
1
1
|
import imaplib
|
2
2
|
import email
|
3
3
|
import loggerutility as logger
|
4
|
-
|
4
|
+
from flask import Flask,request
|
5
|
+
import json
|
6
|
+
import time
|
5
7
|
|
6
8
|
|
7
9
|
class Email_Read:
|
8
10
|
def read_email(self, email_config):
|
9
|
-
"""
|
10
|
-
Reads emails from the inbox and returns relevant details
|
11
|
-
|
12
|
-
Args:
|
13
|
-
email_config (dict): Contains email configuration details
|
14
|
-
- host: IMAP host server
|
15
|
-
- port: IMAP port
|
16
|
-
- email: Email address
|
17
|
-
- password: Email password
|
18
|
-
|
19
|
-
Returns:
|
20
|
-
list: List of dictionaries containing email details
|
21
|
-
"""
|
22
11
|
try:
|
23
12
|
mail = imaplib.IMAP4_SSL(email_config['host'], email_config['port'])
|
24
13
|
mail.login(email_config['email'], email_config['password'])
|
25
14
|
logger.log("login successfully")
|
26
15
|
mail.select('inbox')
|
27
16
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
if status == 'OK':
|
33
|
-
email_ids = email_ids[0].split()
|
17
|
+
while True:
|
18
|
+
status, email_ids = mail.search(None, 'UNSEEN')
|
19
|
+
emails = []
|
34
20
|
|
35
|
-
|
36
|
-
|
37
|
-
|
21
|
+
if status == 'OK':
|
22
|
+
email_ids = email_ids[0].split()
|
23
|
+
|
24
|
+
if not email_ids:
|
25
|
+
logger.log("Email not found, going to check new mail")
|
26
|
+
else:
|
38
27
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
sender_email = msg['From']
|
44
|
-
cc_email = msg['CC']
|
45
|
-
bcc_email = msg['BCC']
|
46
|
-
subject = msg['Subject']
|
47
|
-
|
48
|
-
# Extract email body
|
49
|
-
if msg.is_multipart():
|
50
|
-
for part in msg.walk():
|
51
|
-
if part.get_content_type() == "text/plain":
|
52
|
-
email_body += part.get_payload(decode=True).decode()
|
53
|
-
else:
|
54
|
-
email_body = msg.get_payload(decode=True).decode()
|
28
|
+
for email_id in email_ids:
|
29
|
+
email_body = ""
|
30
|
+
status, data = mail.fetch(email_id, '(RFC822)')
|
55
31
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
32
|
+
if status == 'OK':
|
33
|
+
raw_email = data[0][1]
|
34
|
+
msg = email.message_from_bytes(raw_email)
|
35
|
+
|
36
|
+
sender_email = msg['From']
|
37
|
+
cc_email = msg['CC']
|
38
|
+
bcc_email = msg['BCC']
|
39
|
+
subject = msg['Subject']
|
40
|
+
|
41
|
+
if msg.is_multipart():
|
42
|
+
for part in msg.walk():
|
43
|
+
if part.get_content_type() == "text/plain":
|
44
|
+
email_body += part.get_payload(decode=True).decode()
|
45
|
+
else:
|
46
|
+
email_body = msg.get_payload(decode=True).decode()
|
47
|
+
|
48
|
+
emails.append({
|
49
|
+
'id': email_id,
|
50
|
+
'sender': sender_email,
|
51
|
+
'cc': cc_email,
|
52
|
+
'bcc': bcc_email,
|
53
|
+
'subject': subject,
|
54
|
+
'body': email_body
|
55
|
+
})
|
56
|
+
logger.log(f"emails:: {emails}")
|
57
|
+
time.sleep(10)
|
58
|
+
|
67
59
|
except Exception as e:
|
68
60
|
logger.log(f"Error reading emails: {str(e)}")
|
69
61
|
raise
|
@@ -73,3 +65,41 @@ class Email_Read:
|
|
73
65
|
mail.logout()
|
74
66
|
except:
|
75
67
|
pass
|
68
|
+
|
69
|
+
def Read_Email(self):
|
70
|
+
try:
|
71
|
+
# while True:
|
72
|
+
data = request.get_data('jsonData', None)
|
73
|
+
data = json.loads(data[9:])
|
74
|
+
logger.log(f"jsondata:: {data}")
|
75
|
+
|
76
|
+
reciever_email_addr = data.get("reciever_email_addr")
|
77
|
+
receiver_email_pwd = data.get("receiver_email_pwd")
|
78
|
+
host = data.get("host")
|
79
|
+
port = data.get("port")
|
80
|
+
|
81
|
+
if not all([reciever_email_addr, receiver_email_pwd, host, port]):
|
82
|
+
raise ValueError("Missing required email configuration fields.")
|
83
|
+
|
84
|
+
logger.log(f"\nReceiver Email Address: {reciever_email_addr}\t{type(reciever_email_addr)}", "0")
|
85
|
+
logger.log(f"\nReceiver Email Password: {receiver_email_pwd}\t{type(receiver_email_pwd)}", "0")
|
86
|
+
logger.log(f"\nHost: {host}\t{type(host)}", "0")
|
87
|
+
logger.log(f"\nPort: {port}\t{type(port)}", "0")
|
88
|
+
|
89
|
+
email_config = {
|
90
|
+
'email': reciever_email_addr,
|
91
|
+
'password': receiver_email_pwd,
|
92
|
+
'host': host,
|
93
|
+
'port': int(port)
|
94
|
+
}
|
95
|
+
|
96
|
+
emails = self.read_email(email_config)
|
97
|
+
logger.log(f"Read_Email response: {emails}")
|
98
|
+
# return "Successfully read email"
|
99
|
+
|
100
|
+
except Exception as e:
|
101
|
+
logger.log(f"Error in Read_Email: {str(e)}")
|
102
|
+
# return "Problem in reading email"
|
103
|
+
|
104
|
+
|
105
|
+
|
@@ -1,4 +1,6 @@
|
|
1
1
|
from .Email_Read import Email_Read
|
2
2
|
from .Email_CategoryDetector import Email_CategoryDetector
|
3
|
-
from .
|
3
|
+
from .Email_Draft import Email_Draft
|
4
4
|
from .Email_DocumentUploader import Email_DocumentUploader
|
5
|
+
from .EmailReplyAssistant import EmailReplyAssistant
|
6
|
+
|
{AIEmailAutomationUtility-0.0.1.dist-info → AIEmailAutomationUtility-0.0.3.dist-info}/METADATA
RENAMED
@@ -1,7 +1,7 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: AIEmailAutomationUtility
|
3
|
-
Version: 0.0.
|
4
|
-
Summary:
|
3
|
+
Version: 0.0.3
|
4
|
+
Summary: Changed Email_read function and kept all code in this function only
|
5
5
|
Author: Proteus Technology PVT. LTD.
|
6
6
|
Author-email: <apps@baseinformation.com>
|
7
7
|
Keywords: python,first package
|
@@ -13,4 +13,4 @@ Classifier: Operating System :: MacOS :: MacOS X
|
|
13
13
|
Classifier: Operating System :: Microsoft :: Windows
|
14
14
|
License-File: LICENCE.txt
|
15
15
|
|
16
|
-
|
16
|
+
Changed Email_read function and kept all code in this function only
|
@@ -0,0 +1,11 @@
|
|
1
|
+
AIEmailAutomationUtility/EmailReplyAssistant.py,sha256=IGAf3FZh_f6qxqKnP7dq2FZFNb_0b_6an81SfPBddYE,2841
|
2
|
+
AIEmailAutomationUtility/Email_CategoryDetector.py,sha256=E2BRB57etINb1FjP6hODj7pS1Jj4UCoaCKj3Ic-N8_Y,6779
|
3
|
+
AIEmailAutomationUtility/Email_DocumentUploader.py,sha256=VAfpoH7JD6B2cYQDTatK0wzQhhjtNnoB5tpMI8h4BOU,2148
|
4
|
+
AIEmailAutomationUtility/Email_Draft.py,sha256=XIvATGaikTzJ1KAcW7h3b4TEH3DInO9j3-WYCm6G26g,1572
|
5
|
+
AIEmailAutomationUtility/Email_Read.py,sha256=H5poHx7Unv-tFl4BpUJRevIQKewdnxow38IdteOWcs4,4109
|
6
|
+
AIEmailAutomationUtility/__init__.py,sha256=1wFg_DXxwGtz34XVpEB4WhBEWNwVYHM0LNWUh5Jiowc,244
|
7
|
+
AIEmailAutomationUtility-0.0.3.dist-info/LICENCE.txt,sha256=2qX9IkEUBx0VJp1Vh9O2dsRwE-IpYId0lXDyn7OVsJ8,1073
|
8
|
+
AIEmailAutomationUtility-0.0.3.dist-info/METADATA,sha256=5dWuj49u72GY05Gr78TmGKJ68qG_L9DPterEf8dUnP0,634
|
9
|
+
AIEmailAutomationUtility-0.0.3.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
10
|
+
AIEmailAutomationUtility-0.0.3.dist-info/top_level.txt,sha256=3jTWrTUblVkaP7mpwY2UBSnrlfot5Ykpfsehyke-Uzw,25
|
11
|
+
AIEmailAutomationUtility-0.0.3.dist-info/RECORD,,
|
@@ -1,10 +0,0 @@
|
|
1
|
-
AIEmailAutomationUtility/Email_CategoryDetector.py,sha256=E2BRB57etINb1FjP6hODj7pS1Jj4UCoaCKj3Ic-N8_Y,6779
|
2
|
-
AIEmailAutomationUtility/Email_DocumentUploader.py,sha256=VAfpoH7JD6B2cYQDTatK0wzQhhjtNnoB5tpMI8h4BOU,2148
|
3
|
-
AIEmailAutomationUtility/Email_Drafter.py,sha256=YSD2tWPHyvJKqTjTuQyXbRJO_j6I7znnr5OPKG0nPGg,1574
|
4
|
-
AIEmailAutomationUtility/Email_Read.py,sha256=OfqDmyBGRgLDWNbZbl2bxaTjSa9gydaIO8R6nAuByPw,2698
|
5
|
-
AIEmailAutomationUtility/__init__.py,sha256=JpyFFoYlqLdoj9pe4AkoP_pXy5vbwAZKxEcHshuRHUg,194
|
6
|
-
AIEmailAutomationUtility-0.0.1.dist-info/LICENCE.txt,sha256=2qX9IkEUBx0VJp1Vh9O2dsRwE-IpYId0lXDyn7OVsJ8,1073
|
7
|
-
AIEmailAutomationUtility-0.0.1.dist-info/METADATA,sha256=gH3wC2s4h_Heek-D2FTPUaVEOwaHKFSOict-hFVxNVY,660
|
8
|
-
AIEmailAutomationUtility-0.0.1.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
9
|
-
AIEmailAutomationUtility-0.0.1.dist-info/top_level.txt,sha256=3jTWrTUblVkaP7mpwY2UBSnrlfot5Ykpfsehyke-Uzw,25
|
10
|
-
AIEmailAutomationUtility-0.0.1.dist-info/RECORD,,
|
{AIEmailAutomationUtility-0.0.1.dist-info → AIEmailAutomationUtility-0.0.3.dist-info}/LICENCE.txt
RENAMED
File without changes
|
File without changes
|
{AIEmailAutomationUtility-0.0.1.dist-info → AIEmailAutomationUtility-0.0.3.dist-info}/top_level.txt
RENAMED
File without changes
|