black shift

This commit is contained in:
2025-04-22 11:10:29 +03:00
parent d7f1da8de8
commit e5f88f2eb4
30 changed files with 671 additions and 521 deletions

View File

@@ -30,46 +30,46 @@ T = TypeVar("T")
class EmailProcessingContext:
"""Context manager for email processing that marks emails as unread if an error occurs."""
def __init__(self, email_message, mark_as_read: bool = True):
self.email_message = email_message
self.mark_as_read = mark_as_read
self.success = False
def __enter__(self):
return self
def __exit__(self, exc_type, exc_val, exc_tb):
if exc_type is not None or not self.success:
# If an exception occurred or processing wasn't successful, mark as unread
try:
if hasattr(self.email_message, 'mark_as_unread'):
if hasattr(self.email_message, "mark_as_unread"):
self.email_message.mark_as_unread()
print(f"[EMAIL_SERVICE] Marked email as UNREAD due to processing error: {exc_val if exc_val else 'Unknown error'}")
print(
f"[EMAIL_SERVICE] Marked email as UNREAD due to processing error: {exc_val if exc_val else 'Unknown error'}"
)
except Exception as e:
print(f"[EMAIL_SERVICE] Failed to mark email as unread: {str(e)}")
elif self.mark_as_read:
# If processing was successful and mark_as_read is True, ensure it's marked as read
try:
if hasattr(self.email_message, 'mark_as_read'):
if hasattr(self.email_message, "mark_as_read"):
self.email_message.mark_as_read()
except Exception as e:
print(f"[EMAIL_SERVICE] Failed to mark email as read: {str(e)}")
return False # Don't suppress exceptions
def publish_payload_to_redis(
payload, filename: str, mail_info: dict
) -> bool:
def publish_payload_to_redis(payload, filename: str, mail_info: dict) -> bool:
# Create message document
# Use base64 encoding for binary payloads to ensure proper transmission
if isinstance(payload, bytes):
encoded_payload = base64.b64encode(payload).decode('utf-8')
encoded_payload = base64.b64encode(payload).decode("utf-8")
is_base64 = True
else:
encoded_payload = payload
is_base64 = False
message = {
"filename": filename,
"payload": encoded_payload,
@@ -79,12 +79,14 @@ def publish_payload_to_redis(
"uuid": str(uuid4()), # Use UUID
**mail_info,
}
# Publish to Redis channel
result = redis_pubsub.publisher.publish(REDIS_CHANNEL, message)
if result.status:
print(f"[EMAIL_SERVICE] Published message with filename: {filename} to channel: {REDIS_CHANNEL}")
print(
f"[EMAIL_SERVICE] Published message with filename: {filename} to channel: {REDIS_CHANNEL}"
)
return True
else:
print(f"[EMAIL_SERVICE] Publish error: {result.error}")
@@ -126,7 +128,7 @@ def app():
port = Config.EMAIL_PORT
username = Config.EMAIL_USERNAME
password = Config.EMAIL_PASSWORD
box = EmailBox(host=host, port=port, username=username, password=password)
if not box:
return Exception("Mailbox not found")
@@ -136,41 +138,51 @@ def app():
filter_mail = OR(FROM(Config.MAILBOX), FROM(Config.MAIN_MAIL))
filter_print = f"{Config.MAILBOX} & {Config.MAIN_MAIL}"
# Determine if this is the first run of the day
# Determine if this is the first run of the day
# Store last run date in a file
last_run_file = "/tmp/email_service_last_run.json"
current_date = datetime.now().strftime("%Y-%m-%d")
days_to_check, full_check = 7, 90 # Default to 7 days
try:
if os.path.exists(last_run_file):
with open(last_run_file, 'r') as f:
with open(last_run_file, "r") as f:
last_run_data = json.load(f)
last_run_date = last_run_data.get('last_run_date')
last_run_date = last_run_data.get("last_run_date")
# If this is the first run of a new day, check 90 days
if last_run_date != current_date:
days_to_check = full_check
print(f"[EMAIL_SERVICE] First run of the day. Checking emails from the past {days_to_check} days")
print(
f"[EMAIL_SERVICE] First run of the day. Checking emails from the past {days_to_check} days"
)
else:
print(f"[EMAIL_SERVICE] Subsequent run today. Checking emails from the past {days_to_check} days")
print(
f"[EMAIL_SERVICE] Subsequent run today. Checking emails from the past {days_to_check} days"
)
else:
# If no last run file exists, this is the first run ever - check 90 days
days_to_check = full_check
print(f"[EMAIL_SERVICE] First run detected. Checking emails from the past {days_to_check} days")
print(
f"[EMAIL_SERVICE] First run detected. Checking emails from the past {days_to_check} days"
)
except Exception as e:
print(f"[EMAIL_SERVICE] Error reading last run file: {str(e)}. Using default of {days_to_check} days")
print(
f"[EMAIL_SERVICE] Error reading last run file: {str(e)}. Using default of {days_to_check} days"
)
# Update the last run file
try:
with open(last_run_file, 'w') as f:
json.dump({'last_run_date': current_date}, f)
with open(last_run_file, "w") as f:
json.dump({"last_run_date": current_date}, f)
except Exception as e:
print(f"[EMAIL_SERVICE] Error writing last run file: {str(e)}")
# Calculate the date to check from
check_since_date = (datetime.now() - timedelta(days=days_to_check)).strftime("%d-%b-%Y")
check_since_date = (datetime.now() - timedelta(days=days_to_check)).strftime(
"%d-%b-%Y"
)
for folder in mail_folders:
if folder.name == "INBOX":
# Search for emails since the calculated date
@@ -184,27 +196,33 @@ def app():
# Use context manager to handle errors and mark email as unread if needed
with EmailProcessingContext(banks_mail) as ctx:
try:
headers = {k.lower(): v for k, v in banks_mail.headers.items()}
headers = {
k.lower(): v for k, v in banks_mail.headers.items()
}
mail_info = {
"from": headers["from"],
"to": headers["to"],
"subject": headers["subject"],
"date": str(headers["date"]),
}
# Process the email and publish to Redis
success = read_email_and_publish_to_redis(
email_message=email_message, mail_info=mail_info
)
# Set success flag for the context manager
ctx.success = success
if success:
print(f"[EMAIL_SERVICE] Successfully processed email with subject: {mail_info['subject']}")
print(
f"[EMAIL_SERVICE] Successfully processed email with subject: {mail_info['subject']}"
)
else:
print(f"[EMAIL_SERVICE] No matching attachments found in email with subject: {mail_info['subject']}")
print(
f"[EMAIL_SERVICE] No matching attachments found in email with subject: {mail_info['subject']}"
)
except Exception as e:
print(f"[EMAIL_SERVICE] Error processing email: {str(e)}")
# The context manager will mark the email as unread
@@ -213,8 +231,8 @@ def app():
if __name__ == "__main__":
print("=== Starting Email Service with Redis Pub/Sub ===")
print(f"Publishing to channel: {REDIS_CHANNEL}")
time.sleep(20) # Wait for 20 seconds to other services to kick in
time.sleep(20) # Wait for 20 seconds to other services to kick in
while True:
print("\n[EMAIL_SERVICE] Checking for new emails...")
app()