AIEmailAutomationUtility 0.0.23__py3-none-any.whl → 0.0.25__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/Email_Classification.py +1 -1
- AIEmailAutomationUtility/Email_DocumentUploader.py +2 -1
- AIEmailAutomationUtility/Email_Read.py +15 -15
- AIEmailAutomationUtility/Process_Category.py +78 -47
- {AIEmailAutomationUtility-0.0.23.dist-info → AIEmailAutomationUtility-0.0.25.dist-info}/METADATA +3 -3
- AIEmailAutomationUtility-0.0.25.dist-info/RECORD +15 -0
- AIEmailAutomationUtility-0.0.23.dist-info/RECORD +0 -15
- {AIEmailAutomationUtility-0.0.23.dist-info → AIEmailAutomationUtility-0.0.25.dist-info}/LICENCE.txt +0 -0
- {AIEmailAutomationUtility-0.0.23.dist-info → AIEmailAutomationUtility-0.0.25.dist-info}/WHEEL +0 -0
- {AIEmailAutomationUtility-0.0.23.dist-info → AIEmailAutomationUtility-0.0.25.dist-info}/top_level.txt +0 -0
@@ -18,7 +18,7 @@ class Email_Classification:
|
|
18
18
|
logger.log(f"Final GPT message for detecting category::: {message}")
|
19
19
|
client = OpenAI(api_key=openai_api_key)
|
20
20
|
result = client.chat.completions.create(
|
21
|
-
model="gpt-4.1",
|
21
|
+
model="gpt-4.1-mini",
|
22
22
|
messages=message,
|
23
23
|
temperature=0,
|
24
24
|
max_tokens=1800,
|
@@ -9,11 +9,12 @@ from datetime import datetime
|
|
9
9
|
|
10
10
|
class Email_DocumentUploader:
|
11
11
|
def upload_document(self, upload_config, file_data):
|
12
|
+
document_type = upload_config['document_type']
|
12
13
|
# try:
|
13
14
|
logger.log("inside function" )
|
14
15
|
# Create temp directory if needed
|
15
16
|
today_date = datetime.today().strftime('%Y-%m-%d')
|
16
|
-
temp_dir = os.path.join(
|
17
|
+
temp_dir = os.path.join(document_type, today_date)
|
17
18
|
|
18
19
|
# Save file temporarily
|
19
20
|
file_path = os.path.join(temp_dir, file_data['filename'])
|
@@ -149,9 +149,9 @@ class Email_Read:
|
|
149
149
|
|
150
150
|
|
151
151
|
# Extract UID
|
152
|
-
|
152
|
+
logger.log(f" the data -----{data[0][0]}")
|
153
153
|
raw_uid = data[0][0].decode() if isinstance(data[0][0], bytes) else data[0][0]
|
154
|
-
|
154
|
+
logger.log(f"the raw uid is ------- {raw_uid}")
|
155
155
|
uid_match = re.search(r'UID (\d+)', raw_uid)
|
156
156
|
uid = uid_match.group(1) if uid_match else "N/A"
|
157
157
|
|
@@ -399,57 +399,57 @@ class Email_Read:
|
|
399
399
|
extracted_info['to'] = msg.get('To')
|
400
400
|
extracted_info['from'] = msg.get('From')
|
401
401
|
extracted_info['cc'] = msg.get('Cc')
|
402
|
-
|
402
|
+
logger.log(f"To: {extracted_info['to']}, From: {extracted_info['from']}, CC: {extracted_info['cc']}")
|
403
403
|
|
404
404
|
# Extracting subject and decoding it if necessary
|
405
405
|
subject = decode_header(msg.get('Subject', ''))[0][0]
|
406
406
|
if decode_header(msg.get('Subject', ''))[0][1]:
|
407
407
|
subject = subject.decode()
|
408
408
|
extracted_info['subject'] = subject
|
409
|
-
|
409
|
+
logger.log(f"Subject: {extracted_info['subject']}")
|
410
410
|
|
411
411
|
# Extracting the body content (text or HTML)
|
412
412
|
text_body = None
|
413
413
|
html_body = None
|
414
414
|
if msg.is_multipart():
|
415
|
-
|
415
|
+
logger.log("Multipart email detected.")
|
416
416
|
for part in msg.walk():
|
417
417
|
content_type = part.get_content_type()
|
418
418
|
content_disposition = str(part.get("Content-Disposition"))
|
419
|
-
|
419
|
+
logger.log(f"Part content type: {content_type}, Content-Disposition: {content_disposition}")
|
420
420
|
|
421
421
|
if content_type == "text/plain" and "attachment" not in content_disposition:
|
422
422
|
text_body = part.get_payload(decode=True).decode()
|
423
|
-
|
423
|
+
logger.log("Text body extracted.")
|
424
424
|
elif content_type == "text/html" and "attachment" not in content_disposition:
|
425
425
|
html_body = part.get_payload(decode=True).decode()
|
426
|
-
|
426
|
+
logger.log("HTML body extracted.")
|
427
427
|
else:
|
428
428
|
if msg.get_content_type() == "text/plain":
|
429
429
|
text_body = msg.get_payload(decode=True).decode()
|
430
|
-
|
430
|
+
logger.log("Text body extracted (non-multipart) .")
|
431
431
|
elif msg.get_content_type() == "text/html":
|
432
432
|
html_body = msg.get_payload(decode=True).decode()
|
433
|
-
|
433
|
+
logger.log("HTML body extracted (non-multipart).")
|
434
434
|
|
435
435
|
extracted_info['email_body'] = text_body if text_body else html_body if html_body else None
|
436
436
|
extracted_info['is_html'] = bool(html_body)
|
437
437
|
|
438
438
|
# Extracting the date and converting it to ISO format
|
439
439
|
date_tuple = email.utils.parsedate_tz(msg.get('Date'))
|
440
|
-
|
440
|
+
logger.log(f"date tuple is {date_tuple}")
|
441
441
|
if date_tuple:
|
442
442
|
local_date = datetime.fromtimestamp(email.utils.mktime_tz(date_tuple))
|
443
443
|
extracted_info['date'] = local_date.isoformat()
|
444
|
-
|
444
|
+
logger.log(f"Date: {extracted_info['date']}")
|
445
445
|
else:
|
446
446
|
extracted_info['date'] = None
|
447
|
-
|
447
|
+
logger.log("No date found.")
|
448
448
|
|
449
449
|
# Extracting the unique ID (Message-ID)
|
450
450
|
extracted_info['unique_id'] = msg.get('Message-ID')
|
451
|
-
|
452
|
-
|
451
|
+
logger.log(f"Unique ID: {extracted_info['unique_id']}")
|
452
|
+
logger.log(f"-------------------------------The extracted info is --------------------------{extracted_info}")
|
453
453
|
|
454
454
|
return extracted_info,msg
|
455
455
|
|
@@ -8,6 +8,7 @@ import loggerutility as logger
|
|
8
8
|
from datetime import datetime
|
9
9
|
from openai import OpenAI
|
10
10
|
from fpdf import FPDF
|
11
|
+
import mimetypes
|
11
12
|
import sqlite3
|
12
13
|
import openai
|
13
14
|
import json
|
@@ -42,25 +43,25 @@ class Process_Category:
|
|
42
43
|
import_file = dataValues.get('import_file')
|
43
44
|
|
44
45
|
|
45
|
-
|
46
|
-
|
47
|
-
|
46
|
+
logger.log(f"the json datavalues of mailare ------------------------ {mail}")
|
47
|
+
logger.log(f"the json datavalues of email_id are ------------------------ {email_id}")
|
48
|
+
logger.log(f"the category is ------------------------ {category}")
|
48
49
|
|
49
50
|
if category == "Product Enquiry":
|
50
51
|
if Model_Name == "OpenAI":
|
51
52
|
action_taken = "Reply email drafted using Open_AI Model"
|
52
53
|
responseMethod, parameters = self.get_JsonArray_values(category, file_JsonArray)
|
53
|
-
|
54
|
+
logger.log(f"the repsonse method{responseMethod}")
|
54
55
|
if responseMethod == "Reply_Email_Ai_Assistant":
|
55
56
|
emailreplyassistant = EmailReplyAssistant()
|
56
57
|
openai_Response = emailreplyassistant.Reply_Email_Ai_Assistant(openai_api_key, parameters["Assistant_Id"], openai_Process_Input, subject)
|
57
58
|
logger.log(f"Process openai_Response ::: {openai_Response['message']}\n")
|
58
59
|
email_details = {"sender": sender_email_addr, "cc": cc_email_addr, "subject": subject, "body": email_body}
|
59
|
-
|
60
|
+
logger.log(f"response generated")
|
60
61
|
email_draft = Email_Draft()
|
61
62
|
status, response = email_draft.draft_email(email_config, email_details, openai_Response['message'])
|
62
63
|
logger.log(f"status ::: {status}")
|
63
|
-
|
64
|
+
logger.log(f"Email draft called")
|
64
65
|
csv_data_status = status
|
65
66
|
csv_data_response = response
|
66
67
|
else:
|
@@ -102,24 +103,36 @@ class Process_Category:
|
|
102
103
|
logger.log(f"parameters ::: {parameters}")
|
103
104
|
|
104
105
|
# Download the attachment
|
105
|
-
fileName = self.download_attachment(msg)
|
106
|
-
|
107
|
-
|
108
|
-
today_date = datetime.today().strftime('%Y-%m-%d')
|
109
|
-
order_folder = os.path.join("ORDERS", today_date)
|
106
|
+
fileName, document_type = self.download_attachment(msg)
|
107
|
+
logger.log(f"fileName 107::: {fileName}")
|
108
|
+
logger.log(f"document_type 108::: {document_type}")
|
110
109
|
|
111
110
|
if responseMethod == "Upload_Document":
|
111
|
+
# Get today's date folder path
|
112
|
+
today_date = datetime.today().strftime('%Y-%m-%d')
|
113
|
+
order_folder = os.path.join(document_type, today_date)
|
114
|
+
|
112
115
|
email_upload_document = Email_DocumentUploader()
|
113
116
|
if len(fileName) != 0:
|
114
117
|
file_path = os.path.join(order_folder, fileName) # Correct file path
|
115
118
|
|
116
119
|
with open(file_path, "rb") as file:
|
120
|
+
parameters["DOCUMENT_TYPE"] = document_type
|
121
|
+
|
122
|
+
logger.log(f"Updated Parameters ::: {parameters}")
|
117
123
|
response_status, restAPI_Result = email_upload_document.email_document_upload(file, parameters)
|
118
124
|
logger.log(f"email_upload_document_response ::: {restAPI_Result}")
|
119
125
|
else:
|
126
|
+
document_type = "Order Email"
|
127
|
+
# Get today's date folder path
|
128
|
+
today_date = datetime.today().strftime('%Y-%m-%d')
|
129
|
+
order_folder = os.path.join(document_type, today_date)
|
130
|
+
|
131
|
+
parameters["DOCUMENT_TYPE"] = document_type
|
132
|
+
logger.log(f"Updated Parameters ::: {parameters}")
|
120
133
|
new_fileName = self.create_file_from_emailBody(email_body, sender_email_addr, parameters)
|
121
134
|
new_file_path = os.path.join(order_folder, new_fileName)
|
122
|
-
|
135
|
+
|
123
136
|
with open(new_file_path, "rb") as file:
|
124
137
|
response_status, restAPI_Result = email_upload_document.email_document_upload(file, parameters)
|
125
138
|
logger.log(f"email_upload_document_response ::: {restAPI_Result}")
|
@@ -144,13 +157,13 @@ class Process_Category:
|
|
144
157
|
# Step 4: Identify customer from email using AI
|
145
158
|
customer_data = self.identify_customer(email_body, subject, Model_Name, openai_api_key, geminiAI_APIKey, localAIURL, parameters["Customer_Assistant_Id"])
|
146
159
|
logger.log(f"Identified customer: {customer_data}")
|
147
|
-
|
160
|
+
logger.log(f'This is the customer data we are getting ::: {customer_data}')
|
148
161
|
# Extract customer code once
|
149
162
|
customer_code = customer_data.get("customer_code", "")
|
150
163
|
|
151
164
|
# Step 5: Identify product from email using AI
|
152
165
|
products = self.identify_products(email_body, subject, Model_Name, openai_api_key, geminiAI_APIKey, localAIURL, parameters["Product_Assistant_Id"])
|
153
|
-
|
166
|
+
logger.log(f'this is the products data we are getting ::: {products}')
|
154
167
|
|
155
168
|
db_connection = sqlite3.connect('/home/base/git/ai-email-automation/AI_Email/database/fetchprice.db')
|
156
169
|
for product in products:
|
@@ -181,13 +194,13 @@ class Process_Category:
|
|
181
194
|
|
182
195
|
try:
|
183
196
|
raw_price = float(price_cleaned)
|
184
|
-
|
197
|
+
logger.log(f"[0] Base price for item '{item_no}' is {raw_price}")
|
185
198
|
except (TypeError, ValueError):
|
186
|
-
|
199
|
+
logger.log(f"[0] Invalid raw price for item '{item_no}': {price_result[0]}")
|
187
200
|
product["rate"] = None
|
188
201
|
continue
|
189
202
|
else:
|
190
|
-
|
203
|
+
logger.log(f"[0] No base price found for item '{item_no}'. Skipping...")
|
191
204
|
product["rate"] = None
|
192
205
|
continue
|
193
206
|
|
@@ -205,7 +218,7 @@ class Process_Category:
|
|
205
218
|
if result:
|
206
219
|
rate = result[0]
|
207
220
|
found_rate = True
|
208
|
-
|
221
|
+
logger.log(f"[1] Special Rate for item '{item_no}' and customer '{customer_code}' is {rate}")
|
209
222
|
|
210
223
|
# Condition 2: Customer + Manufacturer discount
|
211
224
|
if not found_rate:
|
@@ -219,10 +232,10 @@ class Process_Category:
|
|
219
232
|
|
220
233
|
if discount_result:
|
221
234
|
discount_percent = discount_result[0]
|
222
|
-
rate = raw_price * (1 - discount_percent / 100)
|
235
|
+
rate = raw_price * (1 - int(discount_percent) / 100)
|
223
236
|
rate = round(rate, 2)
|
224
237
|
found_rate = True
|
225
|
-
|
238
|
+
logger.log(f"[2] Discounted rate for '{make}' ({discount_percent}%) on price {raw_price}: {rate}")
|
226
239
|
|
227
240
|
# Condition 3: Past Sales most used make
|
228
241
|
if not found_rate:
|
@@ -241,14 +254,14 @@ class Process_Category:
|
|
241
254
|
if past_sales_result:
|
242
255
|
most_common_make, past_discount = past_sales_result
|
243
256
|
if isinstance(raw_price, (int, float)):
|
244
|
-
rate = raw_price * (1 - past_discount / 100)
|
257
|
+
rate = raw_price * (1 - int(past_discount) / 100)
|
245
258
|
rate = round(rate, 2)
|
246
259
|
found_rate = True
|
247
|
-
|
260
|
+
logger.log(f"[3] Fallback: Most used make '{most_common_make}' for customer '{customer_code}' got {past_discount}% discount. Rate: {rate}")
|
248
261
|
else:
|
249
|
-
|
262
|
+
logger.log(f"[3] Fallback: Invalid price for item '{item_no}'")
|
250
263
|
else:
|
251
|
-
|
264
|
+
logger.log(f"[3] No past sales data for item '{item_no}' and customer '{customer_code}'")
|
252
265
|
|
253
266
|
# Condition 4: Manufacturer General Discount
|
254
267
|
if not found_rate:
|
@@ -262,12 +275,12 @@ class Process_Category:
|
|
262
275
|
|
263
276
|
if general_discount_result:
|
264
277
|
general_discount_percent = general_discount_result[0]
|
265
|
-
rate = raw_price * (1 - general_discount_percent / 100)
|
278
|
+
rate = raw_price * (1 - int(general_discount_percent) / 100)
|
266
279
|
rate = round(rate, 2)
|
267
280
|
found_rate = True
|
268
|
-
|
281
|
+
logger.log(f"[4] General Discount for '{make}' ({general_discount_percent}%) on price {raw_price}: {rate}")
|
269
282
|
else:
|
270
|
-
|
283
|
+
logger.log(f"[4] No applicable discount found for item '{item_no}'")
|
271
284
|
|
272
285
|
product["rate"] = rate
|
273
286
|
cursor.close()
|
@@ -312,7 +325,7 @@ class Process_Category:
|
|
312
325
|
csv_data_response = f""
|
313
326
|
|
314
327
|
logger.log(f"Marking email as UNREAD. ")
|
315
|
-
|
328
|
+
logger.log(f"email_id: {email_id}, type: {type(email_id)}")
|
316
329
|
mail.store(email_id, '-FLAGS', '\\Seen')
|
317
330
|
mail.create(LABEL)
|
318
331
|
mail.copy(email_id, LABEL)
|
@@ -320,10 +333,11 @@ class Process_Category:
|
|
320
333
|
mail.expunge()
|
321
334
|
logger.log(f"Mail removed from inbox and added to '{LABEL}' label.")
|
322
335
|
|
323
|
-
|
324
|
-
|
336
|
+
current_timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
337
|
+
filename = f'{uid}{current_timestamp}'
|
338
|
+
logger.log(f"the file name is ---------------- {filename}")
|
325
339
|
self.store_email_details_to_csv(
|
326
|
-
email_id=uid,
|
340
|
+
email_id=f'{uid}{current_timestamp}',
|
327
341
|
to_email=parseaddr(to_email_addr)[1],
|
328
342
|
from_email=parseaddr(sender_email_addr)[1],
|
329
343
|
cc_email=parseaddr(cc_email_addr)[1] if cc_email_addr else '',
|
@@ -334,11 +348,11 @@ class Process_Category:
|
|
334
348
|
filename=filename,
|
335
349
|
user_id=user_id,
|
336
350
|
status=csv_data_status,
|
337
|
-
response=csv_data_response
|
338
|
-
|
351
|
+
response=csv_data_response,
|
352
|
+
current_timestamp=current_timestamp
|
339
353
|
)
|
340
354
|
self.store_email_as_eml(
|
341
|
-
uid=uid,
|
355
|
+
uid=f'{uid}{current_timestamp}',
|
342
356
|
from_email=sender_email_addr,
|
343
357
|
to_email=to_email_addr,
|
344
358
|
cc_email=cc_email_addr,
|
@@ -363,21 +377,37 @@ class Process_Category:
|
|
363
377
|
return responseMethod, parameters
|
364
378
|
|
365
379
|
def download_attachment(self, msg):
|
366
|
-
base_folder = "ORDERS" # Main folder for storing orders
|
367
|
-
today_date = datetime.today().strftime('%Y-%m-%d') # Format: YYYY-MM-DD
|
368
|
-
date_folder = os.path.join(base_folder, today_date) # Path: ORDERS/YYYY-MM-DD
|
369
|
-
|
370
|
-
# Ensure folders exist
|
371
|
-
os.makedirs(date_folder, exist_ok=True)
|
372
380
|
|
373
381
|
filename = ""
|
382
|
+
mime_type = ""
|
383
|
+
document_type = "Orders"
|
374
384
|
|
375
385
|
for part in msg.walk():
|
376
386
|
if part.get_content_maintype() == 'multipart':
|
377
387
|
continue
|
378
388
|
if part.get('Content-Disposition') is None:
|
379
389
|
continue
|
390
|
+
|
380
391
|
filename = part.get_filename()
|
392
|
+
mime_type = part.get_content_type().lower()
|
393
|
+
|
394
|
+
if "pdf" in mime_type:
|
395
|
+
document_type = "Orders"
|
396
|
+
elif "msword" in mime_type or "wordprocessingml" in mime_type or filename.endswith(".docx"):
|
397
|
+
document_type = "Order Excel"
|
398
|
+
elif "excel" in mime_type or "spreadsheetml" in mime_type or filename.endswith((".xls", ".xlsx")):
|
399
|
+
document_type = "Order Excel"
|
400
|
+
elif "csv" in mime_type or filename.endswith(".csv"):
|
401
|
+
document_type = "Order Excel"
|
402
|
+
elif "plain" in mime_type or filename.endswith(".txt"):
|
403
|
+
document_type = "Order Email"
|
404
|
+
elif "rtf" in mime_type or filename.endswith(".rtf"):
|
405
|
+
document_type = "Order Excel"
|
406
|
+
|
407
|
+
today_date = datetime.today().strftime('%Y-%m-%d') # Format: YYYY-MM-DD
|
408
|
+
date_folder = os.path.join(document_type, today_date) # Path: ORDERS/YYYY-MM-DD
|
409
|
+
os.makedirs(date_folder, exist_ok=True)
|
410
|
+
|
381
411
|
if filename:
|
382
412
|
filepath = os.path.join(date_folder, filename) # Save inside date-wise folder
|
383
413
|
|
@@ -386,10 +416,10 @@ class Process_Category:
|
|
386
416
|
logger.log(f"\nAttachment saved: '{filepath}'")
|
387
417
|
else:
|
388
418
|
logger.log("\nNo Attachment found.")
|
389
|
-
return filename
|
419
|
+
return filename, document_type
|
390
420
|
|
391
421
|
def create_file_from_emailBody(self, text, sender_email_addr, parameters):
|
392
|
-
base_folder =
|
422
|
+
base_folder = parameters.get('DOCUMENT_TYPE', '')
|
393
423
|
today_date = datetime.today().strftime('%Y-%m-%d') # Format: YYYY-MM-DD
|
394
424
|
order_folder = os.path.join(base_folder, today_date)
|
395
425
|
|
@@ -720,7 +750,7 @@ class Process_Category:
|
|
720
750
|
logger.log(f"Error with Gemini AI detection/generation: {str(e)}")
|
721
751
|
return {"success": "Failed", "message": f"Error with Gemini AI detection/generation: {str(e)}"}
|
722
752
|
|
723
|
-
def store_email_details_to_csv(self, email_id, to_email, from_email, cc_email, subject, body, email_type, action_performed, filename, user_id,status,response):
|
753
|
+
def store_email_details_to_csv(self, email_id, to_email, from_email, cc_email, subject, body, email_type, action_performed, filename, user_id,status,response,current_timestamp):
|
724
754
|
"""
|
725
755
|
Stores the extracted email details to a CSV file inside 'Mail_log/mail_log_user_id' folder
|
726
756
|
with the name user_id.csv.
|
@@ -734,9 +764,10 @@ class Process_Category:
|
|
734
764
|
user_folder = os.path.join(log_folder, f"{user_id}")
|
735
765
|
os.makedirs(user_folder, exist_ok=True)
|
736
766
|
|
767
|
+
filename = filename.lstrip()
|
768
|
+
logger.log(f"filename ::: [{filename}]")
|
737
769
|
full_csv_path = os.path.join(user_folder, f"{filename}.csv")
|
738
|
-
|
739
|
-
current_timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
770
|
+
logger.log(f"full_csv_path ::: {full_csv_path}")
|
740
771
|
|
741
772
|
# Prepare the data to write
|
742
773
|
csv_data = [{
|
@@ -786,6 +817,7 @@ class Process_Category:
|
|
786
817
|
user_folder = os.path.join(archive_folder, f"{user_id}")
|
787
818
|
os.makedirs(user_folder, exist_ok=True)
|
788
819
|
|
820
|
+
filename = filename.lstrip()
|
789
821
|
# Define the full path for the CSV file (csv_filename.csv inside the mail_log_user_id folder)
|
790
822
|
eml_file_path = os.path.join(user_folder, f"{filename}.eml")
|
791
823
|
|
@@ -820,5 +852,4 @@ class Process_Category:
|
|
820
852
|
if user_id:
|
821
853
|
return user_id.value
|
822
854
|
return None
|
823
|
-
|
824
|
-
|
855
|
+
|
{AIEmailAutomationUtility-0.0.23.dist-info → AIEmailAutomationUtility-0.0.25.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.25
|
4
|
+
Summary: Save attachment according to doctype
|
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
|
+
Save attachment according to doctype
|
@@ -0,0 +1,15 @@
|
|
1
|
+
AIEmailAutomationUtility/EmailReplyAssistant.py,sha256=oRobM6C1AwiRA3lQ2Sh51m-FaH2PpbUEidbkOG7O9Ww,6339
|
2
|
+
AIEmailAutomationUtility/Email_Classification.py,sha256=Ar0g4Ff8HOT7xICktd3nP_C_vCyeY-xCpUjVCVRWAyc,9417
|
3
|
+
AIEmailAutomationUtility/Email_DocumentUploader.py,sha256=YJu4tuTHr0K-5vuds9gZfj-Hwsgm4MuAOP39Lmu_t98,3219
|
4
|
+
AIEmailAutomationUtility/Email_Draft.py,sha256=DcyBeDaE8CReKHnHxLiz-o2tDxuUgwy91c4k0qhQbVw,7749
|
5
|
+
AIEmailAutomationUtility/Email_Read.py,sha256=UJDHdsr5RN_GG5OsOvUKbKziaw0a-kR3TT0iUv0oRmI,27795
|
6
|
+
AIEmailAutomationUtility/Email_Upload_Document.py,sha256=3bdkxfDlwoeRp-46KPw2Gs1dqBhEIoA1yE5GCudpdV8,1320
|
7
|
+
AIEmailAutomationUtility/Process_Category.py,sha256=fmcSdb-yfv1SgamNomTVFZ1m7RICRoTW7dGS4aa4wW0,41194
|
8
|
+
AIEmailAutomationUtility/Save_Draft.py,sha256=yzLgFN14I_lXE6qL0I3tKNduvcnWdbsY9i2mKdTtio4,5348
|
9
|
+
AIEmailAutomationUtility/Save_Transaction.py,sha256=Gg1w6hhzHmEFjsuzYvkq-3-EsWReetjLHsYSv5YIGgM,3816
|
10
|
+
AIEmailAutomationUtility/__init__.py,sha256=Jad3IdPRsVMeLqEEh-FbCrc1lE2tzJO2DTG5Hgmxh5g,391
|
11
|
+
AIEmailAutomationUtility-0.0.25.dist-info/LICENCE.txt,sha256=2qX9IkEUBx0VJp1Vh9O2dsRwE-IpYId0lXDyn7OVsJ8,1073
|
12
|
+
AIEmailAutomationUtility-0.0.25.dist-info/METADATA,sha256=wJMVGNyydAOlOVXUGd7AsB0ndMtZr_o9o5h-zrxP9fo,573
|
13
|
+
AIEmailAutomationUtility-0.0.25.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
14
|
+
AIEmailAutomationUtility-0.0.25.dist-info/top_level.txt,sha256=3jTWrTUblVkaP7mpwY2UBSnrlfot5Ykpfsehyke-Uzw,25
|
15
|
+
AIEmailAutomationUtility-0.0.25.dist-info/RECORD,,
|
@@ -1,15 +0,0 @@
|
|
1
|
-
AIEmailAutomationUtility/EmailReplyAssistant.py,sha256=oRobM6C1AwiRA3lQ2Sh51m-FaH2PpbUEidbkOG7O9Ww,6339
|
2
|
-
AIEmailAutomationUtility/Email_Classification.py,sha256=QvNNj8PSsfWoByBeHcaXH9mRET2TQuYGKJZGg385dzs,9412
|
3
|
-
AIEmailAutomationUtility/Email_DocumentUploader.py,sha256=P5P36rgDzALZEpO09aJWM0HEA-6vl48HNwz7GO6SbXc,3159
|
4
|
-
AIEmailAutomationUtility/Email_Draft.py,sha256=DcyBeDaE8CReKHnHxLiz-o2tDxuUgwy91c4k0qhQbVw,7749
|
5
|
-
AIEmailAutomationUtility/Email_Read.py,sha256=nG0Am3rw9-0HCvDqx290HdGkzgtfIQS5pI4r71vEZhc,27720
|
6
|
-
AIEmailAutomationUtility/Email_Upload_Document.py,sha256=3bdkxfDlwoeRp-46KPw2Gs1dqBhEIoA1yE5GCudpdV8,1320
|
7
|
-
AIEmailAutomationUtility/Process_Category.py,sha256=9GAocepaidmRRAcM_u5dczBMrY37aNu0jmduLfQIzHA,39208
|
8
|
-
AIEmailAutomationUtility/Save_Draft.py,sha256=yzLgFN14I_lXE6qL0I3tKNduvcnWdbsY9i2mKdTtio4,5348
|
9
|
-
AIEmailAutomationUtility/Save_Transaction.py,sha256=Gg1w6hhzHmEFjsuzYvkq-3-EsWReetjLHsYSv5YIGgM,3816
|
10
|
-
AIEmailAutomationUtility/__init__.py,sha256=Jad3IdPRsVMeLqEEh-FbCrc1lE2tzJO2DTG5Hgmxh5g,391
|
11
|
-
AIEmailAutomationUtility-0.0.23.dist-info/LICENCE.txt,sha256=2qX9IkEUBx0VJp1Vh9O2dsRwE-IpYId0lXDyn7OVsJ8,1073
|
12
|
-
AIEmailAutomationUtility-0.0.23.dist-info/METADATA,sha256=_quw7O_j8GwgnetwuN1Pz76prGXIfniA4UtOjF8iT4Q,551
|
13
|
-
AIEmailAutomationUtility-0.0.23.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
14
|
-
AIEmailAutomationUtility-0.0.23.dist-info/top_level.txt,sha256=3jTWrTUblVkaP7mpwY2UBSnrlfot5Ykpfsehyke-Uzw,25
|
15
|
-
AIEmailAutomationUtility-0.0.23.dist-info/RECORD,,
|
{AIEmailAutomationUtility-0.0.23.dist-info → AIEmailAutomationUtility-0.0.25.dist-info}/LICENCE.txt
RENAMED
File without changes
|
{AIEmailAutomationUtility-0.0.23.dist-info → AIEmailAutomationUtility-0.0.25.dist-info}/WHEEL
RENAMED
File without changes
|
File without changes
|