AIEmailAutomationUtility 0.0.29__py3-none-any.whl → 0.0.31__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.
@@ -10,6 +10,11 @@ import json
10
10
  import os
11
11
  import csv
12
12
 
13
+ import io
14
+ import pandas as pd
15
+ import docx
16
+ import PyPDF2
17
+
13
18
  from .Save_Transaction import Save_Transaction
14
19
  from .Email_Classification import Email_Classification
15
20
  from .EmailReplyAssistant import EmailReplyAssistant
@@ -110,7 +115,9 @@ class Email_Read:
110
115
  file_JsonArray, categories = self.read_JSON_File(templateName)
111
116
 
112
117
  except Exception as e:
118
+ login_status = "Failed"
113
119
  logger.log(f"Login failed: {e}")
120
+ raise Exception(e)
114
121
 
115
122
  # Log the result
116
123
  self.log_email_login(user_id, reciever_email_addr, Model_Name, login_status)
@@ -248,6 +255,7 @@ class Email_Read:
248
255
 
249
256
  except Exception as e:
250
257
  logger.log(f"Login failed: {e}")
258
+ return f"Login failed: {e}"
251
259
 
252
260
  # Log the result
253
261
  self.log_email_login(user_id, reciever_email_addr, Model_Name, login_status)
@@ -294,7 +302,23 @@ class Email_Read:
294
302
 
295
303
  if content_type == "text/plain":
296
304
  email_body += part.get_payload(decode=True).decode('utf-8', errors='replace')
297
-
305
+
306
+
307
+ # For attachment
308
+ if msg.is_multipart():
309
+ for part in msg.walk():
310
+ content_disposition = str(part.get("Content-Disposition") or "")
311
+ content_type = part.get_content_type()
312
+ if "attachment" in content_disposition.lower():
313
+ filename = part.get_filename() or "attachment"
314
+ content_bytes = part.get_payload(decode=True)
315
+ if content_bytes:
316
+ extracted_content = self.Extract_attachment_content(filename, content_bytes)
317
+ extracted_content =f"\n\n--- The content of the attachment '{filename}' is below ---\n{extracted_content}\n"
318
+ # email_body += f"\n\n--- The content of the attachment '{filename}' is below ---\n{extracted_content}\n"
319
+ else:
320
+ extracted_content="NA"
321
+
298
322
  else:
299
323
  email_body = msg.get_payload(decode=True).decode('utf-8', errors='replace')
300
324
  content_type = msg.get_content_type()
@@ -348,7 +372,8 @@ class Email_Read:
348
372
  "uid": uid,
349
373
  "to_email_addr": to_email_addr,
350
374
  "user_id": user_id,
351
- "is_html": is_html
375
+ "is_html": is_html,
376
+ "extracted_content" : extracted_content
352
377
  }
353
378
  processcategory = Process_Category()
354
379
  processcategory.process_cat(emailCategory, dataValues)
@@ -573,5 +598,41 @@ class Email_Read:
573
598
  def read_status(self):
574
599
  global shared_status
575
600
  return shared_status
601
+
602
+ def Extract_attachment_content(self,filename, content_bytes):
603
+ extension = os.path.splitext(filename)[1].lower()
604
+
605
+ try:
606
+ if extension == ".pdf":
607
+ # Extract text from PDF
608
+ reader = PyPDF2.PdfReader(io.BytesIO(content_bytes))
609
+ text = "\n".join(page.extract_text() or "" for page in reader.pages)
610
+ return text if text.strip() else "[No text content found in PDF]"
611
+
612
+ elif extension in [".docx", ".doc"]:
613
+ # Extract text from Word document
614
+ doc = docx.Document(io.BytesIO(content_bytes))
615
+ text = "\n".join([para.text for para in doc.paragraphs])
616
+ return text if text.strip() else "[No text content found in Word document]"
617
+
618
+ elif extension in [".xls", ".xlsx"]:
619
+ # Extract text from Excel sheet
620
+ df = pd.read_excel(io.BytesIO(content_bytes), engine='openpyxl')
621
+ return df.to_string(index=False)
622
+
623
+ elif extension == ".csv":
624
+ # Extract text from CSV file
625
+ df = pd.read_csv(io.BytesIO(content_bytes))
626
+ return df.to_string(index=False)
627
+
628
+ elif extension in [".txt"]:
629
+ # Decode plain text file
630
+ return content_bytes.decode('utf-8', errors='replace')
631
+
632
+ else:
633
+ return "[Unsupported attachment type]"
634
+
635
+ except Exception as e:
636
+ return f"[Error extracting content: {str(e)}]"
576
637
 
577
638
 
@@ -161,13 +161,22 @@ class Process_Category:
161
161
  # Extract customer code once
162
162
  customer_code = customer_data.get("customer_code", "")
163
163
 
164
+
164
165
  # Step 5: Identify product from email using AI
165
- products = self.identify_products(email_body, subject, Model_Name, openai_api_key, geminiAI_APIKey, localAIURL, parameters["Product_Assistant_Id"])
166
+
167
+ #If there is attachment then append the content in the body.
168
+ extracted_content = dataValues.get('extracted_content')
169
+ if extracted_content != "NA":
170
+ attachment_email_body =email_body + " \n\n" + extracted_content
171
+ products = self.identify_products(attachment_email_body, subject, Model_Name, openai_api_key, geminiAI_APIKey, localAIURL, parameters["Product_Assistant_Id"])
172
+ else:
173
+ products = self.identify_products(email_body, subject, Model_Name, openai_api_key, geminiAI_APIKey, localAIURL, parameters["Product_Assistant_Id"])
174
+
166
175
  logger.log(f'Identified Products are ::: {products}')
167
176
 
168
177
  product_determination=products
169
178
 
170
- db_connection = sqlite3.connect('/home/base/git/ai-email-automation/AI_Email/database/fetchprice.db')
179
+ db_connection = sqlite3.connect('database/fetchprice.db')
171
180
  for product in products:
172
181
  item_no = product.get("item_no", "").strip()
173
182
  make = product.get("make", "").strip()
@@ -207,6 +216,8 @@ class Process_Category:
207
216
  else:
208
217
  logger.log(f"Process_Category - Quotation [0] No base price found for item '{item_no}' .")
209
218
  product["rate"] = "NA"
219
+ product["Price Pickup Source"]="NA"
220
+ product["Discount"]="NA"
210
221
  continue
211
222
 
212
223
  # Condition 1: Exact match in special_rate_customer_wise
@@ -226,6 +237,7 @@ class Process_Category:
226
237
  found_rate = True
227
238
  logger.log(f"Process_Category - Quotation [1] Special Rate for item '{item_no}' and customer '{customer_code}' is {rate}")
228
239
  price_pickup_source="SPECIAL_RATE_CUSTOMER_WISE"
240
+ Discount="NA"
229
241
 
230
242
  # Condition 2: Customer + Manufacturer discount
231
243
  if not found_rate:
@@ -241,6 +253,7 @@ class Process_Category:
241
253
 
242
254
  if discount_result:
243
255
  discount_percent = discount_result[0]
256
+ Discount= discount_percent
244
257
  rate = raw_price * (1 - int(discount_percent) / 100)
245
258
  rate = round(rate, 2)
246
259
  found_rate = True
@@ -265,6 +278,7 @@ class Process_Category:
265
278
 
266
279
  if past_sales_result:
267
280
  most_common_make, past_discount = past_sales_result
281
+ Discount=past_discount
268
282
  if isinstance(raw_price, (int, float)):
269
283
  rate = raw_price * (1 - int(past_discount) / 100)
270
284
  rate = round(rate, 2)
@@ -288,6 +302,7 @@ class Process_Category:
288
302
 
289
303
  if general_discount_result:
290
304
  general_discount_percent = general_discount_result[0]
305
+ Discount=general_discount_percent
291
306
  rate = raw_price * (1 - int(general_discount_percent) / 100)
292
307
  rate = round(rate, 2)
293
308
  found_rate = True
@@ -299,9 +314,11 @@ class Process_Category:
299
314
  rate = raw_price
300
315
  logger.log(f"Process_Category - Quotation [5] No discounts applied. Using base price for item '{item_no}': {rate}")
301
316
  price_pickup_source="PRICE_LIST"
317
+ Discount = "NA"
302
318
 
303
319
  product["rate"] = rate
304
320
  product["Price Pickup Source"]=price_pickup_source
321
+ product["Discount"]=Discount
305
322
 
306
323
  db_connection.close()
307
324
 
@@ -1,7 +1,7 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: AIEmailAutomationUtility
3
- Version: 0.0.29
4
- Summary: Set Bydefault document type as blank to avoid garbage data while uploading
3
+ Version: 0.0.31
4
+ Summary: If attachement in email download it and pass attachement file data to product identification service
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
- Set Bydefault document type as blank to avoid garbage data while uploading
16
+ If attachement in email download it and pass attachement file data to product identification service
@@ -2,14 +2,14 @@ AIEmailAutomationUtility/EmailReplyAssistant.py,sha256=R_wJna3-ITsVxQEccryhM93T_
2
2
  AIEmailAutomationUtility/Email_Classification.py,sha256=Ar0g4Ff8HOT7xICktd3nP_C_vCyeY-xCpUjVCVRWAyc,9417
3
3
  AIEmailAutomationUtility/Email_DocumentUploader.py,sha256=YJu4tuTHr0K-5vuds9gZfj-Hwsgm4MuAOP39Lmu_t98,3219
4
4
  AIEmailAutomationUtility/Email_Draft.py,sha256=DcyBeDaE8CReKHnHxLiz-o2tDxuUgwy91c4k0qhQbVw,7749
5
- AIEmailAutomationUtility/Email_Read.py,sha256=pRqc9295r_qqdfWIFJFG2XH9J-VlvO1E0yP3iv_cRV4,27802
5
+ AIEmailAutomationUtility/Email_Read.py,sha256=6obif-ZLhxuatNcGhO8en_R7-Q56EOhzeyILb8vZBjM,30743
6
6
  AIEmailAutomationUtility/Email_Upload_Document.py,sha256=3bdkxfDlwoeRp-46KPw2Gs1dqBhEIoA1yE5GCudpdV8,1320
7
- AIEmailAutomationUtility/Process_Category.py,sha256=PsOsZJ3ZVI6-h4YrvZZNl1MEXbV8u2OOnaOxWJafKOM,43789
7
+ AIEmailAutomationUtility/Process_Category.py,sha256=Rhs_flyv-_LvDzu6aO_i-ZDjnMKWDIP_mAcqf8mkl_Y,44607
8
8
  AIEmailAutomationUtility/Save_Draft.py,sha256=yzLgFN14I_lXE6qL0I3tKNduvcnWdbsY9i2mKdTtio4,5348
9
9
  AIEmailAutomationUtility/Save_Transaction.py,sha256=Gg1w6hhzHmEFjsuzYvkq-3-EsWReetjLHsYSv5YIGgM,3816
10
10
  AIEmailAutomationUtility/__init__.py,sha256=Jad3IdPRsVMeLqEEh-FbCrc1lE2tzJO2DTG5Hgmxh5g,391
11
- AIEmailAutomationUtility-0.0.29.dist-info/LICENCE.txt,sha256=2qX9IkEUBx0VJp1Vh9O2dsRwE-IpYId0lXDyn7OVsJ8,1073
12
- AIEmailAutomationUtility-0.0.29.dist-info/METADATA,sha256=mnluYbYahxvbznRwtqHnW4lDPhCl56lvNqgylhFluDU,649
13
- AIEmailAutomationUtility-0.0.29.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
14
- AIEmailAutomationUtility-0.0.29.dist-info/top_level.txt,sha256=3jTWrTUblVkaP7mpwY2UBSnrlfot5Ykpfsehyke-Uzw,25
15
- AIEmailAutomationUtility-0.0.29.dist-info/RECORD,,
11
+ AIEmailAutomationUtility-0.0.31.dist-info/LICENCE.txt,sha256=2qX9IkEUBx0VJp1Vh9O2dsRwE-IpYId0lXDyn7OVsJ8,1073
12
+ AIEmailAutomationUtility-0.0.31.dist-info/METADATA,sha256=E_KUzOjVXHaejQTsqUsfCZqLQYTWJQIFY4xUrZufw_o,701
13
+ AIEmailAutomationUtility-0.0.31.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
14
+ AIEmailAutomationUtility-0.0.31.dist-info/top_level.txt,sha256=3jTWrTUblVkaP7mpwY2UBSnrlfot5Ykpfsehyke-Uzw,25
15
+ AIEmailAutomationUtility-0.0.31.dist-info/RECORD,,